From a78d0d6203a990b88c9c3e4c4f2a277001e8bd46 Mon Sep 17 00:00:00 2001 From: Manuel Klimek Date: Wed, 5 Sep 2012 12:12:07 +0000 Subject: [PATCH] Introduces DynTypedMatcher as a new concept that replaces the UntypedBaseMatcher and TypedMatcher. Due to DynTypedNode the basic dynamically typed matcher interface can now be simplified. Also switches the traversal interfaces to use DynTypedNode; this is in preperation for the hasAncestor implementation, and also allows us to need fewer changes when we want to add new nodes to traverse, thus making the code a little more decoupled. Main design concerns: I went back towards the original design of getNodeAs to return a pointer, and switched DynTypedNode::get to always return a pointer (in case of value types like QualType the pointer points into the storage of DynTypedNode, thus allowing us to treat all the nodes the same from the point of view of a user of the DynTypedNodes. Adding the QualType implementation for DynTypedNode was needed for the recursive traversal interface changes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163212 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/ASTMatchers/ASTMatchFinder.h | 9 +- include/clang/ASTMatchers/ASTMatchers.h | 7 +- .../clang/ASTMatchers/ASTMatchersInternal.h | 149 ++++++++---------- include/clang/ASTMatchers/ASTTypeTraits.h | 112 +++++++++---- lib/ASTMatchers/ASTMatchFinder.cpp | 132 ++++++++-------- unittests/ASTMatchers/ASTMatchersTest.cpp | 3 +- 6 files changed, 223 insertions(+), 189 deletions(-) diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index dd237eece3..0fcc5dda1c 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -125,11 +125,10 @@ public: void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); private: - /// \brief The MatchCallback*'s will be called every time the - /// UntypedBaseMatcher matches on the AST. - std::vector< std::pair< - const internal::UntypedBaseMatcher*, - MatchCallback*> > Triggers; + /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called + /// when it matches. + std::vector > + MatcherCallbackPairs; /// \brief Called when parsing is done. ParsingDoneTestCallback *ParsingDone; diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 7cc829a9c5..54a0e02e13 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -65,10 +65,11 @@ namespace ast_matchers { class BoundNodes { public: /// \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 { + const T *getNodeAs(StringRef ID) const { return MyBoundNodes.getNodeAs(ID); } @@ -76,11 +77,11 @@ public: /// @{ template const T *getDeclAs(StringRef ID) const { - return getNodeAs(ID); + return getNodeAs(ID); } template const T *getStmtAs(StringRef ID) const { - return getNodeAs(ID); + return getNodeAs(ID); } /// @} diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 7f585ef3e7..36831e6f11 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -68,7 +68,7 @@ public: /// 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); + NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node); } void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) { NodeMap[ID] = Node; @@ -79,7 +79,7 @@ public: /// 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 { + const T *getNodeAs(StringRef ID) const { IDToNodeMap::const_iterator It = NodeMap.find(ID); if (It == NodeMap.end()) { return NULL; @@ -205,7 +205,8 @@ public: BoundNodesTreeBuilder *Builder) const = 0; }; -/// \brief Interface for matchers that only evaluate properties on a single node. +/// \brief Interface for matchers that only evaluate properties on a single +/// node. template class SingleNodeMatcherInterface : public MatcherInterface { public: @@ -223,6 +224,24 @@ private: } }; +/// \brief Base class for all matchers that works on a \c DynTypedNode. +/// +/// Matcher implementations will check whether the \c DynTypedNode is +/// convertible into the respecitve types and then do the actual match +/// on the actual node, or return false if it is not convertible. +class DynTypedMatcher { +public: + virtual ~DynTypedMatcher() {} + + /// \brief Returns true if the matcher matches the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; + + /// \brief Returns a unique ID for the matcher. + virtual uint64_t getID() const = 0; +}; + /// \brief Wrapper of a MatcherInterface *that allows copying. /// /// A Matcher can be used anywhere a Matcher is @@ -232,7 +251,7 @@ private: /// operator rather than a type hierarchy to be able to templatize the /// type hierarchy instead of spelling it out. template -class Matcher { +class Matcher : public DynTypedMatcher { public: /// \brief Takes ownership of the provided implementation pointer. explicit Matcher(MatcherInterface *Implementation) @@ -260,6 +279,15 @@ public: return reinterpret_cast(Implementation.getPtr()); } + /// \brief Returns whether the matcher matches on the given \c DynNode. + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const T *Node = DynNode.get(); + if (!Node) return false; + return matches(*Node, Finder, Builder); + } + private: /// \brief Allows conversion from Matcher to Matcher if Derived /// is derived from T. @@ -344,7 +372,8 @@ private: }; /// \brief IsBaseType::value is true if T is a "base" type in the AST -/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType). +/// node class hierarchies (i.e. if T is Decl, Stmt, QualType, or +/// CXXCtorInitializer). template struct IsBaseType { static const bool value = @@ -356,65 +385,6 @@ struct IsBaseType { template const bool IsBaseType::value; -/// \brief Interface that can match any AST base node type and contains default -/// implementations returning false. -class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR { -public: - virtual ~UntypedBaseMatcher() {} - - virtual bool matches(const Decl &DeclNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const QualType &TypeNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const Stmt &StmtNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - virtual bool matches(const CXXCtorInitializer &CtorInitNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return false; - } - - /// \brief Returns a unique ID for the matcher. - virtual uint64_t getID() const = 0; -}; - -/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method for -/// node type T. T must be an AST base type. -template -class TypedBaseMatcher : public UntypedBaseMatcher { - TOOLING_COMPILE_ASSERT(IsBaseType::value, - typed_base_matcher_can_only_be_used_with_base_type); -public: - explicit TypedBaseMatcher(const Matcher &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - using UntypedBaseMatcher::matches; - /// \brief Implements UntypedBaseMatcher::Matches. - /// - /// Since T is guaranteed to be a "base" AST node type, this method is - /// guaranteed to override one of the matches() methods from - /// UntypedBaseMatcher. - virtual bool matches(const T &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - return InnerMatcher.matches(Node, Finder, Builder); - } - - /// \brief Implements UntypedBaseMatcher::getID. - virtual uint64_t getID() const { - return InnerMatcher.getID(); - } - -private: - Matcher InnerMatcher; -}; - /// \brief Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. /// @@ -454,24 +424,41 @@ public: 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), + only_Decl_or_Stmt_allowed_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), + only_Decl_or_Stmt_allowed_for_recursive_matching); + return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node), + Matcher, Builder, Bind); + } + +protected: // FIXME: Implement for other base nodes. - virtual bool matchesChildOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - TraversalKind Traverse, - BindKind Bind) = 0; - virtual bool matchesChildOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, TraversalKind Traverse, BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - BindKind Bind) = 0; - virtual bool matchesDescendantOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) = 0; }; @@ -671,7 +658,7 @@ public: } private: - const TypedBaseMatcher ChildMatcher; + const Matcher ChildMatcher; }; /// \brief Matches nodes of type T that have child nodes of type ChildT for @@ -697,7 +684,7 @@ class ForEachMatcher : public MatcherInterface { } private: - const TypedBaseMatcher ChildMatcher; + const Matcher ChildMatcher; }; /// \brief Matches nodes of type T if the given Matcher does not match. @@ -811,7 +798,7 @@ public: } private: - const TypedBaseMatcher DescendantMatcher; + const Matcher DescendantMatcher; }; /// \brief Matches nodes of type T that have at least one descendant node of @@ -837,7 +824,7 @@ class ForEachDescendantMatcher : public MatcherInterface { } private: - const TypedBaseMatcher DescendantMatcher; + const Matcher DescendantMatcher; }; /// \brief Matches on nodes that have a getValue() method if getValue() equals diff --git a/include/clang/ASTMatchers/ASTTypeTraits.h b/include/clang/ASTMatchers/ASTTypeTraits.h index e90446f534..db11ce8e58 100644 --- a/include/clang/ASTMatchers/ASTTypeTraits.h +++ b/include/clang/ASTMatchers/ASTTypeTraits.h @@ -17,24 +17,28 @@ #include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" +#include "llvm/Support/AlignOf.h" namespace clang { namespace ast_type_traits { /// \brief A dynamically typed AST node container. /// -/// Stores an AST node in a type safe way. +/// Stores an AST node in a type safe way. This allows writing code that +/// works with different kinds of AST nodes, despite the fact that they don't +/// have a common base class. +/// /// Use \c create(Node) to create a \c DynTypedNode from an AST node, /// and \c get() to retrieve the node as type T if the types match. +/// +/// See \c NodeTypeTag for which node base types are currently supported; +/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of +/// the supported base types. class DynTypedNode { public: - /// \brief Creates a NULL-node, which is needed to be able to use - /// \c DynTypedNodes in STL data structures. - DynTypedNode() : Tag(), Node(NULL) {} - /// \brief Creates a \c DynTypedNode from \c Node. template - static DynTypedNode create(T Node) { + static DynTypedNode create(const T &Node) { return BaseConverter::create(Node); } @@ -42,12 +46,26 @@ public: /// /// Returns NULL if the stored node does not have a type that is /// convertible to \c T. + /// + /// For types that have identity via their pointer in the AST + /// (like \c Stmt and \c Decl) the returned pointer points to the + /// referenced AST node. + /// For other types (like \c QualType) the value is stored directly + /// in the \c DynTypedNode, and the returned pointer points at + /// the storage inside DynTypedNode. For those nodes, do not + /// use the pointer outside the scope of the DynTypedNode. template - T get() const { - return llvm::dyn_cast::type>( - BaseConverter::get(Tag, Node)); + const T *get() const { + return BaseConverter::get(Tag, Storage.buffer); } + /// \brief Returns a pointer that identifies the stored AST node. + /// + /// Note that this is not supported by all AST nodes. For AST nodes + /// that don't have a pointer-defined identity inside the AST, this + /// method returns NULL. + const void *getMemoizationData() const; + private: /// \brief Takes care of converting from and to \c T. template struct BaseConverter; @@ -55,42 +73,74 @@ private: /// \brief Supported base node types. enum NodeTypeTag { NT_Decl, - NT_Stmt + NT_Stmt, + NT_QualType } Tag; /// \brief Stores the data of the node. - // FIXME: We really want to store a union, as we want to support - // storing TypeLoc nodes by-value. - // FIXME: Add QualType storage: we'll want to use QualType::getAsOpaquePtr() - // and getFromOpaquePtr(...) to convert to and from void*, but return the - // QualType objects by value. - void *Node; - - DynTypedNode(NodeTypeTag Tag, const void *Node) - : Tag(Tag), Node(const_cast(Node)) {} + /// + /// Note that we can store \c Decls and \c Stmts by pointer as they are + /// guaranteed to be unique pointers pointing to dedicated storage in the + /// AST. \c QualTypes on the other hand do not have storage or unique + /// pointers and thus need to be stored by value. + llvm::AlignedCharArrayUnion Storage; }; template struct DynTypedNode::BaseConverter::type > >::type > { - static Decl *get(NodeTypeTag Tag, void *Node) { - if (Tag == NT_Decl) return static_cast(Node); + typename llvm::enable_if >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Decl) + return dyn_cast(*reinterpret_cast(Storage)); return NULL; } - static DynTypedNode create(const Decl *Node) { - return DynTypedNode(NT_Decl, Node); + static DynTypedNode create(const Decl &Node) { + DynTypedNode Result; + Result.Tag = NT_Decl; + new (Result.Storage.buffer) const Decl*(&Node); + return Result; } }; template struct DynTypedNode::BaseConverter::type > >::type > { - static Stmt *get(NodeTypeTag Tag, void *Node) { - if (Tag == NT_Stmt) return static_cast(Node); + typename llvm::enable_if >::type> { + static const T *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_Stmt) + return dyn_cast(*reinterpret_cast(Storage)); return NULL; } - static DynTypedNode create(const Stmt *Node) { - return DynTypedNode(NT_Stmt, Node); + static DynTypedNode create(const Stmt &Node) { + DynTypedNode Result; + Result.Tag = NT_Stmt; + new (Result.Storage.buffer) const Stmt*(&Node); + return Result; } }; +template<> struct DynTypedNode::BaseConverter { + static const QualType *get(NodeTypeTag Tag, const char Storage[]) { + if (Tag == NT_QualType) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const QualType &Node) { + DynTypedNode Result; + Result.Tag = NT_QualType; + new (Result.Storage.buffer) QualType(Node); + return Result; + } +}; +// The only operation we allow on unsupported types is \c get. +// This allows to conveniently use \c DynTypedNode when having an arbitrary +// AST node that is not supported, but prevents misuse - a user cannot create +// a DynTypedNode from arbitrary types. +template struct DynTypedNode::BaseConverter { + static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; } +}; + +inline const void *DynTypedNode::getMemoizationData() const { + switch (Tag) { + case NT_Decl: return BaseConverter::get(Tag, Storage.buffer); + case NT_Stmt: return BaseConverter::get(Tag, Storage.buffer); + default: return NULL; + }; +} } // end namespace ast_type_traits } // end namespace clang diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index 085049debd..8f28c385b9 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -27,10 +27,19 @@ namespace ast_matchers { namespace internal { namespace { +typedef MatchFinder::MatchCallback MatchCallback; + // We use memoization to avoid running the same matcher on the same // AST node twice. This pair is the key for looking up match // result. It consists of an ID of the MatcherInterface (for // identifying the matcher) and a pointer to the AST node. +// +// We currently only memoize on nodes whose pointers identify the +// nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc). +// For \c QualType and \c TypeLoc it is possible to implement +// generation of keys for each type. +// FIXME: Benchmark whether memoization of non-pointer typed nodes +// provides enough benefit for the additional amount of code. typedef std::pair UntypedMatchInput; // Used to store the result of a match and possibly bound nodes. @@ -50,13 +59,13 @@ public: // descendants of a traversed node. max_depth is the maximum depth // to traverse: use 1 for matching the children and INT_MAX for // matching the descendants. - MatchChildASTVisitor(const UntypedBaseMatcher *BaseMatcher, + MatchChildASTVisitor(const DynTypedMatcher *Matcher, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, int MaxDepth, ASTMatchFinder::TraversalKind Traversal, ASTMatchFinder::BindKind Bind) - : BaseMatcher(BaseMatcher), + : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(-1), @@ -76,10 +85,13 @@ public: // Traverse*(c) for each child c of 'node'. // - Traverse*(c) in turn calls Traverse(c), completing the // recursion. - template - bool findMatch(const T &Node) { + bool findMatch(const ast_type_traits::DynTypedNode &DynNode) { reset(); - traverse(Node); + if (const Decl *D = DynNode.get()) + traverse(*D); + else if (const Stmt *S = DynNode.get()) + traverse(*S); + // FIXME: Add other base types after adding tests. return Matches; } @@ -148,7 +160,8 @@ private: return baseTraverse(Node); } if (Bind != ASTMatchFinder::BK_All) { - if (BaseMatcher->matches(Node, Finder, Builder)) { + if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), + Finder, Builder)) { Matches = true; return false; // Abort as soon as a match is found. } @@ -163,7 +176,8 @@ private: return true; } else { BoundNodesTreeBuilder RecursiveBuilder; - if (BaseMatcher->matches(Node, Finder, &RecursiveBuilder)) { + if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), + Finder, &RecursiveBuilder)) { // After the first match the matcher succeeds. Matches = true; Builder->addMatch(RecursiveBuilder.build()); @@ -176,7 +190,7 @@ private: } } - const UntypedBaseMatcher *const BaseMatcher; + const DynTypedMatcher *const Matcher; ASTMatchFinder *const Finder; BoundNodesTreeBuilder *const Builder; int CurrentDepth; @@ -191,9 +205,9 @@ private: class MatchASTVisitor : public RecursiveASTVisitor, public ASTMatchFinder { public: - MatchASTVisitor(std::vector< std::pair > *Triggers) - : Triggers(Triggers), + MatchASTVisitor(std::vector > *MatcherCallbackPairs) + : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(NULL) { } @@ -245,21 +259,19 @@ public: bool TraverseTypeLoc(TypeLoc TypeNode); // Matches children or descendants of 'Node' with 'BaseMatcher'. - template - bool memoizedMatchesRecursively(const T &Node, - const UntypedBaseMatcher &BaseMatcher, + bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, int MaxDepth, TraversalKind Traversal, BindKind Bind) { - TOOLING_COMPILE_ASSERT((llvm::is_same::value) || - (llvm::is_same::value), - type_does_not_support_memoization); - const UntypedMatchInput input(BaseMatcher.getID(), &Node); + const UntypedMatchInput input(Matcher.getID(), Node.getMemoizationData()); + assert(input.second && + "Fix getMemoizationData once more types allow recursive matching."); std::pair InsertResult = ResultCache.insert(std::make_pair(input, MemoizedMatchResult())); if (InsertResult.second) { BoundNodesTreeBuilder DescendantBoundNodesBuilder; InsertResult.first->second.ResultOfMatch = - matchesRecursively(Node, BaseMatcher, &DescendantBoundNodesBuilder, + matchesRecursively(Node, Matcher, &DescendantBoundNodesBuilder, MaxDepth, Traversal, Bind); InsertResult.first->second.Nodes = DescendantBoundNodesBuilder.build(); @@ -269,12 +281,12 @@ public: } // Matches children or descendants of 'Node' with 'BaseMatcher'. - template - bool matchesRecursively(const T &Node, const UntypedBaseMatcher &BaseMatcher, + bool matchesRecursively(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, int MaxDepth, TraversalKind Traversal, BindKind Bind) { MatchChildASTVisitor Visitor( - &BaseMatcher, this, Builder, MaxDepth, Traversal, Bind); + &Matcher, this, Builder, MaxDepth, Traversal, Bind); return Visitor.findMatch(Node); } @@ -283,36 +295,20 @@ public: BoundNodesTreeBuilder *Builder); // Implements ASTMatchFinder::MatchesChildOf. - virtual bool matchesChildOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - TraversalKind Traversal, - BindKind Bind) { - return matchesRecursively(DeclNode, BaseMatcher, Builder, 1, Traversal, - Bind); - } - virtual bool matchesChildOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, TraversalKind Traversal, BindKind Bind) { - return matchesRecursively(StmtNode, BaseMatcher, Builder, 1, Traversal, + return matchesRecursively(Node, Matcher, Builder, 1, Traversal, Bind); } - // Implements ASTMatchFinder::MatchesDescendantOf. - virtual bool matchesDescendantOf(const Decl &DeclNode, - const UntypedBaseMatcher &BaseMatcher, - BoundNodesTreeBuilder *Builder, - BindKind Bind) { - return memoizedMatchesRecursively(DeclNode, BaseMatcher, Builder, INT_MAX, - TK_AsIs, Bind); - } - virtual bool matchesDescendantOf(const Stmt &StmtNode, - const UntypedBaseMatcher &BaseMatcher, + virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) { - return memoizedMatchesRecursively(StmtNode, BaseMatcher, Builder, INT_MAX, + return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX, TK_AsIs, Bind); } @@ -358,21 +354,22 @@ private: // result callback for every node that matches. template void match(const T &node) { - for (std::vector< std::pair >::const_iterator - It = Triggers->begin(), End = Triggers->end(); - It != End; ++It) { + for (std::vector >::const_iterator + I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end(); + I != E; ++I) { BoundNodesTreeBuilder Builder; - if (It->first->matches(node, this, &Builder)) { + if (I->first->matches(ast_type_traits::DynTypedNode::create(node), + this, &Builder)) { BoundNodesTree BoundNodes = Builder.build(); - MatchVisitor Visitor(ActiveASTContext, It->second); + MatchVisitor Visitor(ActiveASTContext, I->second); BoundNodes.visitMatches(&Visitor); } } } - std::vector< std::pair > *const Triggers; + std::vector > *const MatcherCallbackPairs; ASTContext *ActiveASTContext; // Maps a canonical type to its TypedefDecls. @@ -474,11 +471,12 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLoc) { class MatchASTConsumer : public ASTConsumer { public: - MatchASTConsumer(std::vector< std::pair > *Triggers, - MatchFinder::ParsingDoneTestCallback *ParsingDone) - : Visitor(Triggers), - ParsingDone(ParsingDone) {} + MatchASTConsumer( + std::vector > *MatcherCallbackPairs, + MatchFinder::ParsingDoneTestCallback *ParsingDone) + : Visitor(MatcherCallbackPairs), + ParsingDone(ParsingDone) {} private: virtual void HandleTranslationUnit(ASTContext &Context) { @@ -508,9 +506,9 @@ MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {} MatchFinder::MatchFinder() : ParsingDone(NULL) {} MatchFinder::~MatchFinder() { - for (std::vector< std::pair >::const_iterator - It = Triggers.begin(), End = Triggers.end(); + for (std::vector >::const_iterator + It = MatcherCallbackPairs.begin(), End = MatcherCallbackPairs.end(); It != End; ++It) { delete It->first; } @@ -518,24 +516,24 @@ MatchFinder::~MatchFinder() { void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action) { - Triggers.push_back(std::make_pair( - new internal::TypedBaseMatcher(NodeMatch), Action)); + MatcherCallbackPairs.push_back(std::make_pair( + new internal::Matcher(NodeMatch), Action)); } void MatchFinder::addMatcher(const TypeMatcher &NodeMatch, MatchCallback *Action) { - Triggers.push_back(std::make_pair( - new internal::TypedBaseMatcher(NodeMatch), Action)); + MatcherCallbackPairs.push_back(std::make_pair( + new internal::Matcher(NodeMatch), Action)); } void MatchFinder::addMatcher(const StatementMatcher &NodeMatch, MatchCallback *Action) { - Triggers.push_back(std::make_pair( - new internal::TypedBaseMatcher(NodeMatch), Action)); + MatcherCallbackPairs.push_back(std::make_pair( + new internal::Matcher(NodeMatch), Action)); } ASTConsumer *MatchFinder::newASTConsumer() { - return new internal::MatchASTConsumer(&Triggers, ParsingDone); + return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone); } void MatchFinder::registerTestCallbackAfterParsing( diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 595f79cb61..86e949fef4 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1914,9 +1914,8 @@ AST_POLYMORPHIC_MATCHER_P( TOOLING_COMPILE_ASSERT((llvm::is_same::value) || (llvm::is_same::value), assert_node_type_is_accessible); - internal::TypedBaseMatcher ChildMatcher(AMatcher); return Finder->matchesChildOf( - Node, ChildMatcher, Builder, + Node, AMatcher, Builder, ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, ASTMatchFinder::BK_First); } -- 2.40.0