Hi djasper, mdiamond, silvas,
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.
http://llvm-reviews.chandlerc.com/D33
Files:
include/clang/ASTMatchers/ASTMatchFinder.h
include/clang/ASTMatchers/ASTMatchers.h
include/clang/ASTMatchers/ASTMatchersInternal.h
include/clang/ASTMatchers/ASTTypeTraits.h
lib/ASTMatchers/ASTMatchFinder.cpp
unittests/ASTMatchers/ASTMatchersTest.cpp
Index: include/clang/ASTMatchers/ASTMatchFinder.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchFinder.h
+++ include/clang/ASTMatchers/ASTMatchFinder.h
@@ -95,6 +95,10 @@
virtual void run() = 0;
};
+ /// \brief The \c MatchCallback*'s will be called every time the
+ /// \c DynTypedMatcher matches on the AST.
+ typedef std::pair<const internal::DynTypedMatcher*, MatchCallback*> Trigger;
+
MatchFinder();
~MatchFinder();
@@ -125,11 +129,8 @@
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 The triggers executed against the AST.
+ std::vector<Trigger> Triggers;
/// \brief Called when parsing is done.
ParsingDoneTestCallback *ParsingDone;
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -68,19 +68,19 @@
/// 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 <typename T>
- const T getNodeAs(StringRef ID) const {
+ const T *getNodeAs(StringRef ID) const {
return MyBoundNodes.getNodeAs<T>(ID);
}
/// \brief Deprecated. Please use \c getNodeAs instead.
/// @{
template <typename T>
const T *getDeclAs(StringRef ID) const {
- return getNodeAs<T*>(ID);
+ return getNodeAs<T>(ID);
}
template <typename T>
const T *getStmtAs(StringRef ID) const {
- return getNodeAs<T*>(ID);
+ return getNodeAs<T>(ID);
}
/// @}
Index: include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchersInternal.h
+++ include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -68,7 +68,7 @@
/// The node's base type should be in NodeBaseType or it will be unaccessible.
template <typename T>
void addNode(StringRef ID, const T* Node) {
- NodeMap[ID] = ast_type_traits::DynTypedNode::create<const T*>(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 @@
/// 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 <typename T>
- 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 @@
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 <typename T>
class SingleNodeMatcherInterface : public MatcherInterface<T> {
public:
@@ -223,6 +224,24 @@
}
};
+/// \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<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@@ -232,7 +251,7 @@
/// operator rather than a type hierarchy to be able to templatize the
/// type hierarchy instead of spelling it out.
template <typename T>
-class Matcher {
+class Matcher : public DynTypedMatcher {
public:
/// \brief Takes ownership of the provided implementation pointer.
explicit Matcher(MatcherInterface<T> *Implementation)
@@ -260,6 +279,15 @@
return reinterpret_cast<uint64_t>(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<T>();
+ if (!Node) return false;
+ return matches(*Node, Finder, Builder);
+ }
+
private:
/// \brief Allows conversion from Matcher<T> to Matcher<Derived> if Derived
/// is derived from T.
@@ -356,65 +384,6 @@
template <typename T>
const bool IsBaseType<T>::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 <typename T>
-class TypedBaseMatcher : public UntypedBaseMatcher {
- TOOLING_COMPILE_ASSERT(IsBaseType<T>::value,
- typed_base_matcher_can_only_be_used_with_base_type);
-public:
- explicit TypedBaseMatcher(const Matcher<T> &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<T> InnerMatcher;
-};
-
/// \brief Interface that allows matchers to traverse the AST.
/// FIXME: Find a better name.
///
@@ -454,24 +423,41 @@
const Matcher<NamedDecl> &Base,
BoundNodesTreeBuilder *Builder) = 0;
+ template <typename T>
+ bool matchesChildOf(const T &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ TraversalKind Traverse,
+ BindKind Bind) {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<Decl, T>::value ||
+ llvm::is_base_of<Stmt, T>::value),
+ only_Decl_or_Stmt_allowed_for_recursive_matching);
+ return matchesChildOf(ast_type_traits::DynTypedNode::create(Node),
+ Matcher, Builder, Traverse, Bind);
+ }
+
+ template <typename T>
+ bool matchesDescendantOf(const T &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ BindKind Bind) {
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<Decl, T>::value ||
+ llvm::is_base_of<Stmt, T>::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 +657,7 @@
}
private:
- const TypedBaseMatcher<ChildT> ChildMatcher;
+ const Matcher<ChildT> ChildMatcher;
};
/// \brief Matches nodes of type T that have child nodes of type ChildT for
@@ -697,7 +683,7 @@
}
private:
- const TypedBaseMatcher<ChildT> ChildMatcher;
+ const Matcher<ChildT> ChildMatcher;
};
/// \brief Matches nodes of type T if the given Matcher<T> does not match.
@@ -811,7 +797,7 @@
}
private:
- const TypedBaseMatcher<DescendantT> DescendantMatcher;
+ const Matcher<DescendantT> DescendantMatcher;
};
/// \brief Matches nodes of type T that have at least one descendant node of
@@ -837,7 +823,7 @@
}
private:
- const TypedBaseMatcher<DescendantT> DescendantMatcher;
+ const Matcher<DescendantT> DescendantMatcher;
};
/// \brief Matches on nodes that have a getValue() method if getValue() equals
Index: include/clang/ASTMatchers/ASTTypeTraits.h
===================================================================
--- include/clang/ASTMatchers/ASTTypeTraits.h
+++ include/clang/ASTMatchers/ASTTypeTraits.h
@@ -17,35 +17,59 @@
#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 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<T>() 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 <typename T>
- static DynTypedNode create(T Node) {
+ static DynTypedNode create(const T &Node) {
return BaseConverter<T>::create(Node);
}
/// \brief Retrieve the stored node as type \c T.
///
/// 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 Stmt and Decl) the returned pointer points to the
+ /// referenced AST node.
+ /// For other types (like QualType) the value is stored directly
+ /// in the 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 <typename T>
- T get() const {
- return llvm::dyn_cast<typename llvm::remove_pointer<T>::type>(
- BaseConverter<T>::get(Tag, Node));
+ const T *get() const {
+ return BaseConverter<T>::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.
+ void *getMemoizationData() const {
+ switch (Tag) {
+ case NT_Decl: return *reinterpret_cast<Decl* const *>(Storage.buffer);
+ case NT_Stmt: return *reinterpret_cast<Stmt* const *>(Storage.buffer);
+ default: return NULL;
+ };
}
private:
@@ -55,42 +79,65 @@
/// \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<void*>(Node)) {}
+ ///
+ /// Note that we store the QualType by value as we only get
+ /// it by-value from the AST.
+ llvm::AlignedCharArrayUnion<Decl*, Stmt*, QualType> Storage;
};
template<typename T> struct DynTypedNode::BaseConverter<T,
- typename llvm::enable_if<llvm::is_base_of<
- Decl, typename llvm::remove_pointer<T>::type > >::type > {
- static Decl *get(NodeTypeTag Tag, void *Node) {
- if (Tag == NT_Decl) return static_cast<Decl*>(Node);
+ typename llvm::enable_if<llvm::is_base_of<Decl, T> >::type> {
+ static const T *get(NodeTypeTag Tag, const char Storage[]) {
+ if (Tag == NT_Decl)
+ return dyn_cast<T>(*reinterpret_cast<Decl*const*>(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<typename T> struct DynTypedNode::BaseConverter<T,
- typename llvm::enable_if<llvm::is_base_of<
- Stmt, typename llvm::remove_pointer<T>::type > >::type > {
- static Stmt *get(NodeTypeTag Tag, void *Node) {
- if (Tag == NT_Stmt) return static_cast<Stmt*>(Node);
+ typename llvm::enable_if<llvm::is_base_of<Stmt, T> >::type> {
+ static const T *get(NodeTypeTag Tag, const char Storage[]) {
+ if (Tag == NT_Stmt)
+ return dyn_cast<T>(*reinterpret_cast<Stmt*const*>(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<QualType, void> {
+ static const QualType *get(NodeTypeTag Tag, const char Storage[]) {
+ if (Tag == NT_QualType)
+ return reinterpret_cast<const QualType*>(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 <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
+ static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; }
+};
+
} // end namespace ast_type_traits
} // end namespace clang
Index: lib/ASTMatchers/ASTMatchFinder.cpp
===================================================================
--- lib/ASTMatchers/ASTMatchFinder.cpp
+++ lib/ASTMatchers/ASTMatchFinder.cpp
@@ -50,13 +50,13 @@
// 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 +76,13 @@
// Traverse*(c) for each child c of 'node'.
// - Traverse*(c) in turn calls Traverse(c), completing the
// recursion.
- template <typename T>
- bool findMatch(const T &Node) {
+ bool findMatch(const ast_type_traits::DynTypedNode &DynNode) {
reset();
- traverse(Node);
+ if (const Decl *D = DynNode.get<Decl>())
+ traverse(*D);
+ else if (const Stmt *S = DynNode.get<Stmt>())
+ traverse(*S);
+ // FIXME: Add other base types after adding tests.
return Matches;
}
@@ -148,7 +151,8 @@
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 +167,8 @@
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 +181,7 @@
}
}
- const UntypedBaseMatcher *const BaseMatcher;
+ const DynTypedMatcher *const Matcher;
ASTMatchFinder *const Finder;
BoundNodesTreeBuilder *const Builder;
int CurrentDepth;
@@ -191,8 +196,7 @@
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
public ASTMatchFinder {
public:
- MatchASTVisitor(std::vector< std::pair<const UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> > *Triggers)
+ MatchASTVisitor(std::vector<MatchFinder::Trigger> *Triggers)
: Triggers(Triggers),
ActiveASTContext(NULL) {
}
@@ -245,21 +249,19 @@
bool TraverseTypeLoc(TypeLoc TypeNode);
// Matches children or descendants of 'Node' with 'BaseMatcher'.
- template <typename T>
- 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<T, Decl>::value) ||
- (llvm::is_same<T, Stmt>::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<MemoizationMap::iterator, bool> 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,50 +271,34 @@
}
// Matches children or descendants of 'Node' with 'BaseMatcher'.
- template <typename T>
- 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);
}
virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
const Matcher<NamedDecl> &Base,
BoundNodesTreeBuilder *Builder);
// Implements ASTMatchFinder::MatchesChildOf.
- virtual bool matchesChildOf(const Decl &DeclNode,
- const UntypedBaseMatcher &BaseMatcher,
+ virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
+ const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
TraversalKind Traversal,
BindKind Bind) {
- return matchesRecursively(DeclNode, BaseMatcher, Builder, 1, Traversal,
+ return matchesRecursively(Node, Matcher, Builder, 1, Traversal,
Bind);
}
- virtual bool matchesChildOf(const Stmt &StmtNode,
- const UntypedBaseMatcher &BaseMatcher,
- BoundNodesTreeBuilder *Builder,
- TraversalKind Traversal,
- BindKind Bind) {
- return matchesRecursively(StmtNode, BaseMatcher, 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 +344,20 @@
// result callback for every node that matches.
template <typename T>
void match(const T &node) {
- for (std::vector< std::pair<const UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> >::const_iterator
+ for (std::vector<MatchFinder::Trigger>::const_iterator
It = Triggers->begin(), End = Triggers->end();
It != End; ++It) {
BoundNodesTreeBuilder Builder;
- if (It->first->matches(node, this, &Builder)) {
+ if (It->first->matches(ast_type_traits::DynTypedNode::create(node),
+ this, &Builder)) {
BoundNodesTree BoundNodes = Builder.build();
MatchVisitor Visitor(ActiveASTContext, It->second);
BoundNodes.visitMatches(&Visitor);
}
}
}
- std::vector< std::pair<const UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> > *const Triggers;
+ std::vector<MatchFinder::Trigger> *const Triggers;
ASTContext *ActiveASTContext;
// Maps a canonical type to its TypedefDecls.
@@ -474,8 +459,7 @@
class MatchASTConsumer : public ASTConsumer {
public:
- MatchASTConsumer(std::vector< std::pair<const UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> > *Triggers,
+ MatchASTConsumer(std::vector<MatchFinder::Trigger> *Triggers,
MatchFinder::ParsingDoneTestCallback *ParsingDone)
: Visitor(Triggers),
ParsingDone(ParsingDone) {}
@@ -508,8 +492,7 @@
MatchFinder::MatchFinder() : ParsingDone(NULL) {}
MatchFinder::~MatchFinder() {
- for (std::vector< std::pair<const internal::UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> >::const_iterator
+ for (std::vector<Trigger>::const_iterator
It = Triggers.begin(), End = Triggers.end();
It != End; ++It) {
delete It->first;
@@ -519,19 +502,19 @@
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action) {
Triggers.push_back(std::make_pair(
- new internal::TypedBaseMatcher<Decl>(NodeMatch), Action));
+ new internal::Matcher<Decl>(NodeMatch), Action));
}
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
MatchCallback *Action) {
Triggers.push_back(std::make_pair(
- new internal::TypedBaseMatcher<QualType>(NodeMatch), Action));
+ new internal::Matcher<QualType>(NodeMatch), Action));
}
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action) {
Triggers.push_back(std::make_pair(
- new internal::TypedBaseMatcher<Stmt>(NodeMatch), Action));
+ new internal::Matcher<Stmt>(NodeMatch), Action));
}
ASTConsumer *MatchFinder::newASTConsumer() {
Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -1914,9 +1914,8 @@
TOOLING_COMPILE_ASSERT((llvm::is_same<NodeType, Decl>::value) ||
(llvm::is_same<NodeType, Stmt>::value),
assert_node_type_is_accessible);
- internal::TypedBaseMatcher<Decl> ChildMatcher(AMatcher);
return Finder->matchesChildOf(
- Node, ChildMatcher, Builder,
+ Node, AMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_First);
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits