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<std::pair<const internal::DynTypedMatcher*, MatchCallback*> >
+ MatcherCallbackPairs;
/// \brief Called when parsing is done.
ParsingDoneTestCallback *ParsingDone;
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 <typename T>
- const T getNodeAs(StringRef ID) const {
+ const T *getNodeAs(StringRef ID) const {
return MyBoundNodes.getNodeAs<T>(ID);
}
/// @{
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);
}
/// @}
/// 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;
/// 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;
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:
}
};
+/// \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
/// 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)
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.
};
/// \brief IsBaseType<T>::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 <typename T>
struct IsBaseType {
static const bool value =
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.
///
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;
};
}
private:
- const TypedBaseMatcher<ChildT> ChildMatcher;
+ const Matcher<ChildT> ChildMatcher;
};
/// \brief Matches nodes of type T that have child nodes of type ChildT for
}
private:
- const TypedBaseMatcher<ChildT> ChildMatcher;
+ const Matcher<ChildT> ChildMatcher;
};
/// \brief Matches nodes of type T if the given Matcher<T> does not match.
}
private:
- const TypedBaseMatcher<DescendantT> DescendantMatcher;
+ const Matcher<DescendantT> DescendantMatcher;
};
/// \brief Matches nodes of type T that have at least one descendant node of
}
private:
- const TypedBaseMatcher<DescendantT> DescendantMatcher;
+ const Matcher<DescendantT> DescendantMatcher;
};
/// \brief Matches on nodes that have a getValue() method if getValue() equals
#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<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);
}
///
/// 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 <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.
+ const void *getMemoizationData() const;
+
private:
/// \brief Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
/// \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 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<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; }
+};
+
+inline const void *DynTypedNode::getMemoizationData() const {
+ switch (Tag) {
+ case NT_Decl: return BaseConverter<Decl>::get(Tag, Storage.buffer);
+ case NT_Stmt: return BaseConverter<Stmt>::get(Tag, Storage.buffer);
+ default: return NULL;
+ };
+}
} // end namespace ast_type_traits
} // end namespace clang
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<uint64_t, const void*> UntypedMatchInput;
// Used to store the result of a match and possibly bound nodes.
// 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),
// 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;
}
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.
}
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());
}
}
- const UntypedBaseMatcher *const BaseMatcher;
+ const DynTypedMatcher *const Matcher;
ASTMatchFinder *const Finder;
BoundNodesTreeBuilder *const Builder;
int CurrentDepth;
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
public ASTMatchFinder {
public:
- MatchASTVisitor(std::vector< std::pair<const UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> > *Triggers)
- : Triggers(Triggers),
+ MatchASTVisitor(std::vector<std::pair<const internal::DynTypedMatcher*,
+ MatchCallback*> > *MatcherCallbackPairs)
+ : MatcherCallbackPairs(MatcherCallbackPairs),
ActiveASTContext(NULL) {
}
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();
}
// 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);
}
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);
}
// 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
- It = Triggers->begin(), End = Triggers->end();
- It != End; ++It) {
+ for (std::vector<std::pair<const internal::DynTypedMatcher*,
+ MatchCallback*> >::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 UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> > *const Triggers;
+ std::vector<std::pair<const internal::DynTypedMatcher*,
+ MatchCallback*> > *const MatcherCallbackPairs;
ASTContext *ActiveASTContext;
// Maps a canonical type to its TypedefDecls.
class MatchASTConsumer : public ASTConsumer {
public:
- MatchASTConsumer(std::vector< std::pair<const UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> > *Triggers,
- MatchFinder::ParsingDoneTestCallback *ParsingDone)
- : Visitor(Triggers),
- ParsingDone(ParsingDone) {}
+ MatchASTConsumer(
+ std::vector<std::pair<const internal::DynTypedMatcher*,
+ MatchCallback*> > *MatcherCallbackPairs,
+ MatchFinder::ParsingDoneTestCallback *ParsingDone)
+ : Visitor(MatcherCallbackPairs),
+ ParsingDone(ParsingDone) {}
private:
virtual void HandleTranslationUnit(ASTContext &Context) {
MatchFinder::MatchFinder() : ParsingDone(NULL) {}
MatchFinder::~MatchFinder() {
- for (std::vector< std::pair<const internal::UntypedBaseMatcher*,
- MatchFinder::MatchCallback*> >::const_iterator
- It = Triggers.begin(), End = Triggers.end();
+ for (std::vector<std::pair<const internal::DynTypedMatcher*,
+ MatchCallback*> >::const_iterator
+ It = MatcherCallbackPairs.begin(), End = MatcherCallbackPairs.end();
It != End; ++It) {
delete It->first;
}
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action) {
- Triggers.push_back(std::make_pair(
- new internal::TypedBaseMatcher<Decl>(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(
+ 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));
+ MatcherCallbackPairs.push_back(std::make_pair(
+ 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));
+ MatcherCallbackPairs.push_back(std::make_pair(
+ new internal::Matcher<Stmt>(NodeMatch), Action));
}
ASTConsumer *MatchFinder::newASTConsumer() {
- return new internal::MatchASTConsumer(&Triggers, ParsingDone);
+ return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone);
}
void MatchFinder::registerTestCallbackAfterParsing(
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);
}