//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Implements the base layer of the matcher framework. // // Matchers are methods that return a Matcher which provides a method // Matches(...) which is a predicate on an AST node. The Matches method's // parameters define the context of the match, which allows matchers to recurse // or store the current node as bound to a specific string, so that it can be // retrieved later. // // In general, matchers have two parts: // 1. A function Matcher MatcherName() which returns a Matcher // based on the arguments and optionally on template type deduction based // on the arguments. Matchers form an implicit reverse hierarchy // to clang's AST class hierarchy, meaning that you can use a Matcher // everywhere a Matcher is required. // 2. An implementation of a class derived from MatcherInterface. // // The matcher functions are defined in ASTMatchers.h. To make it possible // to implement both the matcher function and the implementation of the matcher // interface in one place, ASTMatcherMacros.h defines macros that allow // implementing a matcher in a single place. // // This file contains the base classes needed to construct the actual matchers. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/VariadicFunction.h" #include "llvm/Support/type_traits.h" #include #include #include namespace clang { namespace ast_matchers { /// FIXME: Move into the llvm support library. template struct CompileAssert {}; #define TOOLING_COMPILE_ASSERT(Expr, Msg) \ typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1] class BoundNodes; namespace internal { /// \brief Internal version of BoundNodes. Holds all the bound nodes. class BoundNodesMap { public: /// \brief Adds \c Node to the map with key \c ID. /// /// The node's base type should be in NodeBaseType or it will be unaccessible. template void addNode(StringRef ID, const T* Node) { NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node); } /// \brief Returns the AST node bound to \c ID. /// /// Returns NULL if there was no node bound to \c ID or if there is a node but /// it cannot be converted to the specified type. template const T *getNodeAs(StringRef ID) const { IDToNodeMap::const_iterator It = NodeMap.find(ID); if (It == NodeMap.end()) { return NULL; } return It->second.get(); } ast_type_traits::DynTypedNode getNode(StringRef ID) const { IDToNodeMap::const_iterator It = NodeMap.find(ID); if (It == NodeMap.end()) { return ast_type_traits::DynTypedNode(); } return It->second; } /// \brief Imposes an order on BoundNodesMaps. bool operator<(const BoundNodesMap &Other) const { return NodeMap < Other.NodeMap; } /// \brief A map from IDs to the bound nodes. /// /// Note that we're using std::map here, as for memoization: /// - we need a comparison operator /// - we need an assignment operator typedef std::map IDToNodeMap; const IDToNodeMap &getMap() const { return NodeMap; } private: IDToNodeMap NodeMap; }; /// \brief Creates BoundNodesTree objects. /// /// The tree builder is used during the matching process to insert the bound /// nodes from the Id matcher. class BoundNodesTreeBuilder { public: /// \brief A visitor interface to visit all BoundNodes results for a /// BoundNodesTree. class Visitor { public: virtual ~Visitor() {} /// \brief Called multiple times during a single call to VisitMatches(...). /// /// 'BoundNodesView' contains the bound nodes for a single match. virtual void visitMatch(const BoundNodes& BoundNodesView) = 0; }; /// \brief Add a binding from an id to a node. template void setBinding(const std::string &Id, const T *Node) { if (Bindings.empty()) Bindings.push_back(BoundNodesMap()); for (unsigned i = 0, e = Bindings.size(); i != e; ++i) Bindings[i].addNode(Id, Node); } /// \brief Adds a branch in the tree. void addMatch(const BoundNodesTreeBuilder &Bindings); /// \brief Visits all matches that this BoundNodesTree represents. /// /// The ownership of 'ResultVisitor' remains at the caller. void visitMatches(Visitor* ResultVisitor); template bool removeBindings(const ExcludePredicate &Predicate) { Bindings.erase(std::remove_if(Bindings.begin(), Bindings.end(), Predicate), Bindings.end()); return !Bindings.empty(); } /// \brief Imposes an order on BoundNodesTreeBuilders. bool operator<(const BoundNodesTreeBuilder &Other) const { return Bindings < Other.Bindings; } private: SmallVector Bindings; }; class ASTMatchFinder; /// \brief Generic interface for matchers on an AST node of type T. /// /// Implement this if your matcher may need to inspect the children or /// descendants of the node or bind matched nodes to names. If you are /// writing a simple matcher that only inspects properties of the /// current node and doesn't care about its children or descendants, /// implement SingleNodeMatcherInterface instead. template class MatcherInterface : public RefCountedBaseVPTR { public: virtual ~MatcherInterface() {} /// \brief Returns true if 'Node' can be matched. /// /// May bind 'Node' to an ID via 'Builder', or recurse into /// the AST via 'Finder'. virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const = 0; }; /// \brief Interface for matchers that only evaluate properties on a single /// node. template class SingleNodeMatcherInterface : public MatcherInterface { public: /// \brief Returns true if the matcher matches the provided node. /// /// A subclass must implement this instead of Matches(). virtual bool matchesNode(const T &Node) const = 0; private: /// Implements MatcherInterface::Matches. virtual bool matches(const T &Node, ASTMatchFinder * /* Finder */, BoundNodesTreeBuilder * /* Builder */) const { return matchesNode(Node); } }; /// \brief Wrapper of a MatcherInterface *that allows copying. /// /// A Matcher can be used anywhere a Matcher is /// required. This establishes an is-a relationship which is reverse /// to the AST hierarchy. In other words, Matcher is contravariant /// with respect to T. The relationship is built via a type conversion /// operator rather than a type hierarchy to be able to templatize the /// type hierarchy instead of spelling it out. template class Matcher { public: /// \brief Takes ownership of the provided implementation pointer. explicit Matcher(MatcherInterface *Implementation) : Implementation(Implementation) {} /// \brief Implicitly converts \c Other to a Matcher. /// /// Requires \c T to be derived from \c From. template Matcher(const Matcher &Other, typename llvm::enable_if_c< llvm::is_base_of::value && !llvm::is_same::value >::type* = 0) : Implementation(new ImplicitCastMatcher(Other)) {} /// \brief Implicitly converts \c Matcher to \c Matcher. /// /// The resulting matcher is not strict, i.e. ignores qualifiers. template Matcher(const Matcher &Other, typename llvm::enable_if_c< llvm::is_same::value && llvm::is_same::value >::type* = 0) : Implementation(new TypeToQualType(Other)) {} /// \brief Forwards the call to the underlying MatcherInterface pointer. bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { if (Implementation->matches(Node, Finder, Builder)) return true; // Delete all bindings when a matcher does not match. // This prevents unexpected exposure of bound nodes in unmatches // branches of the match tree. *Builder = BoundNodesTreeBuilder(); return false; } /// \brief Returns an ID that uniquely identifies the matcher. uint64_t getID() const { /// FIXME: Document the requirements this imposes on matcher /// implementations (no new() implementation_ during a Matches()). return reinterpret_cast(Implementation.getPtr()); } /// \brief Allows the conversion of a \c Matcher to a \c /// Matcher. /// /// Depending on the constructor argument, the matcher is either strict, i.e. /// does only matches in the absence of qualifiers, or not, i.e. simply /// ignores any qualifiers. template class TypeToQualType : public MatcherInterface { public: TypeToQualType(const Matcher &InnerMatcher) : InnerMatcher(InnerMatcher) {} virtual bool matches(const QualType &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { if (Node.isNull()) return false; return InnerMatcher.matches(*Node, Finder, Builder); } private: const Matcher InnerMatcher; }; private: /// \brief Allows conversion from Matcher to Matcher if T /// is derived from Base. template class ImplicitCastMatcher : public MatcherInterface { public: explicit ImplicitCastMatcher(const Matcher &From) : From(From) {} virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return From.matches(Node, Finder, Builder); } private: const Matcher From; }; IntrusiveRefCntPtr< MatcherInterface > Implementation; }; // class Matcher /// \brief A convenient helper for creating a Matcher without specifying /// the template type argument. template inline Matcher makeMatcher(MatcherInterface *Implementation) { return Matcher(Implementation); } template class BindableMatcher; /// \brief Matcher that works on a \c DynTypedNode. /// /// It is constructed from a \c Matcher object and redirects most calls to /// underlying matcher. /// It checks whether the \c DynTypedNode is convertible into the type of the /// underlying matcher and then do the actual match on the actual node, or /// return false if it is not convertible. class DynTypedMatcher { public: /// \brief Construct from a \c Matcher. Copies the matcher. template inline DynTypedMatcher(const Matcher &M); /// \brief Construct from a bindable \c Matcher. Copies the matcher. /// /// This version enables \c tryBind() on the \c DynTypedMatcher. template inline DynTypedMatcher(const BindableMatcher &M); /// \brief Returns true if the matcher matches the given \c DynNode. bool matches(const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return Storage->matches(DynNode, Finder, Builder); } /// \brief Bind the specified \p ID to the matcher. /// \return A new matcher with the \p ID bound to it if this matcher supports /// binding. Otherwise, returns an empty \c Optional<>. llvm::Optional tryBind(StringRef ID) const { return Storage->tryBind(ID); } /// \brief Returns a unique \p ID for the matcher. uint64_t getID() const { return Storage->getID(); } /// \brief Returns the type this matcher works on. /// /// \c matches() will always return false unless the node passed is of this /// or a derived type. ast_type_traits::ASTNodeKind getSupportedKind() const { return Storage->getSupportedKind(); } /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted /// to a \c Matcher. /// /// This method verifies that the underlying matcher in \c Other can process /// nodes of types T. template bool canConvertTo() const { return getSupportedKind().isBaseOf( ast_type_traits::ASTNodeKind::getFromNodeKind()); } /// \brief Construct a \c Matcher interface around the dynamic matcher. /// /// This method asserts that \c canConvertTo() is \c true. Callers /// should call \c canConvertTo() first to make sure that \c this is /// compatible with T. template Matcher convertTo() const { assert(canConvertTo()); return unconditionalConvertTo(); } /// \brief Same as \c convertTo(), but does not check that the underlying /// matcher can handle a value of T. /// /// If it is not compatible, then this matcher will never match anything. template Matcher unconditionalConvertTo() const { return Matcher(new WrappedMatcher(*this)); } private: class MatcherStorage : public RefCountedBaseVPTR { public: MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID) : SupportedKind(SupportedKind), ID(ID) {} virtual ~MatcherStorage(); virtual bool matches(const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const = 0; virtual llvm::Optional tryBind(StringRef ID) const = 0; ast_type_traits::ASTNodeKind getSupportedKind() const { return SupportedKind; } uint64_t getID() const { return ID; } private: const ast_type_traits::ASTNodeKind SupportedKind; const uint64_t ID; }; /// \brief Typed implementation of \c MatcherStorage. template class TypedMatcherStorage; /// \brief Simple MatcherInterface wrapper around a DynTypedMatcher. template class WrappedMatcher; IntrusiveRefCntPtr Storage; }; template class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage { public: TypedMatcherStorage(const Matcher &Other, bool AllowBind) : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind(), Other.getID()), InnerMatcher(Other), AllowBind(AllowBind) {} bool matches(const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const LLVM_OVERRIDE { if (const T *Node = DynNode.get()) { return InnerMatcher.matches(*Node, Finder, Builder); } return false; } llvm::Optional tryBind(StringRef ID) const LLVM_OVERRIDE { if (!AllowBind) return llvm::Optional(); return DynTypedMatcher(BindableMatcher(InnerMatcher).bind(ID)); } private: const Matcher InnerMatcher; const bool AllowBind; }; template inline DynTypedMatcher::DynTypedMatcher(const Matcher &M) : Storage(new TypedMatcherStorage(M, false)) {} template inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher &M) : Storage(new TypedMatcherStorage(M, true)) {} template class DynTypedMatcher::WrappedMatcher : public MatcherInterface { public: explicit WrappedMatcher(const DynTypedMatcher &Matcher) : Inner(Matcher) {} virtual ~WrappedMatcher() {} bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return Inner.matches(ast_type_traits::DynTypedNode::create(Node), Finder, Builder); } private: const DynTypedMatcher Inner; }; /// \brief Specialization of the conversion functions for QualType. /// /// These specializations provide the Matcher->Matcher /// conversion that the static API does. template <> inline bool DynTypedMatcher::canConvertTo() const { const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind(); return SourceKind.isSame( ast_type_traits::ASTNodeKind::getFromNodeKind()) || SourceKind.isSame( ast_type_traits::ASTNodeKind::getFromNodeKind()); } template <> inline Matcher DynTypedMatcher::convertTo() const { assert(canConvertTo()); const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind(); if (SourceKind.isSame( ast_type_traits::ASTNodeKind::getFromNodeKind())) { // We support implicit conversion from Matcher to Matcher return unconditionalConvertTo(); } return unconditionalConvertTo(); } /// \brief Finds the first node in a range that matches the given matcher. template bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start, IteratorT End, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) { for (IteratorT I = Start; I != End; ++I) { BoundNodesTreeBuilder Result(*Builder); if (Matcher.matches(*I, Finder, &Result)) { *Builder = Result; return true; } } return false; } /// \brief Finds the first node in a pointer range that matches the given /// matcher. template bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, IteratorT End, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) { for (IteratorT I = Start; I != End; ++I) { BoundNodesTreeBuilder Result(*Builder); if (Matcher.matches(**I, Finder, &Result)) { *Builder = Result; return true; } } return false; } /// \brief Metafunction to determine if type T has a member called getDecl. template struct has_getDecl { struct Default { int getDecl; }; struct Derived : T, Default { }; template struct CheckT; // If T::getDecl exists, an ambiguity arises and CheckT will // not be instantiable. This makes f(...) the only available // overload. template static char (&f(CheckT*))[1]; template static char (&f(...))[2]; static bool const value = sizeof(f(0)) == 2; }; /// \brief Matches overloaded operators with a specific name. /// /// The type argument ArgT is not used by this matcher but is used by /// PolymorphicMatcherWithParam1 and should be StringRef. template class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface { TOOLING_COMPILE_ASSERT((llvm::is_same::value || llvm::is_same::value), unsupported_class_for_matcher); TOOLING_COMPILE_ASSERT((llvm::is_same::value), argument_type_must_be_StringRef); public: explicit HasOverloadedOperatorNameMatcher(const StringRef Name) : SingleNodeMatcherInterface(), Name(Name) {} virtual bool matchesNode(const T &Node) const LLVM_OVERRIDE { return matchesSpecialized(Node); } private: /// \brief CXXOperatorCallExpr exist only for calls to overloaded operators /// so this function returns true if the call is to an operator of the given /// name. bool matchesSpecialized(const CXXOperatorCallExpr &Node) const { return getOperatorSpelling(Node.getOperator()) == Name; } /// \brief Returns true only if CXXMethodDecl represents an overloaded /// operator and has the given operator name. bool matchesSpecialized(const CXXMethodDecl &Node) const { return Node.isOverloadedOperator() && getOperatorSpelling(Node.getOverloadedOperator()) == Name; } std::string Name; }; /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but /// not actually used. template class HasDeclarationMatcher : public MatcherInterface { TOOLING_COMPILE_ASSERT((llvm::is_same< DeclMatcherT, Matcher >::value), instantiated_with_wrong_types); public: explicit HasDeclarationMatcher(const Matcher &InnerMatcher) : InnerMatcher(InnerMatcher) {} virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesSpecialized(Node, Finder, Builder); } private: /// \brief If getDecl exists as a member of U, returns whether the inner /// matcher matches Node.getDecl(). template bool matchesSpecialized( const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, typename llvm::enable_if, int>::type = 0) const { return matchesDecl(Node.getDecl(), Finder, Builder); } /// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns /// whether the inner matcher matches on it. bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { /// FIXME: Add other ways to convert... if (Node.isNull()) return false; if (const EnumType *AsEnum = dyn_cast(Node.getTypePtr())) return matchesDecl(AsEnum->getDecl(), Finder, Builder); return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder); } /// \brief Gets the TemplateDecl from a TemplateSpecializationType /// and returns whether the inner matches on it. bool matchesSpecialized(const TemplateSpecializationType &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesDecl(Node.getTemplateName().getAsTemplateDecl(), Finder, Builder); } /// \brief Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesDecl(Node.getCalleeDecl(), Finder, Builder); } /// \brief Extracts the Decl of the constructor call and returns whether the /// inner matcher matches on it. bool matchesSpecialized(const CXXConstructExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesDecl(Node.getConstructor(), Finder, Builder); } /// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns /// whether the inner matcher matches on it. bool matchesSpecialized(const MemberExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesDecl(Node.getMemberDecl(), Finder, Builder); } /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node /// is \c NULL. bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return Node != NULL && InnerMatcher.matches(*Node, Finder, Builder); } const Matcher InnerMatcher; }; /// \brief IsBaseType::value is true if T is a "base" type in the AST /// node class hierarchies. template struct IsBaseType { static const bool value = (llvm::is_same::value || llvm::is_same::value || llvm::is_same::value || llvm::is_same::value || llvm::is_same::value || llvm::is_same::value || llvm::is_same::value || llvm::is_same::value); }; template const bool IsBaseType::value; /// \brief Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. /// /// This provides three entry methods for each base node type in the AST: /// - \c matchesChildOf: /// Matches a matcher on every child node of the given node. Returns true /// if at least one child node could be matched. /// - \c matchesDescendantOf: /// Matches a matcher on all descendant nodes of the given node. Returns true /// if at least one descendant matched. /// - \c matchesAncestorOf: /// Matches a matcher on all ancestors of the given node. Returns true if /// at least one ancestor matched. /// /// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal. /// In the future, we wan to implement this for all nodes for which it makes /// sense. In the case of matchesAncestorOf, we'll want to implement it for /// all nodes, as all nodes have ancestors. class ASTMatchFinder { public: /// \brief Defines how we descend a level in the AST when we pass /// through expressions. enum TraversalKind { /// Will traverse any child nodes. TK_AsIs, /// Will not traverse implicit casts and parentheses. TK_IgnoreImplicitCastsAndParentheses }; /// \brief Defines how bindings are processed on recursive matches. enum BindKind { /// Stop at the first match and only bind the first match. BK_First, /// Create results for all combinations of bindings that match. BK_All }; /// \brief Defines which ancestors are considered for a match. enum AncestorMatchMode { /// All ancestors. AMM_All, /// Direct parent only. AMM_ParentOnly }; virtual ~ASTMatchFinder() {} /// \brief Returns true if the given class is directly or indirectly derived /// from a base type matching \c base. /// /// A class is considered to be also derived from itself. virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration, const Matcher &Base, BoundNodesTreeBuilder *Builder) = 0; template bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, TraversalKind Traverse, BindKind Bind) { TOOLING_COMPILE_ASSERT( (llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value), unsupported_type_for_recursive_matching); return matchesChildOf(ast_type_traits::DynTypedNode::create(Node), Matcher, Builder, Traverse, Bind); } template bool matchesDescendantOf(const T &Node, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) { TOOLING_COMPILE_ASSERT( (llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value || llvm::is_base_of::value), unsupported_type_for_recursive_matching); return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node), Matcher, Builder, Bind); } // FIXME: Implement support for BindKind. template bool matchesAncestorOf(const T &Node, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) { TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || llvm::is_base_of::value), only_Decl_or_Stmt_allowed_for_recursive_matching); return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node), Matcher, Builder, MatchMode); } virtual ASTContext &getASTContext() const = 0; protected: virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, TraversalKind Traverse, BindKind Bind) = 0; virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) = 0; virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) = 0; }; /// \brief A type-list implementation. /// /// A list is declared as a tree of type list nodes, where the leafs are the /// types. /// However, it is used as a "linked list" of types, by using the ::head and /// ::tail typedefs. /// Each node supports up to 4 children (instead of just 2) to reduce the /// nesting required by large lists. template struct TypeList { /// \brief Implementation detail. Combined with the specializations below, /// this typedef allows for flattening of nested structures. typedef TypeList self; /// \brief The first type on the list. typedef T1 head; /// \brief A sub list with the tail. ie everything but the head. /// /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the /// end of the list. typedef typename TypeList::self tail; }; /// \brief Template specialization to allow nested lists. /// /// First element is a typelist. Pop its first element. template struct TypeList, T2, T3, T4> : public TypeList::self, typename TypeList::self> {}; /// \brief Template specialization to allow nested lists. /// /// First element is an empty typelist. Skip it. template struct TypeList, T2, T3, T4> : public TypeList { }; /// \brief The empty type list. typedef TypeList<> EmptyTypeList; /// \brief Helper meta-function to determine if some type \c T is present or /// a parent type in the list. template struct TypeListContainsSuperOf { static const bool value = llvm::is_base_of::value || TypeListContainsSuperOf::value; }; template struct TypeListContainsSuperOf { static const bool value = false; }; /// \brief A "type list" that contains all types. /// /// Useful for matchers like \c anything and \c unless. typedef TypeList< TypeList, TypeList > AllNodeBaseTypes; /// \brief Helper meta-function to extract the argument out of a function of /// type void(Arg). /// /// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details. template struct ExtractFunctionArgMeta; template struct ExtractFunctionArgMeta { typedef T type; }; /// \brief Default type lists for ArgumentAdaptingMatcher matchers. typedef AllNodeBaseTypes AdaptativeDefaultFromTypes; typedef TypeList, TypeList > AdaptativeDefaultToTypes; /// \brief All types that are supported by HasDeclarationMatcher above. typedef TypeList, TypeList, TypeList, TypeList > HasDeclarationSupportedTypes; /// \brief Converts a \c Matcher to a matcher of desired type \c To by /// "adapting" a \c To into a \c T. /// /// The \c ArgumentAdapterT argument specifies how the adaptation is done. /// /// For example: /// \c ArgumentAdaptingMatcher(InnerMatcher); /// Given that \c InnerMatcher is of type \c Matcher, this returns a matcher /// that is convertible into any matcher of type \c To by constructing /// \c HasMatcher(InnerMatcher). /// /// If a matcher does not need knowledge about the inner type, prefer to use /// PolymorphicMatcherWithParam1. template