10b57cec5SDimitry Andric //===- ASTMatchersInternal.h - Structural query framework -------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implements the base layer of the matcher framework. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // Matchers are methods that return a Matcher<T> which provides a method 120b57cec5SDimitry Andric // Matches(...) which is a predicate on an AST node. The Matches method's 130b57cec5SDimitry Andric // parameters define the context of the match, which allows matchers to recurse 140b57cec5SDimitry Andric // or store the current node as bound to a specific string, so that it can be 150b57cec5SDimitry Andric // retrieved later. 160b57cec5SDimitry Andric // 170b57cec5SDimitry Andric // In general, matchers have two parts: 180b57cec5SDimitry Andric // 1. A function Matcher<T> MatcherName(<arguments>) which returns a Matcher<T> 190b57cec5SDimitry Andric // based on the arguments and optionally on template type deduction based 200b57cec5SDimitry Andric // on the arguments. Matcher<T>s form an implicit reverse hierarchy 210b57cec5SDimitry Andric // to clang's AST class hierarchy, meaning that you can use a Matcher<Base> 220b57cec5SDimitry Andric // everywhere a Matcher<Derived> is required. 230b57cec5SDimitry Andric // 2. An implementation of a class derived from MatcherInterface<T>. 240b57cec5SDimitry Andric // 250b57cec5SDimitry Andric // The matcher functions are defined in ASTMatchers.h. To make it possible 260b57cec5SDimitry Andric // to implement both the matcher function and the implementation of the matcher 270b57cec5SDimitry Andric // interface in one place, ASTMatcherMacros.h defines macros that allow 280b57cec5SDimitry Andric // implementing a matcher in a single place. 290b57cec5SDimitry Andric // 300b57cec5SDimitry Andric // This file contains the base classes needed to construct the actual matchers. 310b57cec5SDimitry Andric // 320b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H 350b57cec5SDimitry Andric #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #include "clang/AST/ASTTypeTraits.h" 380b57cec5SDimitry Andric #include "clang/AST/Decl.h" 390b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 400b57cec5SDimitry Andric #include "clang/AST/DeclFriend.h" 410b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 420b57cec5SDimitry Andric #include "clang/AST/Expr.h" 430b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 440b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 450b57cec5SDimitry Andric #include "clang/AST/NestedNameSpecifier.h" 460b57cec5SDimitry Andric #include "clang/AST/Stmt.h" 470b57cec5SDimitry Andric #include "clang/AST/TemplateName.h" 480b57cec5SDimitry Andric #include "clang/AST/Type.h" 490b57cec5SDimitry Andric #include "clang/AST/TypeLoc.h" 500b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 510b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.h" 520b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 530b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 540b57cec5SDimitry Andric #include "llvm/ADT/IntrusiveRefCntPtr.h" 550b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 560b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 570b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 580b57cec5SDimitry Andric #include "llvm/ADT/iterator.h" 590b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 600b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 615ffd83dbSDimitry Andric #include "llvm/Support/Regex.h" 620b57cec5SDimitry Andric #include <algorithm> 630b57cec5SDimitry Andric #include <cassert> 640b57cec5SDimitry Andric #include <cstddef> 650b57cec5SDimitry Andric #include <cstdint> 660b57cec5SDimitry Andric #include <map> 675ffd83dbSDimitry Andric #include <memory> 68bdd1243dSDimitry Andric #include <optional> 690b57cec5SDimitry Andric #include <string> 700b57cec5SDimitry Andric #include <tuple> 710b57cec5SDimitry Andric #include <type_traits> 720b57cec5SDimitry Andric #include <utility> 730b57cec5SDimitry Andric #include <vector> 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric namespace clang { 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric class ASTContext; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric namespace ast_matchers { 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric class BoundNodes; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric namespace internal { 840b57cec5SDimitry Andric 85fe6060f1SDimitry Andric /// A type-list implementation. 86fe6060f1SDimitry Andric /// 87fe6060f1SDimitry Andric /// A "linked list" of types, accessible by using the ::head and ::tail 88fe6060f1SDimitry Andric /// typedefs. 89fe6060f1SDimitry Andric template <typename... Ts> struct TypeList {}; // Empty sentinel type list. 90fe6060f1SDimitry Andric 91fe6060f1SDimitry Andric template <typename T1, typename... Ts> struct TypeList<T1, Ts...> { 92fe6060f1SDimitry Andric /// The first type on the list. 93fe6060f1SDimitry Andric using head = T1; 94fe6060f1SDimitry Andric 95fe6060f1SDimitry Andric /// A sublist with the tail. ie everything but the head. 96fe6060f1SDimitry Andric /// 97fe6060f1SDimitry Andric /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the 98fe6060f1SDimitry Andric /// end of the list. 99fe6060f1SDimitry Andric using tail = TypeList<Ts...>; 100fe6060f1SDimitry Andric }; 101fe6060f1SDimitry Andric 102fe6060f1SDimitry Andric /// The empty type list. 103fe6060f1SDimitry Andric using EmptyTypeList = TypeList<>; 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric /// Helper meta-function to determine if some type \c T is present or 106fe6060f1SDimitry Andric /// a parent type in the list. 107fe6060f1SDimitry Andric template <typename AnyTypeList, typename T> struct TypeListContainsSuperOf { 108fe6060f1SDimitry Andric static const bool value = 109fe6060f1SDimitry Andric std::is_base_of<typename AnyTypeList::head, T>::value || 110fe6060f1SDimitry Andric TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value; 111fe6060f1SDimitry Andric }; 112fe6060f1SDimitry Andric template <typename T> struct TypeListContainsSuperOf<EmptyTypeList, T> { 113fe6060f1SDimitry Andric static const bool value = false; 114fe6060f1SDimitry Andric }; 115fe6060f1SDimitry Andric 1160b57cec5SDimitry Andric /// Variadic function object. 1170b57cec5SDimitry Andric /// 1180b57cec5SDimitry Andric /// Most of the functions below that use VariadicFunction could be implemented 1190b57cec5SDimitry Andric /// using plain C++11 variadic functions, but the function object allows us to 1200b57cec5SDimitry Andric /// capture it on the dynamic matcher registry. 1210b57cec5SDimitry Andric template <typename ResultT, typename ArgT, 1220b57cec5SDimitry Andric ResultT (*Func)(ArrayRef<const ArgT *>)> 1230b57cec5SDimitry Andric struct VariadicFunction { 124bdd1243dSDimitry Andric ResultT operator()() const { return Func(std::nullopt); } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric template <typename... ArgsT> 1270b57cec5SDimitry Andric ResultT operator()(const ArgT &Arg1, const ArgsT &... Args) const { 1280b57cec5SDimitry Andric return Execute(Arg1, static_cast<const ArgT &>(Args)...); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric // We also allow calls with an already created array, in case the caller 1320b57cec5SDimitry Andric // already had it. 1330b57cec5SDimitry Andric ResultT operator()(ArrayRef<ArgT> Args) const { 13481ad6265SDimitry Andric return Func(llvm::to_vector<8>(llvm::make_pointer_range(Args))); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric private: 1380b57cec5SDimitry Andric // Trampoline function to allow for implicit conversions to take place 1390b57cec5SDimitry Andric // before we make the array. 1400b57cec5SDimitry Andric template <typename... ArgsT> ResultT Execute(const ArgsT &... Args) const { 1410b57cec5SDimitry Andric const ArgT *const ArgsArray[] = {&Args...}; 1420b57cec5SDimitry Andric return Func(ArrayRef<const ArgT *>(ArgsArray, sizeof...(ArgsT))); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric }; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric /// Unifies obtaining the underlying type of a regular node through 1470b57cec5SDimitry Andric /// `getType` and a TypedefNameDecl node through `getUnderlyingType`. 1480b57cec5SDimitry Andric inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric inline QualType getUnderlyingType(const ValueDecl &Node) { 1510b57cec5SDimitry Andric return Node.getType(); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric inline QualType getUnderlyingType(const TypedefNameDecl &Node) { 1540b57cec5SDimitry Andric return Node.getUnderlyingType(); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric inline QualType getUnderlyingType(const FriendDecl &Node) { 1570b57cec5SDimitry Andric if (const TypeSourceInfo *TSI = Node.getFriendType()) 1580b57cec5SDimitry Andric return TSI->getType(); 1590b57cec5SDimitry Andric return QualType(); 1600b57cec5SDimitry Andric } 1615ffd83dbSDimitry Andric inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) { 1625ffd83dbSDimitry Andric return Node.getType(); 1635ffd83dbSDimitry Andric } 1640b57cec5SDimitry Andric 165fe6060f1SDimitry Andric /// Unifies obtaining a `TypeSourceInfo` from different node types. 166fe6060f1SDimitry Andric template <typename T, 167fe6060f1SDimitry Andric std::enable_if_t<TypeListContainsSuperOf< 168fe6060f1SDimitry Andric TypeList<CXXBaseSpecifier, CXXCtorInitializer, 169fe6060f1SDimitry Andric CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr, 170fe6060f1SDimitry Andric CompoundLiteralExpr, DeclaratorDecl, ObjCPropertyDecl, 171fe6060f1SDimitry Andric TemplateArgumentLoc, TypedefNameDecl>, 172fe6060f1SDimitry Andric T>::value> * = nullptr> 173fe6060f1SDimitry Andric inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) { 174fe6060f1SDimitry Andric return Node.getTypeSourceInfo(); 175fe6060f1SDimitry Andric } 176fe6060f1SDimitry Andric template <typename T, 177fe6060f1SDimitry Andric std::enable_if_t<TypeListContainsSuperOf< 178fe6060f1SDimitry Andric TypeList<CXXFunctionalCastExpr, ExplicitCastExpr>, T>::value> * = 179fe6060f1SDimitry Andric nullptr> 180fe6060f1SDimitry Andric inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) { 181fe6060f1SDimitry Andric return Node.getTypeInfoAsWritten(); 182fe6060f1SDimitry Andric } 183fe6060f1SDimitry Andric inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) { 184fe6060f1SDimitry Andric return Node.getSignatureAsWritten(); 185fe6060f1SDimitry Andric } 186fe6060f1SDimitry Andric inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) { 187fe6060f1SDimitry Andric return Node.getAllocatedTypeSourceInfo(); 188fe6060f1SDimitry Andric } 189fe6060f1SDimitry Andric inline TypeSourceInfo * 190fe6060f1SDimitry Andric GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) { 191fe6060f1SDimitry Andric return Node.getTypeAsWritten(); 192fe6060f1SDimitry Andric } 193fe6060f1SDimitry Andric 1940b57cec5SDimitry Andric /// Unifies obtaining the FunctionProtoType pointer from both 1950b57cec5SDimitry Andric /// FunctionProtoType and FunctionDecl nodes.. 1960b57cec5SDimitry Andric inline const FunctionProtoType * 1970b57cec5SDimitry Andric getFunctionProtoType(const FunctionProtoType &Node) { 1980b57cec5SDimitry Andric return &Node; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) { 2020b57cec5SDimitry Andric return Node.getType()->getAs<FunctionProtoType>(); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2055ffd83dbSDimitry Andric /// Unifies obtaining the access specifier from Decl and CXXBaseSpecifier nodes. 2065ffd83dbSDimitry Andric inline clang::AccessSpecifier getAccessSpecifier(const Decl &Node) { 2075ffd83dbSDimitry Andric return Node.getAccess(); 2085ffd83dbSDimitry Andric } 2095ffd83dbSDimitry Andric 2105ffd83dbSDimitry Andric inline clang::AccessSpecifier getAccessSpecifier(const CXXBaseSpecifier &Node) { 2115ffd83dbSDimitry Andric return Node.getAccessSpecifier(); 2125ffd83dbSDimitry Andric } 2135ffd83dbSDimitry Andric 2140b57cec5SDimitry Andric /// Internal version of BoundNodes. Holds all the bound nodes. 2150b57cec5SDimitry Andric class BoundNodesMap { 2160b57cec5SDimitry Andric public: 2170b57cec5SDimitry Andric /// Adds \c Node to the map with key \c ID. 2180b57cec5SDimitry Andric /// 2190b57cec5SDimitry Andric /// The node's base type should be in NodeBaseType or it will be unaccessible. 2205ffd83dbSDimitry Andric void addNode(StringRef ID, const DynTypedNode &DynNode) { 2215ffd83dbSDimitry Andric NodeMap[std::string(ID)] = DynNode; 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric /// Returns the AST node bound to \c ID. 2250b57cec5SDimitry Andric /// 2260b57cec5SDimitry Andric /// Returns NULL if there was no node bound to \c ID or if there is a node but 2270b57cec5SDimitry Andric /// it cannot be converted to the specified type. 2280b57cec5SDimitry Andric template <typename T> 2290b57cec5SDimitry Andric const T *getNodeAs(StringRef ID) const { 2300b57cec5SDimitry Andric IDToNodeMap::const_iterator It = NodeMap.find(ID); 2310b57cec5SDimitry Andric if (It == NodeMap.end()) { 2320b57cec5SDimitry Andric return nullptr; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric return It->second.get<T>(); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2375ffd83dbSDimitry Andric DynTypedNode getNode(StringRef ID) const { 2380b57cec5SDimitry Andric IDToNodeMap::const_iterator It = NodeMap.find(ID); 2390b57cec5SDimitry Andric if (It == NodeMap.end()) { 2405ffd83dbSDimitry Andric return DynTypedNode(); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric return It->second; 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric /// Imposes an order on BoundNodesMaps. 2460b57cec5SDimitry Andric bool operator<(const BoundNodesMap &Other) const { 2470b57cec5SDimitry Andric return NodeMap < Other.NodeMap; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric /// A map from IDs to the bound nodes. 2510b57cec5SDimitry Andric /// 2520b57cec5SDimitry Andric /// Note that we're using std::map here, as for memoization: 2530b57cec5SDimitry Andric /// - we need a comparison operator 2540b57cec5SDimitry Andric /// - we need an assignment operator 2555ffd83dbSDimitry Andric using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>; 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric const IDToNodeMap &getMap() const { 2580b57cec5SDimitry Andric return NodeMap; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric /// Returns \c true if this \c BoundNodesMap can be compared, i.e. all 2620b57cec5SDimitry Andric /// stored nodes have memoization data. 2630b57cec5SDimitry Andric bool isComparable() const { 2640b57cec5SDimitry Andric for (const auto &IDAndNode : NodeMap) { 2650b57cec5SDimitry Andric if (!IDAndNode.second.getMemoizationData()) 2660b57cec5SDimitry Andric return false; 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric return true; 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric private: 2720b57cec5SDimitry Andric IDToNodeMap NodeMap; 2730b57cec5SDimitry Andric }; 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric /// Creates BoundNodesTree objects. 2760b57cec5SDimitry Andric /// 2770b57cec5SDimitry Andric /// The tree builder is used during the matching process to insert the bound 2780b57cec5SDimitry Andric /// nodes from the Id matcher. 2790b57cec5SDimitry Andric class BoundNodesTreeBuilder { 2800b57cec5SDimitry Andric public: 2810b57cec5SDimitry Andric /// A visitor interface to visit all BoundNodes results for a 2820b57cec5SDimitry Andric /// BoundNodesTree. 2830b57cec5SDimitry Andric class Visitor { 2840b57cec5SDimitry Andric public: 2850b57cec5SDimitry Andric virtual ~Visitor() = default; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric /// Called multiple times during a single call to VisitMatches(...). 2880b57cec5SDimitry Andric /// 2890b57cec5SDimitry Andric /// 'BoundNodesView' contains the bound nodes for a single match. 2900b57cec5SDimitry Andric virtual void visitMatch(const BoundNodes& BoundNodesView) = 0; 2910b57cec5SDimitry Andric }; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric /// Add a binding from an id to a node. 2945ffd83dbSDimitry Andric void setBinding(StringRef Id, const DynTypedNode &DynNode) { 2950b57cec5SDimitry Andric if (Bindings.empty()) 2960b57cec5SDimitry Andric Bindings.emplace_back(); 2970b57cec5SDimitry Andric for (BoundNodesMap &Binding : Bindings) 2980b57cec5SDimitry Andric Binding.addNode(Id, DynNode); 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric /// Adds a branch in the tree. 3020b57cec5SDimitry Andric void addMatch(const BoundNodesTreeBuilder &Bindings); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric /// Visits all matches that this BoundNodesTree represents. 3050b57cec5SDimitry Andric /// 3060b57cec5SDimitry Andric /// The ownership of 'ResultVisitor' remains at the caller. 3070b57cec5SDimitry Andric void visitMatches(Visitor* ResultVisitor); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric template <typename ExcludePredicate> 3100b57cec5SDimitry Andric bool removeBindings(const ExcludePredicate &Predicate) { 311349cc55cSDimitry Andric llvm::erase_if(Bindings, Predicate); 3120b57cec5SDimitry Andric return !Bindings.empty(); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric /// Imposes an order on BoundNodesTreeBuilders. 3160b57cec5SDimitry Andric bool operator<(const BoundNodesTreeBuilder &Other) const { 3170b57cec5SDimitry Andric return Bindings < Other.Bindings; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric /// Returns \c true if this \c BoundNodesTreeBuilder can be compared, 3210b57cec5SDimitry Andric /// i.e. all stored node maps have memoization data. 3220b57cec5SDimitry Andric bool isComparable() const { 3230b57cec5SDimitry Andric for (const BoundNodesMap &NodesMap : Bindings) { 3240b57cec5SDimitry Andric if (!NodesMap.isComparable()) 3250b57cec5SDimitry Andric return false; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric return true; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric private: 3310b57cec5SDimitry Andric SmallVector<BoundNodesMap, 1> Bindings; 3320b57cec5SDimitry Andric }; 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric class ASTMatchFinder; 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric /// Generic interface for all matchers. 3370b57cec5SDimitry Andric /// 3380b57cec5SDimitry Andric /// Used by the implementation of Matcher<T> and DynTypedMatcher. 3390b57cec5SDimitry Andric /// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T> 3400b57cec5SDimitry Andric /// instead. 3410b57cec5SDimitry Andric class DynMatcherInterface 3420b57cec5SDimitry Andric : public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> { 3430b57cec5SDimitry Andric public: 3440b57cec5SDimitry Andric virtual ~DynMatcherInterface() = default; 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric /// Returns true if \p DynNode can be matched. 3470b57cec5SDimitry Andric /// 3480b57cec5SDimitry Andric /// May bind \p DynNode to an ID via \p Builder, or recurse into 3490b57cec5SDimitry Andric /// the AST via \p Finder. 3505ffd83dbSDimitry Andric virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, 3510b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const = 0; 352480093f4SDimitry Andric 353bdd1243dSDimitry Andric virtual std::optional<clang::TraversalKind> TraversalKind() const { 354bdd1243dSDimitry Andric return std::nullopt; 355480093f4SDimitry Andric } 3560b57cec5SDimitry Andric }; 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric /// Generic interface for matchers on an AST node of type T. 3590b57cec5SDimitry Andric /// 3600b57cec5SDimitry Andric /// Implement this if your matcher may need to inspect the children or 3610b57cec5SDimitry Andric /// descendants of the node or bind matched nodes to names. If you are 3620b57cec5SDimitry Andric /// writing a simple matcher that only inspects properties of the 3630b57cec5SDimitry Andric /// current node and doesn't care about its children or descendants, 3640b57cec5SDimitry Andric /// implement SingleNodeMatcherInterface instead. 3650b57cec5SDimitry Andric template <typename T> 3660b57cec5SDimitry Andric class MatcherInterface : public DynMatcherInterface { 3670b57cec5SDimitry Andric public: 3680b57cec5SDimitry Andric /// Returns true if 'Node' can be matched. 3690b57cec5SDimitry Andric /// 3700b57cec5SDimitry Andric /// May bind 'Node' to an ID via 'Builder', or recurse into 3710b57cec5SDimitry Andric /// the AST via 'Finder'. 3720b57cec5SDimitry Andric virtual bool matches(const T &Node, 3730b57cec5SDimitry Andric ASTMatchFinder *Finder, 3740b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const = 0; 3750b57cec5SDimitry Andric 3765ffd83dbSDimitry Andric bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, 3770b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 3780b57cec5SDimitry Andric return matches(DynNode.getUnchecked<T>(), Finder, Builder); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric }; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric /// Interface for matchers that only evaluate properties on a single 3830b57cec5SDimitry Andric /// node. 3840b57cec5SDimitry Andric template <typename T> 3850b57cec5SDimitry Andric class SingleNodeMatcherInterface : public MatcherInterface<T> { 3860b57cec5SDimitry Andric public: 3870b57cec5SDimitry Andric /// Returns true if the matcher matches the provided node. 3880b57cec5SDimitry Andric /// 3890b57cec5SDimitry Andric /// A subclass must implement this instead of Matches(). 3900b57cec5SDimitry Andric virtual bool matchesNode(const T &Node) const = 0; 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric private: 3930b57cec5SDimitry Andric /// Implements MatcherInterface::Matches. 3940b57cec5SDimitry Andric bool matches(const T &Node, 3950b57cec5SDimitry Andric ASTMatchFinder * /* Finder */, 3960b57cec5SDimitry Andric BoundNodesTreeBuilder * /* Builder */) const override { 3970b57cec5SDimitry Andric return matchesNode(Node); 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric }; 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric template <typename> class Matcher; 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric /// Matcher that works on a \c DynTypedNode. 4040b57cec5SDimitry Andric /// 4050b57cec5SDimitry Andric /// It is constructed from a \c Matcher<T> object and redirects most calls to 4060b57cec5SDimitry Andric /// underlying matcher. 4070b57cec5SDimitry Andric /// It checks whether the \c DynTypedNode is convertible into the type of the 4080b57cec5SDimitry Andric /// underlying matcher and then do the actual match on the actual node, or 4090b57cec5SDimitry Andric /// return false if it is not convertible. 4100b57cec5SDimitry Andric class DynTypedMatcher { 4110b57cec5SDimitry Andric public: 4120b57cec5SDimitry Andric /// Takes ownership of the provided implementation pointer. 4130b57cec5SDimitry Andric template <typename T> 4140b57cec5SDimitry Andric DynTypedMatcher(MatcherInterface<T> *Implementation) 4155ffd83dbSDimitry Andric : SupportedKind(ASTNodeKind::getFromNodeKind<T>()), 4160b57cec5SDimitry Andric RestrictKind(SupportedKind), Implementation(Implementation) {} 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric /// Construct from a variadic function. 4190b57cec5SDimitry Andric enum VariadicOperator { 4200b57cec5SDimitry Andric /// Matches nodes for which all provided matchers match. 4210b57cec5SDimitry Andric VO_AllOf, 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric /// Matches nodes for which at least one of the provided matchers 4240b57cec5SDimitry Andric /// matches. 4250b57cec5SDimitry Andric VO_AnyOf, 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric /// Matches nodes for which at least one of the provided matchers 4280b57cec5SDimitry Andric /// matches, but doesn't stop at the first match. 4290b57cec5SDimitry Andric VO_EachOf, 4300b57cec5SDimitry Andric 431480093f4SDimitry Andric /// Matches any node but executes all inner matchers to find result 432480093f4SDimitry Andric /// bindings. 433480093f4SDimitry Andric VO_Optionally, 434480093f4SDimitry Andric 4350b57cec5SDimitry Andric /// Matches nodes that do not match the provided matcher. 4360b57cec5SDimitry Andric /// 4370b57cec5SDimitry Andric /// Uses the variadic matcher interface, but fails if 4380b57cec5SDimitry Andric /// InnerMatchers.size() != 1. 4390b57cec5SDimitry Andric VO_UnaryNot 4400b57cec5SDimitry Andric }; 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric static DynTypedMatcher 4435ffd83dbSDimitry Andric constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind, 4440b57cec5SDimitry Andric std::vector<DynTypedMatcher> InnerMatchers); 4450b57cec5SDimitry Andric 446480093f4SDimitry Andric static DynTypedMatcher 447480093f4SDimitry Andric constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher, 4485ffd83dbSDimitry Andric ASTNodeKind RestrictKind); 449480093f4SDimitry Andric 4500b57cec5SDimitry Andric /// Get a "true" matcher for \p NodeKind. 4510b57cec5SDimitry Andric /// 4520b57cec5SDimitry Andric /// It only checks that the node is of the right kind. 4535ffd83dbSDimitry Andric static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind); 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric void setAllowBind(bool AB) { AllowBind = AB; } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric /// Check whether this matcher could ever match a node of kind \p Kind. 4580b57cec5SDimitry Andric /// \return \c false if this matcher will never match such a node. Otherwise, 4590b57cec5SDimitry Andric /// return \c true. 4605ffd83dbSDimitry Andric bool canMatchNodesOfKind(ASTNodeKind Kind) const; 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric /// Return a matcher that points to the same implementation, but 4630b57cec5SDimitry Andric /// restricts the node types for \p Kind. 4645ffd83dbSDimitry Andric DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const; 4655ffd83dbSDimitry Andric 466bdd1243dSDimitry Andric /// Return a matcher that points to the same implementation, but sets the 4675ffd83dbSDimitry Andric /// traversal kind. 4685ffd83dbSDimitry Andric /// 4695ffd83dbSDimitry Andric /// If the traversal kind is already set, then \c TK overrides it. 4705ffd83dbSDimitry Andric DynTypedMatcher withTraversalKind(TraversalKind TK); 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric /// Returns true if the matcher matches the given \c DynNode. 4735ffd83dbSDimitry Andric bool matches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, 4745ffd83dbSDimitry Andric BoundNodesTreeBuilder *Builder) const; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric /// Same as matches(), but skips the kind check. 4770b57cec5SDimitry Andric /// 4780b57cec5SDimitry Andric /// It is faster, but the caller must ensure the node is valid for the 4790b57cec5SDimitry Andric /// kind of this matcher. 4805ffd83dbSDimitry Andric bool matchesNoKindCheck(const DynTypedNode &DynNode, ASTMatchFinder *Finder, 4810b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const; 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric /// Bind the specified \p ID to the matcher. 4840b57cec5SDimitry Andric /// \return A new matcher with the \p ID bound to it if this matcher supports 485bdd1243dSDimitry Andric /// binding. Otherwise, returns an empty \c std::optional<>. 486bdd1243dSDimitry Andric std::optional<DynTypedMatcher> tryBind(StringRef ID) const; 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric /// Returns a unique \p ID for the matcher. 4890b57cec5SDimitry Andric /// 4900b57cec5SDimitry Andric /// Casting a Matcher<T> to Matcher<U> creates a matcher that has the 4910b57cec5SDimitry Andric /// same \c Implementation pointer, but different \c RestrictKind. We need to 4920b57cec5SDimitry Andric /// include both in the ID to make it unique. 4930b57cec5SDimitry Andric /// 4940b57cec5SDimitry Andric /// \c MatcherIDType supports operator< and provides strict weak ordering. 4955ffd83dbSDimitry Andric using MatcherIDType = std::pair<ASTNodeKind, uint64_t>; 4960b57cec5SDimitry Andric MatcherIDType getID() const { 4970b57cec5SDimitry Andric /// FIXME: Document the requirements this imposes on matcher 4980b57cec5SDimitry Andric /// implementations (no new() implementation_ during a Matches()). 4990b57cec5SDimitry Andric return std::make_pair(RestrictKind, 5000b57cec5SDimitry Andric reinterpret_cast<uint64_t>(Implementation.get())); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric /// Returns the type this matcher works on. 5040b57cec5SDimitry Andric /// 5050b57cec5SDimitry Andric /// \c matches() will always return false unless the node passed is of this 5060b57cec5SDimitry Andric /// or a derived type. 5075ffd83dbSDimitry Andric ASTNodeKind getSupportedKind() const { return SupportedKind; } 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric /// Returns \c true if the passed \c DynTypedMatcher can be converted 5100b57cec5SDimitry Andric /// to a \c Matcher<T>. 5110b57cec5SDimitry Andric /// 5120b57cec5SDimitry Andric /// This method verifies that the underlying matcher in \c Other can process 5130b57cec5SDimitry Andric /// nodes of types T. 5140b57cec5SDimitry Andric template <typename T> bool canConvertTo() const { 5155ffd83dbSDimitry Andric return canConvertTo(ASTNodeKind::getFromNodeKind<T>()); 5160b57cec5SDimitry Andric } 5175ffd83dbSDimitry Andric bool canConvertTo(ASTNodeKind To) const; 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric /// Construct a \c Matcher<T> interface around the dynamic matcher. 5200b57cec5SDimitry Andric /// 5210b57cec5SDimitry Andric /// This method asserts that \c canConvertTo() is \c true. Callers 5220b57cec5SDimitry Andric /// should call \c canConvertTo() first to make sure that \c this is 5230b57cec5SDimitry Andric /// compatible with T. 5240b57cec5SDimitry Andric template <typename T> Matcher<T> convertTo() const { 5250b57cec5SDimitry Andric assert(canConvertTo<T>()); 5260b57cec5SDimitry Andric return unconditionalConvertTo<T>(); 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric /// Same as \c convertTo(), but does not check that the underlying 5300b57cec5SDimitry Andric /// matcher can handle a value of T. 5310b57cec5SDimitry Andric /// 5320b57cec5SDimitry Andric /// If it is not compatible, then this matcher will never match anything. 5330b57cec5SDimitry Andric template <typename T> Matcher<T> unconditionalConvertTo() const; 5340b57cec5SDimitry Andric 5355ffd83dbSDimitry Andric /// Returns the \c TraversalKind respected by calls to `match()`, if any. 5365ffd83dbSDimitry Andric /// 5375ffd83dbSDimitry Andric /// Most matchers will not have a traversal kind set, instead relying on the 538bdd1243dSDimitry Andric /// surrounding context. For those, \c std::nullopt is returned. 539bdd1243dSDimitry Andric std::optional<clang::TraversalKind> getTraversalKind() const { 5405ffd83dbSDimitry Andric return Implementation->TraversalKind(); 5415ffd83dbSDimitry Andric } 5425ffd83dbSDimitry Andric 5430b57cec5SDimitry Andric private: 5445ffd83dbSDimitry Andric DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind, 5450b57cec5SDimitry Andric IntrusiveRefCntPtr<DynMatcherInterface> Implementation) 5460b57cec5SDimitry Andric : SupportedKind(SupportedKind), RestrictKind(RestrictKind), 5470b57cec5SDimitry Andric Implementation(std::move(Implementation)) {} 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric bool AllowBind = false; 5505ffd83dbSDimitry Andric ASTNodeKind SupportedKind; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric /// A potentially stricter node kind. 5530b57cec5SDimitry Andric /// 5540b57cec5SDimitry Andric /// It allows to perform implicit and dynamic cast of matchers without 5550b57cec5SDimitry Andric /// needing to change \c Implementation. 5565ffd83dbSDimitry Andric ASTNodeKind RestrictKind; 5570b57cec5SDimitry Andric IntrusiveRefCntPtr<DynMatcherInterface> Implementation; 5580b57cec5SDimitry Andric }; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric /// Wrapper of a MatcherInterface<T> *that allows copying. 5610b57cec5SDimitry Andric /// 5620b57cec5SDimitry Andric /// A Matcher<Base> can be used anywhere a Matcher<Derived> is 5630b57cec5SDimitry Andric /// required. This establishes an is-a relationship which is reverse 5640b57cec5SDimitry Andric /// to the AST hierarchy. In other words, Matcher<T> is contravariant 5650b57cec5SDimitry Andric /// with respect to T. The relationship is built via a type conversion 5660b57cec5SDimitry Andric /// operator rather than a type hierarchy to be able to templatize the 5670b57cec5SDimitry Andric /// type hierarchy instead of spelling it out. 5680b57cec5SDimitry Andric template <typename T> 5690b57cec5SDimitry Andric class Matcher { 5700b57cec5SDimitry Andric public: 5710b57cec5SDimitry Andric /// Takes ownership of the provided implementation pointer. 5720b57cec5SDimitry Andric explicit Matcher(MatcherInterface<T> *Implementation) 5730b57cec5SDimitry Andric : Implementation(Implementation) {} 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric /// Implicitly converts \c Other to a Matcher<T>. 5760b57cec5SDimitry Andric /// 5770b57cec5SDimitry Andric /// Requires \c T to be derived from \c From. 5780b57cec5SDimitry Andric template <typename From> 5790b57cec5SDimitry Andric Matcher(const Matcher<From> &Other, 5805ffd83dbSDimitry Andric std::enable_if_t<std::is_base_of<From, T>::value && 5815ffd83dbSDimitry Andric !std::is_same<From, T>::value> * = nullptr) 5820b57cec5SDimitry Andric : Implementation(restrictMatcher(Other.Implementation)) { 5830b57cec5SDimitry Andric assert(Implementation.getSupportedKind().isSame( 5845ffd83dbSDimitry Andric ASTNodeKind::getFromNodeKind<T>())); 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric /// Implicitly converts \c Matcher<Type> to \c Matcher<QualType>. 5880b57cec5SDimitry Andric /// 5890b57cec5SDimitry Andric /// The resulting matcher is not strict, i.e. ignores qualifiers. 5900b57cec5SDimitry Andric template <typename TypeT> 5910b57cec5SDimitry Andric Matcher(const Matcher<TypeT> &Other, 5925ffd83dbSDimitry Andric std::enable_if_t<std::is_same<T, QualType>::value && 5935ffd83dbSDimitry Andric std::is_same<TypeT, Type>::value> * = nullptr) 5940b57cec5SDimitry Andric : Implementation(new TypeToQualType<TypeT>(Other)) {} 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric /// Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the 5970b57cec5SDimitry Andric /// argument. 5980b57cec5SDimitry Andric /// \c To must be a base class of \c T. 59981ad6265SDimitry Andric template <typename To> Matcher<To> dynCastTo() const & { 6000b57cec5SDimitry Andric static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call."); 6010b57cec5SDimitry Andric return Matcher<To>(Implementation); 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 604fe6060f1SDimitry Andric template <typename To> Matcher<To> dynCastTo() && { 605fe6060f1SDimitry Andric static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call."); 606fe6060f1SDimitry Andric return Matcher<To>(std::move(Implementation)); 607fe6060f1SDimitry Andric } 608fe6060f1SDimitry Andric 6090b57cec5SDimitry Andric /// Forwards the call to the underlying MatcherInterface<T> pointer. 6100b57cec5SDimitry Andric bool matches(const T &Node, 6110b57cec5SDimitry Andric ASTMatchFinder *Finder, 6120b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 6135ffd83dbSDimitry Andric return Implementation.matches(DynTypedNode::create(Node), Finder, Builder); 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric /// Returns an ID that uniquely identifies the matcher. 6170b57cec5SDimitry Andric DynTypedMatcher::MatcherIDType getID() const { 6180b57cec5SDimitry Andric return Implementation.getID(); 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric /// Extract the dynamic matcher. 6220b57cec5SDimitry Andric /// 6230b57cec5SDimitry Andric /// The returned matcher keeps the same restrictions as \c this and remembers 6240b57cec5SDimitry Andric /// that it is meant to support nodes of type \c T. 62581ad6265SDimitry Andric operator DynTypedMatcher() const & { return Implementation; } 626fe6060f1SDimitry Andric 627fe6060f1SDimitry Andric operator DynTypedMatcher() && { return std::move(Implementation); } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric /// Allows the conversion of a \c Matcher<Type> to a \c 6300b57cec5SDimitry Andric /// Matcher<QualType>. 6310b57cec5SDimitry Andric /// 6320b57cec5SDimitry Andric /// Depending on the constructor argument, the matcher is either strict, i.e. 6330b57cec5SDimitry Andric /// does only matches in the absence of qualifiers, or not, i.e. simply 6340b57cec5SDimitry Andric /// ignores any qualifiers. 6350b57cec5SDimitry Andric template <typename TypeT> 6365ffd83dbSDimitry Andric class TypeToQualType : public MatcherInterface<QualType> { 6375ffd83dbSDimitry Andric const DynTypedMatcher InnerMatcher; 6385ffd83dbSDimitry Andric 6390b57cec5SDimitry Andric public: 6400b57cec5SDimitry Andric TypeToQualType(const Matcher<TypeT> &InnerMatcher) 6415ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher) {} 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric bool matches(const QualType &Node, ASTMatchFinder *Finder, 6440b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 6450b57cec5SDimitry Andric if (Node.isNull()) 6460b57cec5SDimitry Andric return false; 6475ffd83dbSDimitry Andric return this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder, 6485ffd83dbSDimitry Andric Builder); 6490b57cec5SDimitry Andric } 650e8d8bef9SDimitry Andric 651bdd1243dSDimitry Andric std::optional<clang::TraversalKind> TraversalKind() const override { 652e8d8bef9SDimitry Andric return this->InnerMatcher.getTraversalKind(); 653e8d8bef9SDimitry Andric } 6540b57cec5SDimitry Andric }; 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric private: 6570b57cec5SDimitry Andric // For Matcher<T> <=> Matcher<U> conversions. 6580b57cec5SDimitry Andric template <typename U> friend class Matcher; 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric // For DynTypedMatcher::unconditionalConvertTo<T>. 6610b57cec5SDimitry Andric friend class DynTypedMatcher; 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) { 6645ffd83dbSDimitry Andric return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>()); 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric explicit Matcher(const DynTypedMatcher &Implementation) 6680b57cec5SDimitry Andric : Implementation(restrictMatcher(Implementation)) { 6695ffd83dbSDimitry Andric assert(this->Implementation.getSupportedKind().isSame( 6705ffd83dbSDimitry Andric ASTNodeKind::getFromNodeKind<T>())); 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric DynTypedMatcher Implementation; 6740b57cec5SDimitry Andric }; // class Matcher 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric /// A convenient helper for creating a Matcher<T> without specifying 6770b57cec5SDimitry Andric /// the template type argument. 6780b57cec5SDimitry Andric template <typename T> 6790b57cec5SDimitry Andric inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) { 6800b57cec5SDimitry Andric return Matcher<T>(Implementation); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 683e8d8bef9SDimitry Andric /// Interface that allows matchers to traverse the AST. 684e8d8bef9SDimitry Andric /// FIXME: Find a better name. 685e8d8bef9SDimitry Andric /// 686e8d8bef9SDimitry Andric /// This provides three entry methods for each base node type in the AST: 687e8d8bef9SDimitry Andric /// - \c matchesChildOf: 688e8d8bef9SDimitry Andric /// Matches a matcher on every child node of the given node. Returns true 689e8d8bef9SDimitry Andric /// if at least one child node could be matched. 690e8d8bef9SDimitry Andric /// - \c matchesDescendantOf: 691e8d8bef9SDimitry Andric /// Matches a matcher on all descendant nodes of the given node. Returns true 692e8d8bef9SDimitry Andric /// if at least one descendant matched. 693e8d8bef9SDimitry Andric /// - \c matchesAncestorOf: 694e8d8bef9SDimitry Andric /// Matches a matcher on all ancestors of the given node. Returns true if 695e8d8bef9SDimitry Andric /// at least one ancestor matched. 696e8d8bef9SDimitry Andric /// 697e8d8bef9SDimitry Andric /// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal. 698e8d8bef9SDimitry Andric /// In the future, we want to implement this for all nodes for which it makes 699e8d8bef9SDimitry Andric /// sense. In the case of matchesAncestorOf, we'll want to implement it for 700e8d8bef9SDimitry Andric /// all nodes, as all nodes have ancestors. 701e8d8bef9SDimitry Andric class ASTMatchFinder { 702e8d8bef9SDimitry Andric public: 703e8d8bef9SDimitry Andric /// Defines how bindings are processed on recursive matches. 704e8d8bef9SDimitry Andric enum BindKind { 705e8d8bef9SDimitry Andric /// Stop at the first match and only bind the first match. 706e8d8bef9SDimitry Andric BK_First, 707e8d8bef9SDimitry Andric 708e8d8bef9SDimitry Andric /// Create results for all combinations of bindings that match. 709e8d8bef9SDimitry Andric BK_All 710e8d8bef9SDimitry Andric }; 711e8d8bef9SDimitry Andric 712e8d8bef9SDimitry Andric /// Defines which ancestors are considered for a match. 713e8d8bef9SDimitry Andric enum AncestorMatchMode { 714e8d8bef9SDimitry Andric /// All ancestors. 715e8d8bef9SDimitry Andric AMM_All, 716e8d8bef9SDimitry Andric 717e8d8bef9SDimitry Andric /// Direct parent only. 718e8d8bef9SDimitry Andric AMM_ParentOnly 719e8d8bef9SDimitry Andric }; 720e8d8bef9SDimitry Andric 721e8d8bef9SDimitry Andric virtual ~ASTMatchFinder() = default; 722e8d8bef9SDimitry Andric 723e8d8bef9SDimitry Andric /// Returns true if the given C++ class is directly or indirectly derived 724e8d8bef9SDimitry Andric /// from a base type matching \c base. 725e8d8bef9SDimitry Andric /// 726e8d8bef9SDimitry Andric /// A class is not considered to be derived from itself. 727e8d8bef9SDimitry Andric virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration, 728e8d8bef9SDimitry Andric const Matcher<NamedDecl> &Base, 729e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, 730e8d8bef9SDimitry Andric bool Directly) = 0; 731e8d8bef9SDimitry Andric 732e8d8bef9SDimitry Andric /// Returns true if the given Objective-C class is directly or indirectly 733e8d8bef9SDimitry Andric /// derived from a base class matching \c base. 734e8d8bef9SDimitry Andric /// 735e8d8bef9SDimitry Andric /// A class is not considered to be derived from itself. 736e8d8bef9SDimitry Andric virtual bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration, 737e8d8bef9SDimitry Andric const Matcher<NamedDecl> &Base, 738e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, 739e8d8bef9SDimitry Andric bool Directly) = 0; 740e8d8bef9SDimitry Andric 741e8d8bef9SDimitry Andric template <typename T> 742e8d8bef9SDimitry Andric bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher, 743e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, BindKind Bind) { 744e8d8bef9SDimitry Andric static_assert(std::is_base_of<Decl, T>::value || 745e8d8bef9SDimitry Andric std::is_base_of<Stmt, T>::value || 746e8d8bef9SDimitry Andric std::is_base_of<NestedNameSpecifier, T>::value || 747e8d8bef9SDimitry Andric std::is_base_of<NestedNameSpecifierLoc, T>::value || 748e8d8bef9SDimitry Andric std::is_base_of<TypeLoc, T>::value || 749349cc55cSDimitry Andric std::is_base_of<QualType, T>::value || 750349cc55cSDimitry Andric std::is_base_of<Attr, T>::value, 751e8d8bef9SDimitry Andric "unsupported type for recursive matching"); 752e8d8bef9SDimitry Andric return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher, 753e8d8bef9SDimitry Andric Builder, Bind); 754e8d8bef9SDimitry Andric } 755e8d8bef9SDimitry Andric 756e8d8bef9SDimitry Andric template <typename T> 757e8d8bef9SDimitry Andric bool matchesDescendantOf(const T &Node, const DynTypedMatcher &Matcher, 758e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, BindKind Bind) { 759e8d8bef9SDimitry Andric static_assert(std::is_base_of<Decl, T>::value || 760e8d8bef9SDimitry Andric std::is_base_of<Stmt, T>::value || 761e8d8bef9SDimitry Andric std::is_base_of<NestedNameSpecifier, T>::value || 762e8d8bef9SDimitry Andric std::is_base_of<NestedNameSpecifierLoc, T>::value || 763e8d8bef9SDimitry Andric std::is_base_of<TypeLoc, T>::value || 764349cc55cSDimitry Andric std::is_base_of<QualType, T>::value || 765349cc55cSDimitry Andric std::is_base_of<Attr, T>::value, 766e8d8bef9SDimitry Andric "unsupported type for recursive matching"); 767e8d8bef9SDimitry Andric return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(), 768e8d8bef9SDimitry Andric Matcher, Builder, Bind); 769e8d8bef9SDimitry Andric } 770e8d8bef9SDimitry Andric 771e8d8bef9SDimitry Andric // FIXME: Implement support for BindKind. 772e8d8bef9SDimitry Andric template <typename T> 773e8d8bef9SDimitry Andric bool matchesAncestorOf(const T &Node, const DynTypedMatcher &Matcher, 774e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, 775e8d8bef9SDimitry Andric AncestorMatchMode MatchMode) { 776e8d8bef9SDimitry Andric static_assert(std::is_base_of<Decl, T>::value || 777e8d8bef9SDimitry Andric std::is_base_of<NestedNameSpecifierLoc, T>::value || 778e8d8bef9SDimitry Andric std::is_base_of<Stmt, T>::value || 779349cc55cSDimitry Andric std::is_base_of<TypeLoc, T>::value || 780349cc55cSDimitry Andric std::is_base_of<Attr, T>::value, 781e8d8bef9SDimitry Andric "type not allowed for recursive matching"); 782e8d8bef9SDimitry Andric return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(), 783e8d8bef9SDimitry Andric Matcher, Builder, MatchMode); 784e8d8bef9SDimitry Andric } 785e8d8bef9SDimitry Andric 786e8d8bef9SDimitry Andric virtual ASTContext &getASTContext() const = 0; 787e8d8bef9SDimitry Andric 788e8d8bef9SDimitry Andric virtual bool IsMatchingInASTNodeNotSpelledInSource() const = 0; 789e8d8bef9SDimitry Andric 790e8d8bef9SDimitry Andric virtual bool IsMatchingInASTNodeNotAsIs() const = 0; 791e8d8bef9SDimitry Andric 792e8d8bef9SDimitry Andric bool isTraversalIgnoringImplicitNodes() const; 793e8d8bef9SDimitry Andric 794e8d8bef9SDimitry Andric protected: 795e8d8bef9SDimitry Andric virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx, 796e8d8bef9SDimitry Andric const DynTypedMatcher &Matcher, 797e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, 798e8d8bef9SDimitry Andric BindKind Bind) = 0; 799e8d8bef9SDimitry Andric 800e8d8bef9SDimitry Andric virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx, 801e8d8bef9SDimitry Andric const DynTypedMatcher &Matcher, 802e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, 803e8d8bef9SDimitry Andric BindKind Bind) = 0; 804e8d8bef9SDimitry Andric 805e8d8bef9SDimitry Andric virtual bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx, 806e8d8bef9SDimitry Andric const DynTypedMatcher &Matcher, 807e8d8bef9SDimitry Andric BoundNodesTreeBuilder *Builder, 808e8d8bef9SDimitry Andric AncestorMatchMode MatchMode) = 0; 809e8d8bef9SDimitry Andric private: 810e8d8bef9SDimitry Andric friend struct ASTChildrenNotSpelledInSourceScope; 811e8d8bef9SDimitry Andric virtual bool isMatchingChildrenNotSpelledInSource() const = 0; 812e8d8bef9SDimitry Andric virtual void setMatchingChildrenNotSpelledInSource(bool Set) = 0; 813e8d8bef9SDimitry Andric }; 814e8d8bef9SDimitry Andric 815e8d8bef9SDimitry Andric struct ASTChildrenNotSpelledInSourceScope { 816e8d8bef9SDimitry Andric ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *V, bool B) 817e8d8bef9SDimitry Andric : MV(V), MB(V->isMatchingChildrenNotSpelledInSource()) { 818e8d8bef9SDimitry Andric V->setMatchingChildrenNotSpelledInSource(B); 819e8d8bef9SDimitry Andric } 820e8d8bef9SDimitry Andric ~ASTChildrenNotSpelledInSourceScope() { 821e8d8bef9SDimitry Andric MV->setMatchingChildrenNotSpelledInSource(MB); 822e8d8bef9SDimitry Andric } 823e8d8bef9SDimitry Andric 824e8d8bef9SDimitry Andric private: 825e8d8bef9SDimitry Andric ASTMatchFinder *MV; 826e8d8bef9SDimitry Andric bool MB; 827e8d8bef9SDimitry Andric }; 828e8d8bef9SDimitry Andric 8290b57cec5SDimitry Andric /// Specialization of the conversion functions for QualType. 8300b57cec5SDimitry Andric /// 8310b57cec5SDimitry Andric /// This specialization provides the Matcher<Type>->Matcher<QualType> 8320b57cec5SDimitry Andric /// conversion that the static API does. 8330b57cec5SDimitry Andric template <> 8340b57cec5SDimitry Andric inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const { 8350b57cec5SDimitry Andric assert(canConvertTo<QualType>()); 8365ffd83dbSDimitry Andric const ASTNodeKind SourceKind = getSupportedKind(); 8375ffd83dbSDimitry Andric if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) { 8380b57cec5SDimitry Andric // We support implicit conversion from Matcher<Type> to Matcher<QualType> 8390b57cec5SDimitry Andric return unconditionalConvertTo<Type>(); 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric return unconditionalConvertTo<QualType>(); 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric /// Finds the first node in a range that matches the given matcher. 8450b57cec5SDimitry Andric template <typename MatcherT, typename IteratorT> 846e8d8bef9SDimitry Andric IteratorT matchesFirstInRange(const MatcherT &Matcher, IteratorT Start, 8470b57cec5SDimitry Andric IteratorT End, ASTMatchFinder *Finder, 8480b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) { 8490b57cec5SDimitry Andric for (IteratorT I = Start; I != End; ++I) { 8500b57cec5SDimitry Andric BoundNodesTreeBuilder Result(*Builder); 8510b57cec5SDimitry Andric if (Matcher.matches(*I, Finder, &Result)) { 8520b57cec5SDimitry Andric *Builder = std::move(Result); 853e8d8bef9SDimitry Andric return I; 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric } 856e8d8bef9SDimitry Andric return End; 8570b57cec5SDimitry Andric } 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andric /// Finds the first node in a pointer range that matches the given 8600b57cec5SDimitry Andric /// matcher. 8610b57cec5SDimitry Andric template <typename MatcherT, typename IteratorT> 862e8d8bef9SDimitry Andric IteratorT matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, 8630b57cec5SDimitry Andric IteratorT End, ASTMatchFinder *Finder, 8640b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) { 8650b57cec5SDimitry Andric for (IteratorT I = Start; I != End; ++I) { 8660b57cec5SDimitry Andric BoundNodesTreeBuilder Result(*Builder); 8670b57cec5SDimitry Andric if (Matcher.matches(**I, Finder, &Result)) { 8680b57cec5SDimitry Andric *Builder = std::move(Result); 869e8d8bef9SDimitry Andric return I; 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric } 872e8d8bef9SDimitry Andric return End; 873e8d8bef9SDimitry Andric } 874e8d8bef9SDimitry Andric 875e8d8bef9SDimitry Andric template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value> 876e8d8bef9SDimitry Andric * = nullptr> 877e8d8bef9SDimitry Andric inline bool isDefaultedHelper(const T *) { 8780b57cec5SDimitry Andric return false; 8790b57cec5SDimitry Andric } 880e8d8bef9SDimitry Andric inline bool isDefaultedHelper(const FunctionDecl *FD) { 881e8d8bef9SDimitry Andric return FD->isDefaulted(); 882e8d8bef9SDimitry Andric } 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric // Metafunction to determine if type T has a member called getDecl. 8850b57cec5SDimitry Andric template <typename Ty> 8860b57cec5SDimitry Andric class has_getDecl { 8870b57cec5SDimitry Andric using yes = char[1]; 8880b57cec5SDimitry Andric using no = char[2]; 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric template <typename Inner> 8910b57cec5SDimitry Andric static yes& test(Inner *I, decltype(I->getDecl()) * = nullptr); 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric template <typename> 8940b57cec5SDimitry Andric static no& test(...); 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andric public: 8970b57cec5SDimitry Andric static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); 8980b57cec5SDimitry Andric }; 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric /// Matches overloaded operators with a specific name. 9010b57cec5SDimitry Andric /// 9020b57cec5SDimitry Andric /// The type argument ArgT is not used by this matcher but is used by 903fe6060f1SDimitry Andric /// PolymorphicMatcher and should be StringRef. 9040b57cec5SDimitry Andric template <typename T, typename ArgT> 9050b57cec5SDimitry Andric class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> { 9060b57cec5SDimitry Andric static_assert(std::is_same<T, CXXOperatorCallExpr>::value || 9070b57cec5SDimitry Andric std::is_base_of<FunctionDecl, T>::value, 9080b57cec5SDimitry Andric "unsupported class for matcher"); 9095ffd83dbSDimitry Andric static_assert(std::is_same<ArgT, std::vector<std::string>>::value, 9105ffd83dbSDimitry Andric "argument type must be std::vector<std::string>"); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric public: 9135ffd83dbSDimitry Andric explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names) 9145ffd83dbSDimitry Andric : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {} 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric bool matchesNode(const T &Node) const override { 9170b57cec5SDimitry Andric return matchesSpecialized(Node); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric private: 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric /// CXXOperatorCallExpr exist only for calls to overloaded operators 9230b57cec5SDimitry Andric /// so this function returns true if the call is to an operator of the given 9240b57cec5SDimitry Andric /// name. 9250b57cec5SDimitry Andric bool matchesSpecialized(const CXXOperatorCallExpr &Node) const { 9265ffd83dbSDimitry Andric return llvm::is_contained(Names, getOperatorSpelling(Node.getOperator())); 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric /// Returns true only if CXXMethodDecl represents an overloaded 9300b57cec5SDimitry Andric /// operator and has the given operator name. 9310b57cec5SDimitry Andric bool matchesSpecialized(const FunctionDecl &Node) const { 9320b57cec5SDimitry Andric return Node.isOverloadedOperator() && 9335ffd83dbSDimitry Andric llvm::is_contained( 9345ffd83dbSDimitry Andric Names, getOperatorSpelling(Node.getOverloadedOperator())); 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 937fe6060f1SDimitry Andric std::vector<std::string> Names; 9380b57cec5SDimitry Andric }; 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric /// Matches named declarations with a specific name. 9410b57cec5SDimitry Andric /// 9420b57cec5SDimitry Andric /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details. 9430b57cec5SDimitry Andric class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> { 9440b57cec5SDimitry Andric public: 9450b57cec5SDimitry Andric explicit HasNameMatcher(std::vector<std::string> Names); 9460b57cec5SDimitry Andric 9470b57cec5SDimitry Andric bool matchesNode(const NamedDecl &Node) const override; 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric private: 9500b57cec5SDimitry Andric /// Unqualified match routine. 9510b57cec5SDimitry Andric /// 9520b57cec5SDimitry Andric /// It is much faster than the full match, but it only works for unqualified 9530b57cec5SDimitry Andric /// matches. 9540b57cec5SDimitry Andric bool matchesNodeUnqualified(const NamedDecl &Node) const; 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric /// Full match routine 9570b57cec5SDimitry Andric /// 9580b57cec5SDimitry Andric /// Fast implementation for the simple case of a named declaration at 9590b57cec5SDimitry Andric /// namespace or RecordDecl scope. 9600b57cec5SDimitry Andric /// It is slower than matchesNodeUnqualified, but faster than 9610b57cec5SDimitry Andric /// matchesNodeFullSlow. 9620b57cec5SDimitry Andric bool matchesNodeFullFast(const NamedDecl &Node) const; 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric /// Full match routine 9650b57cec5SDimitry Andric /// 9660b57cec5SDimitry Andric /// It generates the fully qualified name of the declaration (which is 9670b57cec5SDimitry Andric /// expensive) before trying to match. 9680b57cec5SDimitry Andric /// It is slower but simple and works on all cases. 9690b57cec5SDimitry Andric bool matchesNodeFullSlow(const NamedDecl &Node) const; 9700b57cec5SDimitry Andric 971fe6060f1SDimitry Andric bool UseUnqualifiedMatch; 972fe6060f1SDimitry Andric std::vector<std::string> Names; 9730b57cec5SDimitry Andric }; 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric /// Trampoline function to use VariadicFunction<> to construct a 9760b57cec5SDimitry Andric /// HasNameMatcher. 9770b57cec5SDimitry Andric Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs); 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric /// Trampoline function to use VariadicFunction<> to construct a 9800b57cec5SDimitry Andric /// hasAnySelector matcher. 9810b57cec5SDimitry Andric Matcher<ObjCMessageExpr> hasAnySelectorFunc( 9820b57cec5SDimitry Andric ArrayRef<const StringRef *> NameRefs); 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric /// Matches declarations for QualType and CallExpr. 9850b57cec5SDimitry Andric /// 986fe6060f1SDimitry Andric /// Type argument DeclMatcherT is required by PolymorphicMatcher but 9870b57cec5SDimitry Andric /// not actually used. 9880b57cec5SDimitry Andric template <typename T, typename DeclMatcherT> 9895ffd83dbSDimitry Andric class HasDeclarationMatcher : public MatcherInterface<T> { 9900b57cec5SDimitry Andric static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value, 9910b57cec5SDimitry Andric "instantiated with wrong types"); 9920b57cec5SDimitry Andric 993fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 9945ffd83dbSDimitry Andric 9950b57cec5SDimitry Andric public: 9960b57cec5SDimitry Andric explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher) 9975ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher) {} 9980b57cec5SDimitry Andric 9990b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 10000b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 10010b57cec5SDimitry Andric return matchesSpecialized(Node, Finder, Builder); 10020b57cec5SDimitry Andric } 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric private: 10050b57cec5SDimitry Andric /// Forwards to matching on the underlying type of the QualType. 10060b57cec5SDimitry Andric bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, 10070b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 10080b57cec5SDimitry Andric if (Node.isNull()) 10090b57cec5SDimitry Andric return false; 10100b57cec5SDimitry Andric 10110b57cec5SDimitry Andric return matchesSpecialized(*Node, Finder, Builder); 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric /// Finds the best declaration for a type and returns whether the inner 10150b57cec5SDimitry Andric /// matcher matches on it. 10160b57cec5SDimitry Andric bool matchesSpecialized(const Type &Node, ASTMatchFinder *Finder, 10170b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 10180b57cec5SDimitry Andric // DeducedType does not have declarations of its own, so 10190b57cec5SDimitry Andric // match the deduced type instead. 10200b57cec5SDimitry Andric if (const auto *S = dyn_cast<DeducedType>(&Node)) { 1021349cc55cSDimitry Andric QualType DT = S->getDeducedType(); 1022349cc55cSDimitry Andric return !DT.isNull() ? matchesSpecialized(*DT, Finder, Builder) : false; 10230b57cec5SDimitry Andric } 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric // First, for any types that have a declaration, extract the declaration and 10260b57cec5SDimitry Andric // match on it. 1027349cc55cSDimitry Andric if (const auto *S = dyn_cast<TagType>(&Node)) { 10280b57cec5SDimitry Andric return matchesDecl(S->getDecl(), Finder, Builder); 10290b57cec5SDimitry Andric } 1030349cc55cSDimitry Andric if (const auto *S = dyn_cast<InjectedClassNameType>(&Node)) { 10310b57cec5SDimitry Andric return matchesDecl(S->getDecl(), Finder, Builder); 10320b57cec5SDimitry Andric } 1033349cc55cSDimitry Andric if (const auto *S = dyn_cast<TemplateTypeParmType>(&Node)) { 10340b57cec5SDimitry Andric return matchesDecl(S->getDecl(), Finder, Builder); 10350b57cec5SDimitry Andric } 1036349cc55cSDimitry Andric if (const auto *S = dyn_cast<TypedefType>(&Node)) { 10370b57cec5SDimitry Andric return matchesDecl(S->getDecl(), Finder, Builder); 10380b57cec5SDimitry Andric } 1039349cc55cSDimitry Andric if (const auto *S = dyn_cast<UnresolvedUsingType>(&Node)) { 10400b57cec5SDimitry Andric return matchesDecl(S->getDecl(), Finder, Builder); 10410b57cec5SDimitry Andric } 1042349cc55cSDimitry Andric if (const auto *S = dyn_cast<ObjCObjectType>(&Node)) { 10430b57cec5SDimitry Andric return matchesDecl(S->getInterface(), Finder, Builder); 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric // A SubstTemplateTypeParmType exists solely to mark a type substitution 10470b57cec5SDimitry Andric // on the instantiated template. As users usually want to match the 10480b57cec5SDimitry Andric // template parameter on the uninitialized template, we can always desugar 10490b57cec5SDimitry Andric // one level without loss of expressivness. 10500b57cec5SDimitry Andric // For example, given: 10510b57cec5SDimitry Andric // template<typename T> struct X { T t; } class A {}; X<A> a; 10520b57cec5SDimitry Andric // The following matcher will match, which otherwise would not: 10530b57cec5SDimitry Andric // fieldDecl(hasType(pointerType())). 1054349cc55cSDimitry Andric if (const auto *S = dyn_cast<SubstTemplateTypeParmType>(&Node)) { 10550b57cec5SDimitry Andric return matchesSpecialized(S->getReplacementType(), Finder, Builder); 10560b57cec5SDimitry Andric } 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric // For template specialization types, we want to match the template 10590b57cec5SDimitry Andric // declaration, as long as the type is still dependent, and otherwise the 10600b57cec5SDimitry Andric // declaration of the instantiated tag type. 1061349cc55cSDimitry Andric if (const auto *S = dyn_cast<TemplateSpecializationType>(&Node)) { 10620b57cec5SDimitry Andric if (!S->isTypeAlias() && S->isSugared()) { 10630b57cec5SDimitry Andric // If the template is non-dependent, we want to match the instantiated 10640b57cec5SDimitry Andric // tag type. 10650b57cec5SDimitry Andric // For example, given: 10660b57cec5SDimitry Andric // template<typename T> struct X {}; X<int> a; 10670b57cec5SDimitry Andric // The following matcher will match, which otherwise would not: 10680b57cec5SDimitry Andric // templateSpecializationType(hasDeclaration(cxxRecordDecl())). 10690b57cec5SDimitry Andric return matchesSpecialized(*S->desugar(), Finder, Builder); 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric // If the template is dependent or an alias, match the template 10720b57cec5SDimitry Andric // declaration. 10730b57cec5SDimitry Andric return matchesDecl(S->getTemplateName().getAsTemplateDecl(), Finder, 10740b57cec5SDimitry Andric Builder); 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric // FIXME: We desugar elaborated types. This makes the assumption that users 10780b57cec5SDimitry Andric // do never want to match on whether a type is elaborated - there are 10790b57cec5SDimitry Andric // arguments for both sides; for now, continue desugaring. 1080349cc55cSDimitry Andric if (const auto *S = dyn_cast<ElaboratedType>(&Node)) { 10810b57cec5SDimitry Andric return matchesSpecialized(S->desugar(), Finder, Builder); 10820b57cec5SDimitry Andric } 10830eae32dcSDimitry Andric // Similarly types found via using declarations. 10840eae32dcSDimitry Andric // These are *usually* meaningless sugar, and this matches the historical 10850eae32dcSDimitry Andric // behavior prior to the introduction of UsingType. 10860eae32dcSDimitry Andric if (const auto *S = dyn_cast<UsingType>(&Node)) { 10870eae32dcSDimitry Andric return matchesSpecialized(S->desugar(), Finder, Builder); 10880eae32dcSDimitry Andric } 10890b57cec5SDimitry Andric return false; 10900b57cec5SDimitry Andric } 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric /// Extracts the Decl the DeclRefExpr references and returns whether 10930b57cec5SDimitry Andric /// the inner matcher matches on it. 10940b57cec5SDimitry Andric bool matchesSpecialized(const DeclRefExpr &Node, ASTMatchFinder *Finder, 10950b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 10960b57cec5SDimitry Andric return matchesDecl(Node.getDecl(), Finder, Builder); 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric /// Extracts the Decl of the callee of a CallExpr and returns whether 11000b57cec5SDimitry Andric /// the inner matcher matches on it. 11010b57cec5SDimitry Andric bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, 11020b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 11030b57cec5SDimitry Andric return matchesDecl(Node.getCalleeDecl(), Finder, Builder); 11040b57cec5SDimitry Andric } 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric /// Extracts the Decl of the constructor call and returns whether the 11070b57cec5SDimitry Andric /// inner matcher matches on it. 11080b57cec5SDimitry Andric bool matchesSpecialized(const CXXConstructExpr &Node, 11090b57cec5SDimitry Andric ASTMatchFinder *Finder, 11100b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 11110b57cec5SDimitry Andric return matchesDecl(Node.getConstructor(), Finder, Builder); 11120b57cec5SDimitry Andric } 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric bool matchesSpecialized(const ObjCIvarRefExpr &Node, 11150b57cec5SDimitry Andric ASTMatchFinder *Finder, 11160b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 11170b57cec5SDimitry Andric return matchesDecl(Node.getDecl(), Finder, Builder); 11180b57cec5SDimitry Andric } 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric /// Extracts the operator new of the new call and returns whether the 11210b57cec5SDimitry Andric /// inner matcher matches on it. 11220b57cec5SDimitry Andric bool matchesSpecialized(const CXXNewExpr &Node, 11230b57cec5SDimitry Andric ASTMatchFinder *Finder, 11240b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 11250b57cec5SDimitry Andric return matchesDecl(Node.getOperatorNew(), Finder, Builder); 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric 11280b57cec5SDimitry Andric /// Extracts the \c ValueDecl a \c MemberExpr refers to and returns 11290b57cec5SDimitry Andric /// whether the inner matcher matches on it. 11300b57cec5SDimitry Andric bool matchesSpecialized(const MemberExpr &Node, 11310b57cec5SDimitry Andric ASTMatchFinder *Finder, 11320b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 11330b57cec5SDimitry Andric return matchesDecl(Node.getMemberDecl(), Finder, Builder); 11340b57cec5SDimitry Andric } 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric /// Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns 11370b57cec5SDimitry Andric /// whether the inner matcher matches on it. 11380b57cec5SDimitry Andric bool matchesSpecialized(const AddrLabelExpr &Node, 11390b57cec5SDimitry Andric ASTMatchFinder *Finder, 11400b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 11410b57cec5SDimitry Andric return matchesDecl(Node.getLabel(), Finder, Builder); 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric /// Extracts the declaration of a LabelStmt and returns whether the 11450b57cec5SDimitry Andric /// inner matcher matches on it. 11460b57cec5SDimitry Andric bool matchesSpecialized(const LabelStmt &Node, ASTMatchFinder *Finder, 11470b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 11480b57cec5SDimitry Andric return matchesDecl(Node.getDecl(), Finder, Builder); 11490b57cec5SDimitry Andric } 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric /// Returns whether the inner matcher \c Node. Returns false if \c Node 11520b57cec5SDimitry Andric /// is \c NULL. 11530b57cec5SDimitry Andric bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder, 11540b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const { 1155e8d8bef9SDimitry Andric return Node != nullptr && 1156e8d8bef9SDimitry Andric !(Finder->isTraversalIgnoringImplicitNodes() && 1157e8d8bef9SDimitry Andric Node->isImplicit()) && 1158e8d8bef9SDimitry Andric this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder, 1159e8d8bef9SDimitry Andric Builder); 11600b57cec5SDimitry Andric } 11610b57cec5SDimitry Andric }; 11620b57cec5SDimitry Andric 11630b57cec5SDimitry Andric /// IsBaseType<T>::value is true if T is a "base" type in the AST 11640b57cec5SDimitry Andric /// node class hierarchies. 11650b57cec5SDimitry Andric template <typename T> 11660b57cec5SDimitry Andric struct IsBaseType { 11670b57cec5SDimitry Andric static const bool value = 1168e8d8bef9SDimitry Andric std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value || 1169e8d8bef9SDimitry Andric std::is_same<T, QualType>::value || std::is_same<T, Type>::value || 11700b57cec5SDimitry Andric std::is_same<T, TypeLoc>::value || 11710b57cec5SDimitry Andric std::is_same<T, NestedNameSpecifier>::value || 11720b57cec5SDimitry Andric std::is_same<T, NestedNameSpecifierLoc>::value || 1173e8d8bef9SDimitry Andric std::is_same<T, CXXCtorInitializer>::value || 1174349cc55cSDimitry Andric std::is_same<T, TemplateArgumentLoc>::value || 1175349cc55cSDimitry Andric std::is_same<T, Attr>::value; 11760b57cec5SDimitry Andric }; 11770b57cec5SDimitry Andric template <typename T> 11780b57cec5SDimitry Andric const bool IsBaseType<T>::value; 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric /// A "type list" that contains all types. 11810b57cec5SDimitry Andric /// 11820b57cec5SDimitry Andric /// Useful for matchers like \c anything and \c unless. 11830b57cec5SDimitry Andric using AllNodeBaseTypes = 11840b57cec5SDimitry Andric TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType, 1185349cc55cSDimitry Andric Type, TypeLoc, CXXCtorInitializer, Attr>; 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric /// Helper meta-function to extract the argument out of a function of 11880b57cec5SDimitry Andric /// type void(Arg). 11890b57cec5SDimitry Andric /// 11900b57cec5SDimitry Andric /// See AST_POLYMORPHIC_SUPPORTED_TYPES for details. 11910b57cec5SDimitry Andric template <class T> struct ExtractFunctionArgMeta; 11920b57cec5SDimitry Andric template <class T> struct ExtractFunctionArgMeta<void(T)> { 11930b57cec5SDimitry Andric using type = T; 11940b57cec5SDimitry Andric }; 11950b57cec5SDimitry Andric 1196fe6060f1SDimitry Andric template <class T, class Tuple, std::size_t... I> 1197fe6060f1SDimitry Andric constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) { 1198fe6060f1SDimitry Andric return new T(std::get<I>(std::forward<Tuple>(t))...); 1199fe6060f1SDimitry Andric } 1200fe6060f1SDimitry Andric 1201fe6060f1SDimitry Andric template <class T, class Tuple> constexpr T *new_from_tuple(Tuple &&t) { 1202fe6060f1SDimitry Andric return new_from_tuple_impl<T>( 1203fe6060f1SDimitry Andric std::forward<Tuple>(t), 1204fe6060f1SDimitry Andric std::make_index_sequence< 1205fe6060f1SDimitry Andric std::tuple_size<std::remove_reference_t<Tuple>>::value>{}); 1206fe6060f1SDimitry Andric } 1207fe6060f1SDimitry Andric 12080b57cec5SDimitry Andric /// Default type lists for ArgumentAdaptingMatcher matchers. 12090b57cec5SDimitry Andric using AdaptativeDefaultFromTypes = AllNodeBaseTypes; 12100b57cec5SDimitry Andric using AdaptativeDefaultToTypes = 12110b57cec5SDimitry Andric TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc, 1212349cc55cSDimitry Andric QualType, Attr>; 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric /// All types that are supported by HasDeclarationMatcher above. 12150b57cec5SDimitry Andric using HasDeclarationSupportedTypes = 12160b57cec5SDimitry Andric TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType, 12170b57cec5SDimitry Andric ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr, 12180b57cec5SDimitry Andric MemberExpr, QualType, RecordType, TagType, 12190b57cec5SDimitry Andric TemplateSpecializationType, TemplateTypeParmType, TypedefType, 12200b57cec5SDimitry Andric UnresolvedUsingType, ObjCIvarRefExpr>; 12210b57cec5SDimitry Andric 1222e8d8bef9SDimitry Andric /// A Matcher that allows binding the node it matches to an id. 1223e8d8bef9SDimitry Andric /// 1224e8d8bef9SDimitry Andric /// BindableMatcher provides a \a bind() method that allows binding the 1225e8d8bef9SDimitry Andric /// matched node to an id if the match was successful. 1226e8d8bef9SDimitry Andric template <typename T> class BindableMatcher : public Matcher<T> { 1227e8d8bef9SDimitry Andric public: 1228e8d8bef9SDimitry Andric explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {} 1229e8d8bef9SDimitry Andric explicit BindableMatcher(MatcherInterface<T> *Implementation) 1230e8d8bef9SDimitry Andric : Matcher<T>(Implementation) {} 1231e8d8bef9SDimitry Andric 1232e8d8bef9SDimitry Andric /// Returns a matcher that will bind the matched node on a match. 1233e8d8bef9SDimitry Andric /// 1234e8d8bef9SDimitry Andric /// The returned matcher is equivalent to this matcher, but will 1235e8d8bef9SDimitry Andric /// bind the matched node on a match. 1236e8d8bef9SDimitry Andric Matcher<T> bind(StringRef ID) const { 1237e8d8bef9SDimitry Andric return DynTypedMatcher(*this) 1238e8d8bef9SDimitry Andric .tryBind(ID) 1239e8d8bef9SDimitry Andric ->template unconditionalConvertTo<T>(); 1240e8d8bef9SDimitry Andric } 1241e8d8bef9SDimitry Andric 1242e8d8bef9SDimitry Andric /// Same as Matcher<T>'s conversion operator, but enables binding on 1243e8d8bef9SDimitry Andric /// the returned matcher. 1244e8d8bef9SDimitry Andric operator DynTypedMatcher() const { 1245e8d8bef9SDimitry Andric DynTypedMatcher Result = static_cast<const Matcher<T> &>(*this); 1246e8d8bef9SDimitry Andric Result.setAllowBind(true); 1247e8d8bef9SDimitry Andric return Result; 1248e8d8bef9SDimitry Andric } 1249e8d8bef9SDimitry Andric }; 1250e8d8bef9SDimitry Andric 1251e8d8bef9SDimitry Andric /// Matches any instance of the given NodeType. 1252e8d8bef9SDimitry Andric /// 1253e8d8bef9SDimitry Andric /// This is useful when a matcher syntactically requires a child matcher, 1254e8d8bef9SDimitry Andric /// but the context doesn't care. See for example: anything(). 1255e8d8bef9SDimitry Andric class TrueMatcher { 1256e8d8bef9SDimitry Andric public: 1257e8d8bef9SDimitry Andric using ReturnTypes = AllNodeBaseTypes; 1258e8d8bef9SDimitry Andric 1259e8d8bef9SDimitry Andric template <typename T> operator Matcher<T>() const { 1260e8d8bef9SDimitry Andric return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>()) 1261e8d8bef9SDimitry Andric .template unconditionalConvertTo<T>(); 1262e8d8bef9SDimitry Andric } 1263e8d8bef9SDimitry Andric }; 1264e8d8bef9SDimitry Andric 1265e8d8bef9SDimitry Andric /// Creates a Matcher<T> that matches if all inner matchers match. 1266e8d8bef9SDimitry Andric template <typename T> 1267e8d8bef9SDimitry Andric BindableMatcher<T> 1268e8d8bef9SDimitry Andric makeAllOfComposite(ArrayRef<const Matcher<T> *> InnerMatchers) { 1269e8d8bef9SDimitry Andric // For the size() == 0 case, we return a "true" matcher. 1270e8d8bef9SDimitry Andric if (InnerMatchers.empty()) { 1271e8d8bef9SDimitry Andric return BindableMatcher<T>(TrueMatcher()); 1272e8d8bef9SDimitry Andric } 1273e8d8bef9SDimitry Andric // For the size() == 1 case, we simply return that one matcher. 1274e8d8bef9SDimitry Andric // No need to wrap it in a variadic operation. 1275e8d8bef9SDimitry Andric if (InnerMatchers.size() == 1) { 1276e8d8bef9SDimitry Andric return BindableMatcher<T>(*InnerMatchers[0]); 1277e8d8bef9SDimitry Andric } 1278e8d8bef9SDimitry Andric 1279e8d8bef9SDimitry Andric using PI = llvm::pointee_iterator<const Matcher<T> *const *>; 1280e8d8bef9SDimitry Andric 1281e8d8bef9SDimitry Andric std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()), 1282e8d8bef9SDimitry Andric PI(InnerMatchers.end())); 1283e8d8bef9SDimitry Andric return BindableMatcher<T>( 1284e8d8bef9SDimitry Andric DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf, 1285e8d8bef9SDimitry Andric ASTNodeKind::getFromNodeKind<T>(), 1286e8d8bef9SDimitry Andric std::move(DynMatchers)) 1287e8d8bef9SDimitry Andric .template unconditionalConvertTo<T>()); 1288e8d8bef9SDimitry Andric } 1289e8d8bef9SDimitry Andric 1290e8d8bef9SDimitry Andric /// Creates a Matcher<T> that matches if 1291e8d8bef9SDimitry Andric /// T is dyn_cast'able into InnerT and all inner matchers match. 1292e8d8bef9SDimitry Andric /// 1293e8d8bef9SDimitry Andric /// Returns BindableMatcher, as matchers that use dyn_cast have 1294e8d8bef9SDimitry Andric /// the same object both to match on and to run submatchers on, 1295e8d8bef9SDimitry Andric /// so there is no ambiguity with what gets bound. 1296e8d8bef9SDimitry Andric template <typename T, typename InnerT> 1297e8d8bef9SDimitry Andric BindableMatcher<T> 1298e8d8bef9SDimitry Andric makeDynCastAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) { 1299e8d8bef9SDimitry Andric return BindableMatcher<T>( 1300e8d8bef9SDimitry Andric makeAllOfComposite(InnerMatchers).template dynCastTo<T>()); 1301e8d8bef9SDimitry Andric } 1302e8d8bef9SDimitry Andric 1303e8d8bef9SDimitry Andric /// A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a 1304e8d8bef9SDimitry Andric /// variadic functor that takes a number of Matcher<TargetT> and returns a 1305e8d8bef9SDimitry Andric /// Matcher<SourceT> that matches TargetT nodes that are matched by all of the 1306e8d8bef9SDimitry Andric /// given matchers, if SourceT can be dynamically casted into TargetT. 1307e8d8bef9SDimitry Andric /// 1308e8d8bef9SDimitry Andric /// For example: 1309e8d8bef9SDimitry Andric /// const VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> record; 1310e8d8bef9SDimitry Andric /// Creates a functor record(...) that creates a Matcher<Decl> given 1311e8d8bef9SDimitry Andric /// a variable number of arguments of type Matcher<CXXRecordDecl>. 1312e8d8bef9SDimitry Andric /// The returned matcher matches if the given Decl can by dynamically 1313e8d8bef9SDimitry Andric /// casted to CXXRecordDecl and all given matchers match. 1314e8d8bef9SDimitry Andric template <typename SourceT, typename TargetT> 1315e8d8bef9SDimitry Andric class VariadicDynCastAllOfMatcher 1316e8d8bef9SDimitry Andric : public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>, 1317e8d8bef9SDimitry Andric makeDynCastAllOfComposite<SourceT, TargetT>> { 1318e8d8bef9SDimitry Andric public: 1319e8d8bef9SDimitry Andric VariadicDynCastAllOfMatcher() {} 1320e8d8bef9SDimitry Andric }; 1321e8d8bef9SDimitry Andric 1322e8d8bef9SDimitry Andric /// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes 1323e8d8bef9SDimitry Andric /// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T 1324e8d8bef9SDimitry Andric /// nodes that are matched by all of the given matchers. 1325e8d8bef9SDimitry Andric /// 1326e8d8bef9SDimitry Andric /// For example: 1327e8d8bef9SDimitry Andric /// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; 1328e8d8bef9SDimitry Andric /// Creates a functor nestedNameSpecifier(...) that creates a 1329e8d8bef9SDimitry Andric /// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type 1330e8d8bef9SDimitry Andric /// \c Matcher<NestedNameSpecifier>. 1331e8d8bef9SDimitry Andric /// The returned matcher matches if all given matchers match. 1332e8d8bef9SDimitry Andric template <typename T> 1333e8d8bef9SDimitry Andric class VariadicAllOfMatcher 1334e8d8bef9SDimitry Andric : public VariadicFunction<BindableMatcher<T>, Matcher<T>, 1335e8d8bef9SDimitry Andric makeAllOfComposite<T>> { 1336e8d8bef9SDimitry Andric public: 1337e8d8bef9SDimitry Andric VariadicAllOfMatcher() {} 1338e8d8bef9SDimitry Andric }; 1339e8d8bef9SDimitry Andric 1340e8d8bef9SDimitry Andric /// VariadicOperatorMatcher related types. 1341e8d8bef9SDimitry Andric /// @{ 1342e8d8bef9SDimitry Andric 1343e8d8bef9SDimitry Andric /// Polymorphic matcher object that uses a \c 1344e8d8bef9SDimitry Andric /// DynTypedMatcher::VariadicOperator operator. 1345e8d8bef9SDimitry Andric /// 1346e8d8bef9SDimitry Andric /// Input matchers can have any type (including other polymorphic matcher 1347e8d8bef9SDimitry Andric /// types), and the actual Matcher<T> is generated on demand with an implicit 1348e8d8bef9SDimitry Andric /// conversion operator. 1349e8d8bef9SDimitry Andric template <typename... Ps> class VariadicOperatorMatcher { 1350e8d8bef9SDimitry Andric public: 1351e8d8bef9SDimitry Andric VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params) 1352e8d8bef9SDimitry Andric : Op(Op), Params(std::forward<Ps>(Params)...) {} 1353e8d8bef9SDimitry Andric 135481ad6265SDimitry Andric template <typename T> operator Matcher<T>() const & { 1355e8d8bef9SDimitry Andric return DynTypedMatcher::constructVariadic( 1356e8d8bef9SDimitry Andric Op, ASTNodeKind::getFromNodeKind<T>(), 1357e8d8bef9SDimitry Andric getMatchers<T>(std::index_sequence_for<Ps...>())) 1358e8d8bef9SDimitry Andric .template unconditionalConvertTo<T>(); 1359e8d8bef9SDimitry Andric } 1360e8d8bef9SDimitry Andric 1361fe6060f1SDimitry Andric template <typename T> operator Matcher<T>() && { 1362fe6060f1SDimitry Andric return DynTypedMatcher::constructVariadic( 1363fe6060f1SDimitry Andric Op, ASTNodeKind::getFromNodeKind<T>(), 1364fe6060f1SDimitry Andric getMatchers<T>(std::index_sequence_for<Ps...>())) 1365fe6060f1SDimitry Andric .template unconditionalConvertTo<T>(); 1366fe6060f1SDimitry Andric } 136781ad6265SDimitry Andric 1368e8d8bef9SDimitry Andric private: 1369e8d8bef9SDimitry Andric // Helper method to unpack the tuple into a vector. 1370e8d8bef9SDimitry Andric template <typename T, std::size_t... Is> 137181ad6265SDimitry Andric std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const & { 1372e8d8bef9SDimitry Andric return {Matcher<T>(std::get<Is>(Params))...}; 1373e8d8bef9SDimitry Andric } 1374e8d8bef9SDimitry Andric 1375fe6060f1SDimitry Andric template <typename T, std::size_t... Is> 1376fe6060f1SDimitry Andric std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) && { 1377fe6060f1SDimitry Andric return {Matcher<T>(std::get<Is>(std::move(Params)))...}; 1378fe6060f1SDimitry Andric } 1379fe6060f1SDimitry Andric 1380e8d8bef9SDimitry Andric const DynTypedMatcher::VariadicOperator Op; 1381e8d8bef9SDimitry Andric std::tuple<Ps...> Params; 1382e8d8bef9SDimitry Andric }; 1383e8d8bef9SDimitry Andric 1384e8d8bef9SDimitry Andric /// Overloaded function object to generate VariadicOperatorMatcher 1385e8d8bef9SDimitry Andric /// objects from arbitrary matchers. 1386e8d8bef9SDimitry Andric template <unsigned MinCount, unsigned MaxCount> 1387e8d8bef9SDimitry Andric struct VariadicOperatorMatcherFunc { 1388e8d8bef9SDimitry Andric DynTypedMatcher::VariadicOperator Op; 1389e8d8bef9SDimitry Andric 1390e8d8bef9SDimitry Andric template <typename... Ms> 1391e8d8bef9SDimitry Andric VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const { 1392e8d8bef9SDimitry Andric static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount, 1393e8d8bef9SDimitry Andric "invalid number of parameters for variadic matcher"); 1394e8d8bef9SDimitry Andric return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...); 1395e8d8bef9SDimitry Andric } 1396e8d8bef9SDimitry Andric }; 1397e8d8bef9SDimitry Andric 1398e8d8bef9SDimitry Andric template <typename T, bool IsBaseOf, typename Head, typename Tail> 1399e8d8bef9SDimitry Andric struct GetCladeImpl { 1400e8d8bef9SDimitry Andric using Type = Head; 1401e8d8bef9SDimitry Andric }; 1402e8d8bef9SDimitry Andric template <typename T, typename Head, typename Tail> 1403e8d8bef9SDimitry Andric struct GetCladeImpl<T, false, Head, Tail> 1404e8d8bef9SDimitry Andric : GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value, 1405e8d8bef9SDimitry Andric typename Tail::head, typename Tail::tail> {}; 1406e8d8bef9SDimitry Andric 1407e8d8bef9SDimitry Andric template <typename T, typename... U> 1408e8d8bef9SDimitry Andric struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {}; 1409e8d8bef9SDimitry Andric 1410e8d8bef9SDimitry Andric template <typename CladeType, typename... MatcherTypes> 1411e8d8bef9SDimitry Andric struct MapAnyOfMatcherImpl { 1412e8d8bef9SDimitry Andric 1413e8d8bef9SDimitry Andric template <typename... InnerMatchers> 1414e8d8bef9SDimitry Andric BindableMatcher<CladeType> 1415e8d8bef9SDimitry Andric operator()(InnerMatchers &&... InnerMatcher) const { 1416bdd1243dSDimitry Andric return VariadicAllOfMatcher<CladeType>()(std::apply( 1417e8d8bef9SDimitry Andric internal::VariadicOperatorMatcherFunc< 1418e8d8bef9SDimitry Andric 0, std::numeric_limits<unsigned>::max()>{ 1419e8d8bef9SDimitry Andric internal::DynTypedMatcher::VO_AnyOf}, 1420bdd1243dSDimitry Andric std::apply( 1421e8d8bef9SDimitry Andric [&](auto... Matcher) { 1422fe6060f1SDimitry Andric return std::make_tuple(Matcher(InnerMatcher...)...); 1423e8d8bef9SDimitry Andric }, 1424e8d8bef9SDimitry Andric std::tuple< 1425e8d8bef9SDimitry Andric VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>()))); 1426e8d8bef9SDimitry Andric } 1427e8d8bef9SDimitry Andric }; 1428e8d8bef9SDimitry Andric 1429e8d8bef9SDimitry Andric template <typename... MatcherTypes> 1430e8d8bef9SDimitry Andric using MapAnyOfMatcher = 1431e8d8bef9SDimitry Andric MapAnyOfMatcherImpl<typename GetClade<MatcherTypes...>::Type, 1432e8d8bef9SDimitry Andric MatcherTypes...>; 1433e8d8bef9SDimitry Andric 1434e8d8bef9SDimitry Andric template <typename... MatcherTypes> struct MapAnyOfHelper { 1435e8d8bef9SDimitry Andric using CladeType = typename GetClade<MatcherTypes...>::Type; 1436e8d8bef9SDimitry Andric 1437e8d8bef9SDimitry Andric MapAnyOfMatcher<MatcherTypes...> with; 1438e8d8bef9SDimitry Andric 1439e8d8bef9SDimitry Andric operator BindableMatcher<CladeType>() const { return with(); } 1440e8d8bef9SDimitry Andric 1441e8d8bef9SDimitry Andric Matcher<CladeType> bind(StringRef ID) const { return with().bind(ID); } 1442e8d8bef9SDimitry Andric }; 1443e8d8bef9SDimitry Andric 1444480093f4SDimitry Andric template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, 1445480093f4SDimitry Andric typename T, typename ToTypes> 1446480093f4SDimitry Andric class ArgumentAdaptingMatcherFuncAdaptor { 1447480093f4SDimitry Andric public: 1448480093f4SDimitry Andric explicit ArgumentAdaptingMatcherFuncAdaptor(const Matcher<T> &InnerMatcher) 1449480093f4SDimitry Andric : InnerMatcher(InnerMatcher) {} 1450480093f4SDimitry Andric 1451480093f4SDimitry Andric using ReturnTypes = ToTypes; 1452480093f4SDimitry Andric 145381ad6265SDimitry Andric template <typename To> operator Matcher<To>() const & { 1454480093f4SDimitry Andric return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher)); 1455480093f4SDimitry Andric } 1456480093f4SDimitry Andric 1457fe6060f1SDimitry Andric template <typename To> operator Matcher<To>() && { 1458fe6060f1SDimitry Andric return Matcher<To>(new ArgumentAdapterT<To, T>(std::move(InnerMatcher))); 1459fe6060f1SDimitry Andric } 1460fe6060f1SDimitry Andric 1461480093f4SDimitry Andric private: 1462fe6060f1SDimitry Andric Matcher<T> InnerMatcher; 1463480093f4SDimitry Andric }; 1464480093f4SDimitry Andric 14650b57cec5SDimitry Andric /// Converts a \c Matcher<T> to a matcher of desired type \c To by 14660b57cec5SDimitry Andric /// "adapting" a \c To into a \c T. 14670b57cec5SDimitry Andric /// 14680b57cec5SDimitry Andric /// The \c ArgumentAdapterT argument specifies how the adaptation is done. 14690b57cec5SDimitry Andric /// 14700b57cec5SDimitry Andric /// For example: 14710b57cec5SDimitry Andric /// \c ArgumentAdaptingMatcher<HasMatcher, T>(InnerMatcher); 14720b57cec5SDimitry Andric /// Given that \c InnerMatcher is of type \c Matcher<T>, this returns a matcher 14730b57cec5SDimitry Andric /// that is convertible into any matcher of type \c To by constructing 14740b57cec5SDimitry Andric /// \c HasMatcher<To, T>(InnerMatcher). 14750b57cec5SDimitry Andric /// 14760b57cec5SDimitry Andric /// If a matcher does not need knowledge about the inner type, prefer to use 1477fe6060f1SDimitry Andric /// PolymorphicMatcher. 14780b57cec5SDimitry Andric template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, 14790b57cec5SDimitry Andric typename FromTypes = AdaptativeDefaultFromTypes, 14800b57cec5SDimitry Andric typename ToTypes = AdaptativeDefaultToTypes> 14810b57cec5SDimitry Andric struct ArgumentAdaptingMatcherFunc { 1482480093f4SDimitry Andric template <typename T> 1483480093f4SDimitry Andric static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes> 1484480093f4SDimitry Andric create(const Matcher<T> &InnerMatcher) { 1485480093f4SDimitry Andric return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>( 1486480093f4SDimitry Andric InnerMatcher); 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric 1489480093f4SDimitry Andric template <typename T> 1490480093f4SDimitry Andric ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes> 1491480093f4SDimitry Andric operator()(const Matcher<T> &InnerMatcher) const { 1492480093f4SDimitry Andric return create(InnerMatcher); 1493480093f4SDimitry Andric } 1494e8d8bef9SDimitry Andric 1495e8d8bef9SDimitry Andric template <typename... T> 1496e8d8bef9SDimitry Andric ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, 1497e8d8bef9SDimitry Andric typename GetClade<T...>::Type, ToTypes> 1498e8d8bef9SDimitry Andric operator()(const MapAnyOfHelper<T...> &InnerMatcher) const { 1499e8d8bef9SDimitry Andric return create(InnerMatcher.with()); 1500e8d8bef9SDimitry Andric } 15010b57cec5SDimitry Andric }; 15020b57cec5SDimitry Andric 15035ffd83dbSDimitry Andric template <typename T> class TraversalMatcher : public MatcherInterface<T> { 1504fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 15055ffd83dbSDimitry Andric clang::TraversalKind Traversal; 1506480093f4SDimitry Andric 1507480093f4SDimitry Andric public: 15085ffd83dbSDimitry Andric explicit TraversalMatcher(clang::TraversalKind TK, 15095ffd83dbSDimitry Andric const Matcher<T> &InnerMatcher) 15105ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher), Traversal(TK) {} 15110b57cec5SDimitry Andric 1512480093f4SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 1513480093f4SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 15145ffd83dbSDimitry Andric return this->InnerMatcher.matches(DynTypedNode::create(Node), Finder, 15155ffd83dbSDimitry Andric Builder); 15160b57cec5SDimitry Andric } 1517480093f4SDimitry Andric 1518bdd1243dSDimitry Andric std::optional<clang::TraversalKind> TraversalKind() const override { 1519e8d8bef9SDimitry Andric if (auto NestedKind = this->InnerMatcher.getTraversalKind()) 1520e8d8bef9SDimitry Andric return NestedKind; 1521480093f4SDimitry Andric return Traversal; 1522480093f4SDimitry Andric } 1523480093f4SDimitry Andric }; 1524480093f4SDimitry Andric 1525480093f4SDimitry Andric template <typename MatcherType> class TraversalWrapper { 1526480093f4SDimitry Andric public: 15275ffd83dbSDimitry Andric TraversalWrapper(TraversalKind TK, const MatcherType &InnerMatcher) 1528480093f4SDimitry Andric : TK(TK), InnerMatcher(InnerMatcher) {} 1529480093f4SDimitry Andric 153081ad6265SDimitry Andric template <typename T> operator Matcher<T>() const & { 1531480093f4SDimitry Andric return internal::DynTypedMatcher::constructRestrictedWrapper( 1532480093f4SDimitry Andric new internal::TraversalMatcher<T>(TK, InnerMatcher), 15335ffd83dbSDimitry Andric ASTNodeKind::getFromNodeKind<T>()) 1534480093f4SDimitry Andric .template unconditionalConvertTo<T>(); 1535480093f4SDimitry Andric } 1536480093f4SDimitry Andric 1537fe6060f1SDimitry Andric template <typename T> operator Matcher<T>() && { 1538fe6060f1SDimitry Andric return internal::DynTypedMatcher::constructRestrictedWrapper( 1539fe6060f1SDimitry Andric new internal::TraversalMatcher<T>(TK, std::move(InnerMatcher)), 1540fe6060f1SDimitry Andric ASTNodeKind::getFromNodeKind<T>()) 1541fe6060f1SDimitry Andric .template unconditionalConvertTo<T>(); 1542fe6060f1SDimitry Andric } 1543fe6060f1SDimitry Andric 1544480093f4SDimitry Andric private: 15455ffd83dbSDimitry Andric TraversalKind TK; 1546480093f4SDimitry Andric MatcherType InnerMatcher; 15470b57cec5SDimitry Andric }; 15480b57cec5SDimitry Andric 1549fe6060f1SDimitry Andric /// A PolymorphicMatcher<MatcherT, P1, ..., PN> object can be 15500b57cec5SDimitry Andric /// created from N parameters p1, ..., pN (of type P1, ..., PN) and 15510b57cec5SDimitry Andric /// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN) 15520b57cec5SDimitry Andric /// can be constructed. 15530b57cec5SDimitry Andric /// 15540b57cec5SDimitry Andric /// For example: 1555fe6060f1SDimitry Andric /// - PolymorphicMatcher<IsDefinitionMatcher>() 15560b57cec5SDimitry Andric /// creates an object that can be used as a Matcher<T> for any type T 15570b57cec5SDimitry Andric /// where an IsDefinitionMatcher<T>() can be constructed. 1558fe6060f1SDimitry Andric /// - PolymorphicMatcher<ValueEqualsMatcher, int>(42) 15590b57cec5SDimitry Andric /// creates an object that can be used as a Matcher<T> for any type T 15600b57cec5SDimitry Andric /// where a ValueEqualsMatcher<T, int>(42) can be constructed. 1561fe6060f1SDimitry Andric template <template <typename T, typename... Params> class MatcherT, 1562fe6060f1SDimitry Andric typename ReturnTypesF, typename... ParamTypes> 1563fe6060f1SDimitry Andric class PolymorphicMatcher { 15640b57cec5SDimitry Andric public: 1565fe6060f1SDimitry Andric PolymorphicMatcher(const ParamTypes &... Params) : Params(Params...) {} 15660b57cec5SDimitry Andric 15670b57cec5SDimitry Andric using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; 15680b57cec5SDimitry Andric 156981ad6265SDimitry Andric template <typename T> operator Matcher<T>() const & { 15700b57cec5SDimitry Andric static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, 15710b57cec5SDimitry Andric "right polymorphic conversion"); 1572fe6060f1SDimitry Andric return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params)); 15730b57cec5SDimitry Andric } 15740b57cec5SDimitry Andric 1575fe6060f1SDimitry Andric template <typename T> operator Matcher<T>() && { 1576fe6060f1SDimitry Andric static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, 1577fe6060f1SDimitry Andric "right polymorphic conversion"); 1578fe6060f1SDimitry Andric return Matcher<T>( 1579fe6060f1SDimitry Andric new_from_tuple<MatcherT<T, ParamTypes...>>(std::move(Params))); 1580fe6060f1SDimitry Andric } 1581fe6060f1SDimitry Andric 15820b57cec5SDimitry Andric private: 1583fe6060f1SDimitry Andric std::tuple<ParamTypes...> Params; 15840b57cec5SDimitry Andric }; 15850b57cec5SDimitry Andric 15860b57cec5SDimitry Andric /// Matches nodes of type T that have child nodes of type ChildT for 15870b57cec5SDimitry Andric /// which a specified child matcher matches. 15880b57cec5SDimitry Andric /// 15890b57cec5SDimitry Andric /// ChildT must be an AST base type. 15900b57cec5SDimitry Andric template <typename T, typename ChildT> 15915ffd83dbSDimitry Andric class HasMatcher : public MatcherInterface<T> { 1592fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 15935ffd83dbSDimitry Andric 15940b57cec5SDimitry Andric public: 15955ffd83dbSDimitry Andric explicit HasMatcher(const Matcher<ChildT> &InnerMatcher) 15965ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher) {} 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 15990b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 16000b57cec5SDimitry Andric return Finder->matchesChildOf(Node, this->InnerMatcher, Builder, 16010b57cec5SDimitry Andric ASTMatchFinder::BK_First); 16020b57cec5SDimitry Andric } 16030b57cec5SDimitry Andric }; 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric /// Matches nodes of type T that have child nodes of type ChildT for 16060b57cec5SDimitry Andric /// which a specified child matcher matches. ChildT must be an AST base 16070b57cec5SDimitry Andric /// type. 16080b57cec5SDimitry Andric /// As opposed to the HasMatcher, the ForEachMatcher will produce a match 16090b57cec5SDimitry Andric /// for each child that matches. 16100b57cec5SDimitry Andric template <typename T, typename ChildT> 16115ffd83dbSDimitry Andric class ForEachMatcher : public MatcherInterface<T> { 16120b57cec5SDimitry Andric static_assert(IsBaseType<ChildT>::value, 16130b57cec5SDimitry Andric "for each only accepts base type matcher"); 16140b57cec5SDimitry Andric 1615fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 16165ffd83dbSDimitry Andric 16170b57cec5SDimitry Andric public: 16185ffd83dbSDimitry Andric explicit ForEachMatcher(const Matcher<ChildT> &InnerMatcher) 16195ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher) {} 16200b57cec5SDimitry Andric 16210b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 16220b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 16230b57cec5SDimitry Andric return Finder->matchesChildOf( 16240b57cec5SDimitry Andric Node, this->InnerMatcher, Builder, 16250b57cec5SDimitry Andric ASTMatchFinder::BK_All); 16260b57cec5SDimitry Andric } 16270b57cec5SDimitry Andric }; 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric /// @} 16300b57cec5SDimitry Andric 16310b57cec5SDimitry Andric template <typename T> 16320b57cec5SDimitry Andric inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const { 16330b57cec5SDimitry Andric return Matcher<T>(*this); 16340b57cec5SDimitry Andric } 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric /// Matches nodes of type T that have at least one descendant node of 16370b57cec5SDimitry Andric /// type DescendantT for which the given inner matcher matches. 16380b57cec5SDimitry Andric /// 16390b57cec5SDimitry Andric /// DescendantT must be an AST base type. 16400b57cec5SDimitry Andric template <typename T, typename DescendantT> 16415ffd83dbSDimitry Andric class HasDescendantMatcher : public MatcherInterface<T> { 16420b57cec5SDimitry Andric static_assert(IsBaseType<DescendantT>::value, 16430b57cec5SDimitry Andric "has descendant only accepts base type matcher"); 16440b57cec5SDimitry Andric 1645fe6060f1SDimitry Andric DynTypedMatcher DescendantMatcher; 16465ffd83dbSDimitry Andric 16470b57cec5SDimitry Andric public: 16480b57cec5SDimitry Andric explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher) 16495ffd83dbSDimitry Andric : DescendantMatcher(DescendantMatcher) {} 16500b57cec5SDimitry Andric 16510b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 16520b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 16535ffd83dbSDimitry Andric return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder, 16540b57cec5SDimitry Andric ASTMatchFinder::BK_First); 16550b57cec5SDimitry Andric } 16560b57cec5SDimitry Andric }; 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric /// Matches nodes of type \c T that have a parent node of type \c ParentT 16590b57cec5SDimitry Andric /// for which the given inner matcher matches. 16600b57cec5SDimitry Andric /// 16610b57cec5SDimitry Andric /// \c ParentT must be an AST base type. 16620b57cec5SDimitry Andric template <typename T, typename ParentT> 16635ffd83dbSDimitry Andric class HasParentMatcher : public MatcherInterface<T> { 16640b57cec5SDimitry Andric static_assert(IsBaseType<ParentT>::value, 16650b57cec5SDimitry Andric "has parent only accepts base type matcher"); 16660b57cec5SDimitry Andric 1667fe6060f1SDimitry Andric DynTypedMatcher ParentMatcher; 16685ffd83dbSDimitry Andric 16690b57cec5SDimitry Andric public: 16700b57cec5SDimitry Andric explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher) 16715ffd83dbSDimitry Andric : ParentMatcher(ParentMatcher) {} 16720b57cec5SDimitry Andric 16730b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 16740b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 16755ffd83dbSDimitry Andric return Finder->matchesAncestorOf(Node, this->ParentMatcher, Builder, 16760b57cec5SDimitry Andric ASTMatchFinder::AMM_ParentOnly); 16770b57cec5SDimitry Andric } 16780b57cec5SDimitry Andric }; 16790b57cec5SDimitry Andric 16800b57cec5SDimitry Andric /// Matches nodes of type \c T that have at least one ancestor node of 16810b57cec5SDimitry Andric /// type \c AncestorT for which the given inner matcher matches. 16820b57cec5SDimitry Andric /// 16830b57cec5SDimitry Andric /// \c AncestorT must be an AST base type. 16840b57cec5SDimitry Andric template <typename T, typename AncestorT> 16855ffd83dbSDimitry Andric class HasAncestorMatcher : public MatcherInterface<T> { 16860b57cec5SDimitry Andric static_assert(IsBaseType<AncestorT>::value, 16870b57cec5SDimitry Andric "has ancestor only accepts base type matcher"); 16880b57cec5SDimitry Andric 1689fe6060f1SDimitry Andric DynTypedMatcher AncestorMatcher; 16905ffd83dbSDimitry Andric 16910b57cec5SDimitry Andric public: 16920b57cec5SDimitry Andric explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher) 16935ffd83dbSDimitry Andric : AncestorMatcher(AncestorMatcher) {} 16940b57cec5SDimitry Andric 16950b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 16960b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 16975ffd83dbSDimitry Andric return Finder->matchesAncestorOf(Node, this->AncestorMatcher, Builder, 16980b57cec5SDimitry Andric ASTMatchFinder::AMM_All); 16990b57cec5SDimitry Andric } 17000b57cec5SDimitry Andric }; 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric /// Matches nodes of type T that have at least one descendant node of 17030b57cec5SDimitry Andric /// type DescendantT for which the given inner matcher matches. 17040b57cec5SDimitry Andric /// 17050b57cec5SDimitry Andric /// DescendantT must be an AST base type. 17060b57cec5SDimitry Andric /// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match 17070b57cec5SDimitry Andric /// for each descendant node that matches instead of only for the first. 17080b57cec5SDimitry Andric template <typename T, typename DescendantT> 17095ffd83dbSDimitry Andric class ForEachDescendantMatcher : public MatcherInterface<T> { 17100b57cec5SDimitry Andric static_assert(IsBaseType<DescendantT>::value, 17110b57cec5SDimitry Andric "for each descendant only accepts base type matcher"); 17120b57cec5SDimitry Andric 1713fe6060f1SDimitry Andric DynTypedMatcher DescendantMatcher; 17145ffd83dbSDimitry Andric 17150b57cec5SDimitry Andric public: 17160b57cec5SDimitry Andric explicit ForEachDescendantMatcher( 17170b57cec5SDimitry Andric const Matcher<DescendantT> &DescendantMatcher) 17185ffd83dbSDimitry Andric : DescendantMatcher(DescendantMatcher) {} 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 17210b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 17225ffd83dbSDimitry Andric return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder, 17230b57cec5SDimitry Andric ASTMatchFinder::BK_All); 17240b57cec5SDimitry Andric } 17250b57cec5SDimitry Andric }; 17260b57cec5SDimitry Andric 17270b57cec5SDimitry Andric /// Matches on nodes that have a getValue() method if getValue() equals 17280b57cec5SDimitry Andric /// the value the ValueEqualsMatcher was constructed with. 17290b57cec5SDimitry Andric template <typename T, typename ValueT> 17300b57cec5SDimitry Andric class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> { 17310b57cec5SDimitry Andric static_assert(std::is_base_of<CharacterLiteral, T>::value || 17320b57cec5SDimitry Andric std::is_base_of<CXXBoolLiteralExpr, T>::value || 17330b57cec5SDimitry Andric std::is_base_of<FloatingLiteral, T>::value || 17340b57cec5SDimitry Andric std::is_base_of<IntegerLiteral, T>::value, 17350b57cec5SDimitry Andric "the node must have a getValue method"); 17360b57cec5SDimitry Andric 17370b57cec5SDimitry Andric public: 17380b57cec5SDimitry Andric explicit ValueEqualsMatcher(const ValueT &ExpectedValue) 17390b57cec5SDimitry Andric : ExpectedValue(ExpectedValue) {} 17400b57cec5SDimitry Andric 17410b57cec5SDimitry Andric bool matchesNode(const T &Node) const override { 17420b57cec5SDimitry Andric return Node.getValue() == ExpectedValue; 17430b57cec5SDimitry Andric } 17440b57cec5SDimitry Andric 17450b57cec5SDimitry Andric private: 1746fe6060f1SDimitry Andric ValueT ExpectedValue; 17470b57cec5SDimitry Andric }; 17480b57cec5SDimitry Andric 17490b57cec5SDimitry Andric /// Template specializations to easily write matchers for floating point 17500b57cec5SDimitry Andric /// literals. 17510b57cec5SDimitry Andric template <> 17520b57cec5SDimitry Andric inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode( 17530b57cec5SDimitry Andric const FloatingLiteral &Node) const { 17540b57cec5SDimitry Andric if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle()) 17550b57cec5SDimitry Andric return Node.getValue().convertToFloat() == ExpectedValue; 17560b57cec5SDimitry Andric if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble()) 17570b57cec5SDimitry Andric return Node.getValue().convertToDouble() == ExpectedValue; 17580b57cec5SDimitry Andric return false; 17590b57cec5SDimitry Andric } 17600b57cec5SDimitry Andric template <> 17610b57cec5SDimitry Andric inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode( 17620b57cec5SDimitry Andric const FloatingLiteral &Node) const { 17630b57cec5SDimitry Andric if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle()) 17640b57cec5SDimitry Andric return Node.getValue().convertToFloat() == ExpectedValue; 17650b57cec5SDimitry Andric if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble()) 17660b57cec5SDimitry Andric return Node.getValue().convertToDouble() == ExpectedValue; 17670b57cec5SDimitry Andric return false; 17680b57cec5SDimitry Andric } 17690b57cec5SDimitry Andric template <> 17700b57cec5SDimitry Andric inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode( 17710b57cec5SDimitry Andric const FloatingLiteral &Node) const { 17720b57cec5SDimitry Andric return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual; 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric 17750b57cec5SDimitry Andric /// Matches nodes of type \c TLoc for which the inner 17760b57cec5SDimitry Andric /// \c Matcher<T> matches. 17770b57cec5SDimitry Andric template <typename TLoc, typename T> 17785ffd83dbSDimitry Andric class LocMatcher : public MatcherInterface<TLoc> { 1779fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 17805ffd83dbSDimitry Andric 17810b57cec5SDimitry Andric public: 17820b57cec5SDimitry Andric explicit LocMatcher(const Matcher<T> &InnerMatcher) 17835ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher) {} 17840b57cec5SDimitry Andric 17850b57cec5SDimitry Andric bool matches(const TLoc &Node, ASTMatchFinder *Finder, 17860b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 17870b57cec5SDimitry Andric if (!Node) 17880b57cec5SDimitry Andric return false; 17890b57cec5SDimitry Andric return this->InnerMatcher.matches(extract(Node), Finder, Builder); 17900b57cec5SDimitry Andric } 17910b57cec5SDimitry Andric 17920b57cec5SDimitry Andric private: 17935ffd83dbSDimitry Andric static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) { 17945ffd83dbSDimitry Andric return DynTypedNode::create(*Loc.getNestedNameSpecifier()); 17950b57cec5SDimitry Andric } 17960b57cec5SDimitry Andric }; 17970b57cec5SDimitry Andric 17980b57cec5SDimitry Andric /// Matches \c TypeLocs based on an inner matcher matching a certain 17990b57cec5SDimitry Andric /// \c QualType. 18000b57cec5SDimitry Andric /// 18010b57cec5SDimitry Andric /// Used to implement the \c loc() matcher. 18025ffd83dbSDimitry Andric class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> { 1803fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 18045ffd83dbSDimitry Andric 18050b57cec5SDimitry Andric public: 18060b57cec5SDimitry Andric explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher) 18075ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher) {} 18080b57cec5SDimitry Andric 18090b57cec5SDimitry Andric bool matches(const TypeLoc &Node, ASTMatchFinder *Finder, 18100b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 18110b57cec5SDimitry Andric if (!Node) 18120b57cec5SDimitry Andric return false; 18135ffd83dbSDimitry Andric return this->InnerMatcher.matches(DynTypedNode::create(Node.getType()), 18145ffd83dbSDimitry Andric Finder, Builder); 18150b57cec5SDimitry Andric } 18160b57cec5SDimitry Andric }; 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric /// Matches nodes of type \c T for which the inner matcher matches on a 18190b57cec5SDimitry Andric /// another node of type \c T that can be reached using a given traverse 18200b57cec5SDimitry Andric /// function. 18215ffd83dbSDimitry Andric template <typename T> class TypeTraverseMatcher : public MatcherInterface<T> { 1822fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 18235ffd83dbSDimitry Andric 18240b57cec5SDimitry Andric public: 18250b57cec5SDimitry Andric explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher, 18260b57cec5SDimitry Andric QualType (T::*TraverseFunction)() const) 18275ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} 18280b57cec5SDimitry Andric 18290b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 18300b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 18310b57cec5SDimitry Andric QualType NextNode = (Node.*TraverseFunction)(); 18320b57cec5SDimitry Andric if (NextNode.isNull()) 18330b57cec5SDimitry Andric return false; 18345ffd83dbSDimitry Andric return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder, 18355ffd83dbSDimitry Andric Builder); 18360b57cec5SDimitry Andric } 18370b57cec5SDimitry Andric 18380b57cec5SDimitry Andric private: 18390b57cec5SDimitry Andric QualType (T::*TraverseFunction)() const; 18400b57cec5SDimitry Andric }; 18410b57cec5SDimitry Andric 18420b57cec5SDimitry Andric /// Matches nodes of type \c T in a ..Loc hierarchy, for which the inner 18430b57cec5SDimitry Andric /// matcher matches on a another node of type \c T that can be reached using a 18440b57cec5SDimitry Andric /// given traverse function. 18450b57cec5SDimitry Andric template <typename T> 18465ffd83dbSDimitry Andric class TypeLocTraverseMatcher : public MatcherInterface<T> { 1847fe6060f1SDimitry Andric DynTypedMatcher InnerMatcher; 18485ffd83dbSDimitry Andric 18490b57cec5SDimitry Andric public: 18500b57cec5SDimitry Andric explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher, 18510b57cec5SDimitry Andric TypeLoc (T::*TraverseFunction)() const) 18525ffd83dbSDimitry Andric : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} 18530b57cec5SDimitry Andric 18540b57cec5SDimitry Andric bool matches(const T &Node, ASTMatchFinder *Finder, 18550b57cec5SDimitry Andric BoundNodesTreeBuilder *Builder) const override { 18560b57cec5SDimitry Andric TypeLoc NextNode = (Node.*TraverseFunction)(); 18570b57cec5SDimitry Andric if (!NextNode) 18580b57cec5SDimitry Andric return false; 18595ffd83dbSDimitry Andric return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder, 18605ffd83dbSDimitry Andric Builder); 18610b57cec5SDimitry Andric } 18620b57cec5SDimitry Andric 18630b57cec5SDimitry Andric private: 18640b57cec5SDimitry Andric TypeLoc (T::*TraverseFunction)() const; 18650b57cec5SDimitry Andric }; 18660b57cec5SDimitry Andric 18670b57cec5SDimitry Andric /// Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where 18680b57cec5SDimitry Andric /// \c OuterT is any type that is supported by \c Getter. 18690b57cec5SDimitry Andric /// 18700b57cec5SDimitry Andric /// \code Getter<OuterT>::value() \endcode returns a 18710b57cec5SDimitry Andric /// \code InnerTBase (OuterT::*)() \endcode, which is used to adapt a \c OuterT 18720b57cec5SDimitry Andric /// object into a \c InnerT 18730b57cec5SDimitry Andric template <typename InnerTBase, 18740b57cec5SDimitry Andric template <typename OuterT> class Getter, 18750b57cec5SDimitry Andric template <typename OuterT> class MatcherImpl, 18760b57cec5SDimitry Andric typename ReturnTypesF> 18770b57cec5SDimitry Andric class TypeTraversePolymorphicMatcher { 18780b57cec5SDimitry Andric private: 18790b57cec5SDimitry Andric using Self = TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, 18800b57cec5SDimitry Andric ReturnTypesF>; 18810b57cec5SDimitry Andric 18820b57cec5SDimitry Andric static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers); 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric public: 18850b57cec5SDimitry Andric using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; 18860b57cec5SDimitry Andric 18870b57cec5SDimitry Andric explicit TypeTraversePolymorphicMatcher( 18880b57cec5SDimitry Andric ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) 18890b57cec5SDimitry Andric : InnerMatcher(makeAllOfComposite(InnerMatchers)) {} 18900b57cec5SDimitry Andric 18910b57cec5SDimitry Andric template <typename OuterT> operator Matcher<OuterT>() const { 18920b57cec5SDimitry Andric return Matcher<OuterT>( 18930b57cec5SDimitry Andric new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value())); 18940b57cec5SDimitry Andric } 18950b57cec5SDimitry Andric 18960b57cec5SDimitry Andric struct Func 18970b57cec5SDimitry Andric : public VariadicFunction<Self, Matcher<InnerTBase>, &Self::create> { 18980b57cec5SDimitry Andric Func() {} 18990b57cec5SDimitry Andric }; 19000b57cec5SDimitry Andric 19010b57cec5SDimitry Andric private: 1902fe6060f1SDimitry Andric Matcher<InnerTBase> InnerMatcher; 19030b57cec5SDimitry Andric }; 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric /// A simple memoizer of T(*)() functions. 19060b57cec5SDimitry Andric /// 19070b57cec5SDimitry Andric /// It will call the passed 'Func' template parameter at most once. 19080b57cec5SDimitry Andric /// Used to support AST_MATCHER_FUNCTION() macro. 19090b57cec5SDimitry Andric template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher { 19100b57cec5SDimitry Andric struct Wrapper { 19110b57cec5SDimitry Andric Wrapper() : M(Func()) {} 19120b57cec5SDimitry Andric 19130b57cec5SDimitry Andric Matcher M; 19140b57cec5SDimitry Andric }; 19150b57cec5SDimitry Andric 19160b57cec5SDimitry Andric public: 19170b57cec5SDimitry Andric static const Matcher &getInstance() { 19180b57cec5SDimitry Andric static llvm::ManagedStatic<Wrapper> Instance; 19190b57cec5SDimitry Andric return Instance->M; 19200b57cec5SDimitry Andric } 19210b57cec5SDimitry Andric }; 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric // Define the create() method out of line to silence a GCC warning about 19240b57cec5SDimitry Andric // the struct "Func" having greater visibility than its base, which comes from 19250b57cec5SDimitry Andric // using the flag -fvisibility-inlines-hidden. 19260b57cec5SDimitry Andric template <typename InnerTBase, template <typename OuterT> class Getter, 19270b57cec5SDimitry Andric template <typename OuterT> class MatcherImpl, typename ReturnTypesF> 19280b57cec5SDimitry Andric TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF> 19290b57cec5SDimitry Andric TypeTraversePolymorphicMatcher< 19300b57cec5SDimitry Andric InnerTBase, Getter, MatcherImpl, 19310b57cec5SDimitry Andric ReturnTypesF>::create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) { 19320b57cec5SDimitry Andric return Self(InnerMatchers); 19330b57cec5SDimitry Andric } 19340b57cec5SDimitry Andric 19350b57cec5SDimitry Andric // FIXME: unify ClassTemplateSpecializationDecl and TemplateSpecializationType's 19360b57cec5SDimitry Andric // APIs for accessing the template argument list. 19370b57cec5SDimitry Andric inline ArrayRef<TemplateArgument> 19380b57cec5SDimitry Andric getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) { 19390b57cec5SDimitry Andric return D.getTemplateArgs().asArray(); 19400b57cec5SDimitry Andric } 19410b57cec5SDimitry Andric 19420b57cec5SDimitry Andric inline ArrayRef<TemplateArgument> 19430b57cec5SDimitry Andric getTemplateSpecializationArgs(const TemplateSpecializationType &T) { 1944bdd1243dSDimitry Andric return T.template_arguments(); 19450b57cec5SDimitry Andric } 19460b57cec5SDimitry Andric 19470b57cec5SDimitry Andric inline ArrayRef<TemplateArgument> 19480b57cec5SDimitry Andric getTemplateSpecializationArgs(const FunctionDecl &FD) { 19490b57cec5SDimitry Andric if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs()) 19500b57cec5SDimitry Andric return TemplateArgs->asArray(); 19510b57cec5SDimitry Andric return ArrayRef<TemplateArgument>(); 19520b57cec5SDimitry Andric } 19530b57cec5SDimitry Andric 19540b57cec5SDimitry Andric struct NotEqualsBoundNodePredicate { 19550b57cec5SDimitry Andric bool operator()(const internal::BoundNodesMap &Nodes) const { 19560b57cec5SDimitry Andric return Nodes.getNode(ID) != Node; 19570b57cec5SDimitry Andric } 19580b57cec5SDimitry Andric 19590b57cec5SDimitry Andric std::string ID; 19605ffd83dbSDimitry Andric DynTypedNode Node; 19610b57cec5SDimitry Andric }; 19620b57cec5SDimitry Andric 1963e8d8bef9SDimitry Andric template <typename Ty, typename Enable = void> struct GetBodyMatcher { 1964e8d8bef9SDimitry Andric static const Stmt *get(const Ty &Node) { return Node.getBody(); } 1965e8d8bef9SDimitry Andric }; 1966e8d8bef9SDimitry Andric 19670b57cec5SDimitry Andric template <typename Ty> 1968bdd1243dSDimitry Andric struct GetBodyMatcher< 1969bdd1243dSDimitry Andric Ty, std::enable_if_t<std::is_base_of<FunctionDecl, Ty>::value>> { 19700b57cec5SDimitry Andric static const Stmt *get(const Ty &Node) { 1971e8d8bef9SDimitry Andric return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr; 19720b57cec5SDimitry Andric } 19730b57cec5SDimitry Andric }; 19740b57cec5SDimitry Andric 1975e8d8bef9SDimitry Andric template <typename NodeType> 1976bdd1243dSDimitry Andric inline std::optional<BinaryOperatorKind> 1977e8d8bef9SDimitry Andric equivalentBinaryOperator(const NodeType &Node) { 1978e8d8bef9SDimitry Andric return Node.getOpcode(); 1979e8d8bef9SDimitry Andric } 1980e8d8bef9SDimitry Andric 19810b57cec5SDimitry Andric template <> 1982bdd1243dSDimitry Andric inline std::optional<BinaryOperatorKind> 1983e8d8bef9SDimitry Andric equivalentBinaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { 1984e8d8bef9SDimitry Andric if (Node.getNumArgs() != 2) 1985bdd1243dSDimitry Andric return std::nullopt; 1986e8d8bef9SDimitry Andric switch (Node.getOperator()) { 1987e8d8bef9SDimitry Andric default: 1988bdd1243dSDimitry Andric return std::nullopt; 1989e8d8bef9SDimitry Andric case OO_ArrowStar: 1990e8d8bef9SDimitry Andric return BO_PtrMemI; 1991e8d8bef9SDimitry Andric case OO_Star: 1992e8d8bef9SDimitry Andric return BO_Mul; 1993e8d8bef9SDimitry Andric case OO_Slash: 1994e8d8bef9SDimitry Andric return BO_Div; 1995e8d8bef9SDimitry Andric case OO_Percent: 1996e8d8bef9SDimitry Andric return BO_Rem; 1997e8d8bef9SDimitry Andric case OO_Plus: 1998e8d8bef9SDimitry Andric return BO_Add; 1999e8d8bef9SDimitry Andric case OO_Minus: 2000e8d8bef9SDimitry Andric return BO_Sub; 2001e8d8bef9SDimitry Andric case OO_LessLess: 2002e8d8bef9SDimitry Andric return BO_Shl; 2003e8d8bef9SDimitry Andric case OO_GreaterGreater: 2004e8d8bef9SDimitry Andric return BO_Shr; 2005e8d8bef9SDimitry Andric case OO_Spaceship: 2006e8d8bef9SDimitry Andric return BO_Cmp; 2007e8d8bef9SDimitry Andric case OO_Less: 2008e8d8bef9SDimitry Andric return BO_LT; 2009e8d8bef9SDimitry Andric case OO_Greater: 2010e8d8bef9SDimitry Andric return BO_GT; 2011e8d8bef9SDimitry Andric case OO_LessEqual: 2012e8d8bef9SDimitry Andric return BO_LE; 2013e8d8bef9SDimitry Andric case OO_GreaterEqual: 2014e8d8bef9SDimitry Andric return BO_GE; 2015e8d8bef9SDimitry Andric case OO_EqualEqual: 2016e8d8bef9SDimitry Andric return BO_EQ; 2017e8d8bef9SDimitry Andric case OO_ExclaimEqual: 2018e8d8bef9SDimitry Andric return BO_NE; 2019e8d8bef9SDimitry Andric case OO_Amp: 2020e8d8bef9SDimitry Andric return BO_And; 2021e8d8bef9SDimitry Andric case OO_Caret: 2022e8d8bef9SDimitry Andric return BO_Xor; 2023e8d8bef9SDimitry Andric case OO_Pipe: 2024e8d8bef9SDimitry Andric return BO_Or; 2025e8d8bef9SDimitry Andric case OO_AmpAmp: 2026e8d8bef9SDimitry Andric return BO_LAnd; 2027e8d8bef9SDimitry Andric case OO_PipePipe: 2028e8d8bef9SDimitry Andric return BO_LOr; 2029e8d8bef9SDimitry Andric case OO_Equal: 2030e8d8bef9SDimitry Andric return BO_Assign; 2031e8d8bef9SDimitry Andric case OO_StarEqual: 2032e8d8bef9SDimitry Andric return BO_MulAssign; 2033e8d8bef9SDimitry Andric case OO_SlashEqual: 2034e8d8bef9SDimitry Andric return BO_DivAssign; 2035e8d8bef9SDimitry Andric case OO_PercentEqual: 2036e8d8bef9SDimitry Andric return BO_RemAssign; 2037e8d8bef9SDimitry Andric case OO_PlusEqual: 2038e8d8bef9SDimitry Andric return BO_AddAssign; 2039e8d8bef9SDimitry Andric case OO_MinusEqual: 2040e8d8bef9SDimitry Andric return BO_SubAssign; 2041e8d8bef9SDimitry Andric case OO_LessLessEqual: 2042e8d8bef9SDimitry Andric return BO_ShlAssign; 2043e8d8bef9SDimitry Andric case OO_GreaterGreaterEqual: 2044e8d8bef9SDimitry Andric return BO_ShrAssign; 2045e8d8bef9SDimitry Andric case OO_AmpEqual: 2046e8d8bef9SDimitry Andric return BO_AndAssign; 2047e8d8bef9SDimitry Andric case OO_CaretEqual: 2048e8d8bef9SDimitry Andric return BO_XorAssign; 2049e8d8bef9SDimitry Andric case OO_PipeEqual: 2050e8d8bef9SDimitry Andric return BO_OrAssign; 2051e8d8bef9SDimitry Andric case OO_Comma: 2052e8d8bef9SDimitry Andric return BO_Comma; 2053e8d8bef9SDimitry Andric } 2054e8d8bef9SDimitry Andric } 2055e8d8bef9SDimitry Andric 2056e8d8bef9SDimitry Andric template <typename NodeType> 2057bdd1243dSDimitry Andric inline std::optional<UnaryOperatorKind> 2058e8d8bef9SDimitry Andric equivalentUnaryOperator(const NodeType &Node) { 2059e8d8bef9SDimitry Andric return Node.getOpcode(); 2060e8d8bef9SDimitry Andric } 2061e8d8bef9SDimitry Andric 2062e8d8bef9SDimitry Andric template <> 2063bdd1243dSDimitry Andric inline std::optional<UnaryOperatorKind> 2064e8d8bef9SDimitry Andric equivalentUnaryOperator<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { 2065fe6060f1SDimitry Andric if (Node.getNumArgs() != 1 && Node.getOperator() != OO_PlusPlus && 2066fe6060f1SDimitry Andric Node.getOperator() != OO_MinusMinus) 2067bdd1243dSDimitry Andric return std::nullopt; 2068e8d8bef9SDimitry Andric switch (Node.getOperator()) { 2069e8d8bef9SDimitry Andric default: 2070bdd1243dSDimitry Andric return std::nullopt; 2071e8d8bef9SDimitry Andric case OO_Plus: 2072e8d8bef9SDimitry Andric return UO_Plus; 2073e8d8bef9SDimitry Andric case OO_Minus: 2074e8d8bef9SDimitry Andric return UO_Minus; 2075e8d8bef9SDimitry Andric case OO_Amp: 2076e8d8bef9SDimitry Andric return UO_AddrOf; 2077fe6060f1SDimitry Andric case OO_Star: 2078fe6060f1SDimitry Andric return UO_Deref; 2079e8d8bef9SDimitry Andric case OO_Tilde: 2080e8d8bef9SDimitry Andric return UO_Not; 2081e8d8bef9SDimitry Andric case OO_Exclaim: 2082e8d8bef9SDimitry Andric return UO_LNot; 2083e8d8bef9SDimitry Andric case OO_PlusPlus: { 2084e8d8bef9SDimitry Andric const auto *FD = Node.getDirectCallee(); 2085e8d8bef9SDimitry Andric if (!FD) 2086bdd1243dSDimitry Andric return std::nullopt; 2087e8d8bef9SDimitry Andric return FD->getNumParams() > 0 ? UO_PostInc : UO_PreInc; 2088e8d8bef9SDimitry Andric } 2089e8d8bef9SDimitry Andric case OO_MinusMinus: { 2090e8d8bef9SDimitry Andric const auto *FD = Node.getDirectCallee(); 2091e8d8bef9SDimitry Andric if (!FD) 2092bdd1243dSDimitry Andric return std::nullopt; 2093e8d8bef9SDimitry Andric return FD->getNumParams() > 0 ? UO_PostDec : UO_PreDec; 2094e8d8bef9SDimitry Andric } 2095e8d8bef9SDimitry Andric case OO_Coawait: 2096e8d8bef9SDimitry Andric return UO_Coawait; 2097e8d8bef9SDimitry Andric } 2098e8d8bef9SDimitry Andric } 2099e8d8bef9SDimitry Andric 2100e8d8bef9SDimitry Andric template <typename NodeType> inline const Expr *getLHS(const NodeType &Node) { 2101e8d8bef9SDimitry Andric return Node.getLHS(); 2102e8d8bef9SDimitry Andric } 2103e8d8bef9SDimitry Andric template <> 2104e8d8bef9SDimitry Andric inline const Expr * 2105e8d8bef9SDimitry Andric getLHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { 2106e8d8bef9SDimitry Andric if (!internal::equivalentBinaryOperator(Node)) 2107e8d8bef9SDimitry Andric return nullptr; 2108e8d8bef9SDimitry Andric return Node.getArg(0); 2109e8d8bef9SDimitry Andric } 2110e8d8bef9SDimitry Andric template <typename NodeType> inline const Expr *getRHS(const NodeType &Node) { 2111e8d8bef9SDimitry Andric return Node.getRHS(); 2112e8d8bef9SDimitry Andric } 2113e8d8bef9SDimitry Andric template <> 2114e8d8bef9SDimitry Andric inline const Expr * 2115e8d8bef9SDimitry Andric getRHS<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { 2116e8d8bef9SDimitry Andric if (!internal::equivalentBinaryOperator(Node)) 2117e8d8bef9SDimitry Andric return nullptr; 2118e8d8bef9SDimitry Andric return Node.getArg(1); 2119e8d8bef9SDimitry Andric } 2120e8d8bef9SDimitry Andric template <typename NodeType> 2121e8d8bef9SDimitry Andric inline const Expr *getSubExpr(const NodeType &Node) { 2122e8d8bef9SDimitry Andric return Node.getSubExpr(); 2123e8d8bef9SDimitry Andric } 2124e8d8bef9SDimitry Andric template <> 2125e8d8bef9SDimitry Andric inline const Expr * 2126e8d8bef9SDimitry Andric getSubExpr<CXXOperatorCallExpr>(const CXXOperatorCallExpr &Node) { 2127e8d8bef9SDimitry Andric if (!internal::equivalentUnaryOperator(Node)) 2128e8d8bef9SDimitry Andric return nullptr; 2129e8d8bef9SDimitry Andric return Node.getArg(0); 21300b57cec5SDimitry Andric } 21310b57cec5SDimitry Andric 21320b57cec5SDimitry Andric template <typename Ty> 21330b57cec5SDimitry Andric struct HasSizeMatcher { 21340b57cec5SDimitry Andric static bool hasSize(const Ty &Node, unsigned int N) { 21350b57cec5SDimitry Andric return Node.getSize() == N; 21360b57cec5SDimitry Andric } 21370b57cec5SDimitry Andric }; 21380b57cec5SDimitry Andric 21390b57cec5SDimitry Andric template <> 21400b57cec5SDimitry Andric inline bool HasSizeMatcher<StringLiteral>::hasSize( 21410b57cec5SDimitry Andric const StringLiteral &Node, unsigned int N) { 21420b57cec5SDimitry Andric return Node.getLength() == N; 21430b57cec5SDimitry Andric } 21440b57cec5SDimitry Andric 21450b57cec5SDimitry Andric template <typename Ty> 21460b57cec5SDimitry Andric struct GetSourceExpressionMatcher { 21470b57cec5SDimitry Andric static const Expr *get(const Ty &Node) { 21480b57cec5SDimitry Andric return Node.getSubExpr(); 21490b57cec5SDimitry Andric } 21500b57cec5SDimitry Andric }; 21510b57cec5SDimitry Andric 21520b57cec5SDimitry Andric template <> 21530b57cec5SDimitry Andric inline const Expr *GetSourceExpressionMatcher<OpaqueValueExpr>::get( 21540b57cec5SDimitry Andric const OpaqueValueExpr &Node) { 21550b57cec5SDimitry Andric return Node.getSourceExpr(); 21560b57cec5SDimitry Andric } 21570b57cec5SDimitry Andric 21580b57cec5SDimitry Andric template <typename Ty> 21590b57cec5SDimitry Andric struct CompoundStmtMatcher { 21600b57cec5SDimitry Andric static const CompoundStmt *get(const Ty &Node) { 21610b57cec5SDimitry Andric return &Node; 21620b57cec5SDimitry Andric } 21630b57cec5SDimitry Andric }; 21640b57cec5SDimitry Andric 21650b57cec5SDimitry Andric template <> 21660b57cec5SDimitry Andric inline const CompoundStmt * 21670b57cec5SDimitry Andric CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) { 21680b57cec5SDimitry Andric return Node.getSubStmt(); 21690b57cec5SDimitry Andric } 21700b57cec5SDimitry Andric 21715ffd83dbSDimitry Andric /// If \p Loc is (transitively) expanded from macro \p MacroName, returns the 21725ffd83dbSDimitry Andric /// location (in the chain of expansions) at which \p MacroName was 21735ffd83dbSDimitry Andric /// expanded. Since the macro may have been expanded inside a series of 21745ffd83dbSDimitry Andric /// expansions, that location may itself be a MacroID. 2175bdd1243dSDimitry Andric std::optional<SourceLocation> getExpansionLocOfMacro(StringRef MacroName, 2176bdd1243dSDimitry Andric SourceLocation Loc, 21775ffd83dbSDimitry Andric const ASTContext &Context); 21785ffd83dbSDimitry Andric 2179bdd1243dSDimitry Andric inline std::optional<StringRef> getOpName(const UnaryOperator &Node) { 2180e8d8bef9SDimitry Andric return Node.getOpcodeStr(Node.getOpcode()); 2181e8d8bef9SDimitry Andric } 2182bdd1243dSDimitry Andric inline std::optional<StringRef> getOpName(const BinaryOperator &Node) { 2183e8d8bef9SDimitry Andric return Node.getOpcodeStr(); 2184e8d8bef9SDimitry Andric } 2185e8d8bef9SDimitry Andric inline StringRef getOpName(const CXXRewrittenBinaryOperator &Node) { 2186e8d8bef9SDimitry Andric return Node.getOpcodeStr(); 2187e8d8bef9SDimitry Andric } 2188bdd1243dSDimitry Andric inline std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) { 2189e8d8bef9SDimitry Andric auto optBinaryOpcode = equivalentBinaryOperator(Node); 2190e8d8bef9SDimitry Andric if (!optBinaryOpcode) { 2191e8d8bef9SDimitry Andric auto optUnaryOpcode = equivalentUnaryOperator(Node); 2192e8d8bef9SDimitry Andric if (!optUnaryOpcode) 2193bdd1243dSDimitry Andric return std::nullopt; 2194e8d8bef9SDimitry Andric return UnaryOperator::getOpcodeStr(*optUnaryOpcode); 2195e8d8bef9SDimitry Andric } 2196e8d8bef9SDimitry Andric return BinaryOperator::getOpcodeStr(*optBinaryOpcode); 2197e8d8bef9SDimitry Andric } 21987a6dacacSDimitry Andric inline StringRef getOpName(const CXXFoldExpr &Node) { 21997a6dacacSDimitry Andric return BinaryOperator::getOpcodeStr(Node.getOperator()); 22007a6dacacSDimitry Andric } 2201e8d8bef9SDimitry Andric 22025ffd83dbSDimitry Andric /// Matches overloaded operators with a specific name. 22035ffd83dbSDimitry Andric /// 22045ffd83dbSDimitry Andric /// The type argument ArgT is not used by this matcher but is used by 2205fe6060f1SDimitry Andric /// PolymorphicMatcher and should be std::vector<std::string>>. 22065ffd83dbSDimitry Andric template <typename T, typename ArgT = std::vector<std::string>> 22075ffd83dbSDimitry Andric class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> { 22085ffd83dbSDimitry Andric static_assert(std::is_same<T, BinaryOperator>::value || 2209e8d8bef9SDimitry Andric std::is_same<T, CXXOperatorCallExpr>::value || 2210e8d8bef9SDimitry Andric std::is_same<T, CXXRewrittenBinaryOperator>::value || 22115ffd83dbSDimitry Andric std::is_same<T, UnaryOperator>::value, 2212e8d8bef9SDimitry Andric "Matcher only supports `BinaryOperator`, `UnaryOperator`, " 2213e8d8bef9SDimitry Andric "`CXXOperatorCallExpr` and `CXXRewrittenBinaryOperator`"); 22145ffd83dbSDimitry Andric static_assert(std::is_same<ArgT, std::vector<std::string>>::value, 22155ffd83dbSDimitry Andric "Matcher ArgT must be std::vector<std::string>"); 22165ffd83dbSDimitry Andric 22175ffd83dbSDimitry Andric public: 22185ffd83dbSDimitry Andric explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names) 22195ffd83dbSDimitry Andric : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {} 22205ffd83dbSDimitry Andric 22215ffd83dbSDimitry Andric bool matchesNode(const T &Node) const override { 2222bdd1243dSDimitry Andric std::optional<StringRef> OptOpName = getOpName(Node); 2223349cc55cSDimitry Andric return OptOpName && llvm::is_contained(Names, *OptOpName); 22245ffd83dbSDimitry Andric } 22255ffd83dbSDimitry Andric 22265ffd83dbSDimitry Andric private: 2227bdd1243dSDimitry Andric static std::optional<StringRef> getOpName(const UnaryOperator &Node) { 22285ffd83dbSDimitry Andric return Node.getOpcodeStr(Node.getOpcode()); 22295ffd83dbSDimitry Andric } 2230bdd1243dSDimitry Andric static std::optional<StringRef> getOpName(const BinaryOperator &Node) { 22315ffd83dbSDimitry Andric return Node.getOpcodeStr(); 22325ffd83dbSDimitry Andric } 2233e8d8bef9SDimitry Andric static StringRef getOpName(const CXXRewrittenBinaryOperator &Node) { 2234e8d8bef9SDimitry Andric return Node.getOpcodeStr(); 2235e8d8bef9SDimitry Andric } 2236bdd1243dSDimitry Andric static std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) { 2237e8d8bef9SDimitry Andric auto optBinaryOpcode = equivalentBinaryOperator(Node); 2238e8d8bef9SDimitry Andric if (!optBinaryOpcode) { 2239e8d8bef9SDimitry Andric auto optUnaryOpcode = equivalentUnaryOperator(Node); 2240e8d8bef9SDimitry Andric if (!optUnaryOpcode) 2241bdd1243dSDimitry Andric return std::nullopt; 2242e8d8bef9SDimitry Andric return UnaryOperator::getOpcodeStr(*optUnaryOpcode); 2243e8d8bef9SDimitry Andric } 2244e8d8bef9SDimitry Andric return BinaryOperator::getOpcodeStr(*optBinaryOpcode); 2245e8d8bef9SDimitry Andric } 22465ffd83dbSDimitry Andric 2247fe6060f1SDimitry Andric std::vector<std::string> Names; 22485ffd83dbSDimitry Andric }; 22495ffd83dbSDimitry Andric 2250fe6060f1SDimitry Andric using HasOpNameMatcher = 2251fe6060f1SDimitry Andric PolymorphicMatcher<HasAnyOperatorNameMatcher, 2252fe6060f1SDimitry Andric void( 2253fe6060f1SDimitry Andric TypeList<BinaryOperator, CXXOperatorCallExpr, 2254fe6060f1SDimitry Andric CXXRewrittenBinaryOperator, UnaryOperator>), 2255fe6060f1SDimitry Andric std::vector<std::string>>; 22565ffd83dbSDimitry Andric 22575ffd83dbSDimitry Andric HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs); 22585ffd83dbSDimitry Andric 2259fe6060f1SDimitry Andric using HasOverloadOpNameMatcher = 2260fe6060f1SDimitry Andric PolymorphicMatcher<HasOverloadedOperatorNameMatcher, 2261fe6060f1SDimitry Andric void(TypeList<CXXOperatorCallExpr, FunctionDecl>), 2262fe6060f1SDimitry Andric std::vector<std::string>>; 22635ffd83dbSDimitry Andric 22645ffd83dbSDimitry Andric HasOverloadOpNameMatcher 22655ffd83dbSDimitry Andric hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs); 22665ffd83dbSDimitry Andric 22675ffd83dbSDimitry Andric /// Returns true if \p Node has a base specifier matching \p BaseSpec. 22685ffd83dbSDimitry Andric /// 22695ffd83dbSDimitry Andric /// A class is not considered to be derived from itself. 22705ffd83dbSDimitry Andric bool matchesAnyBase(const CXXRecordDecl &Node, 22715ffd83dbSDimitry Andric const Matcher<CXXBaseSpecifier> &BaseSpecMatcher, 22725ffd83dbSDimitry Andric ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder); 22735ffd83dbSDimitry Andric 22745ffd83dbSDimitry Andric std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex, 22755ffd83dbSDimitry Andric llvm::Regex::RegexFlags Flags, 22765ffd83dbSDimitry Andric StringRef MatcherID); 22775ffd83dbSDimitry Andric 2278349cc55cSDimitry Andric inline bool 2279349cc55cSDimitry Andric MatchTemplateArgLocAt(const DeclRefExpr &Node, unsigned int Index, 2280349cc55cSDimitry Andric internal::Matcher<TemplateArgumentLoc> InnerMatcher, 2281349cc55cSDimitry Andric internal::ASTMatchFinder *Finder, 2282349cc55cSDimitry Andric internal::BoundNodesTreeBuilder *Builder) { 2283349cc55cSDimitry Andric llvm::ArrayRef<TemplateArgumentLoc> ArgLocs = Node.template_arguments(); 2284349cc55cSDimitry Andric return Index < ArgLocs.size() && 2285349cc55cSDimitry Andric InnerMatcher.matches(ArgLocs[Index], Finder, Builder); 2286349cc55cSDimitry Andric } 2287349cc55cSDimitry Andric 2288349cc55cSDimitry Andric inline bool 2289349cc55cSDimitry Andric MatchTemplateArgLocAt(const TemplateSpecializationTypeLoc &Node, 2290349cc55cSDimitry Andric unsigned int Index, 2291349cc55cSDimitry Andric internal::Matcher<TemplateArgumentLoc> InnerMatcher, 2292349cc55cSDimitry Andric internal::ASTMatchFinder *Finder, 2293349cc55cSDimitry Andric internal::BoundNodesTreeBuilder *Builder) { 2294349cc55cSDimitry Andric return !Node.isNull() && Index < Node.getNumArgs() && 2295349cc55cSDimitry Andric InnerMatcher.matches(Node.getArgLoc(Index), Finder, Builder); 2296349cc55cSDimitry Andric } 2297349cc55cSDimitry Andric 22980b57cec5SDimitry Andric } // namespace internal 22990b57cec5SDimitry Andric 23000b57cec5SDimitry Andric } // namespace ast_matchers 23010b57cec5SDimitry Andric 23020b57cec5SDimitry Andric } // namespace clang 23030b57cec5SDimitry Andric 23040b57cec5SDimitry Andric #endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H 2305