summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp425
1 files changed, 259 insertions, 166 deletions
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 6ebd736..f6dcb97 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -30,10 +30,21 @@ namespace {
typedef MatchFinder::MatchCallback MatchCallback;
+// The maximum number of memoization entries to store.
+// 10k has been experimentally found to give a good trade-off
+// of performance vs. memory consumption by running matcher
+// that match on every statement over a very large codebase.
+//
+// FIXME: Do some performance optimization in general and
+// revisit this number; also, put up micro-benchmarks that we can
+// optimize this on.
+static const unsigned MaxMemoizationEntries = 10000;
+
// We use memoization to avoid running the same matcher on the same
-// AST node twice. This pair is the key for looking up match
+// AST node twice. This struct 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.
+// identifying the matcher), a pointer to the AST node and the
+// bound nodes before the matcher was executed.
//
// We currently only memoize on nodes whose pointers identify the
// nodes (\c Stmt and \c Decl, but not \c QualType or \c TypeLoc).
@@ -41,12 +52,24 @@ typedef MatchFinder::MatchCallback MatchCallback;
// 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;
+struct MatchKey {
+ uint64_t MatcherID;
+ ast_type_traits::DynTypedNode Node;
+ BoundNodesTreeBuilder BoundNodes;
+
+ bool operator<(const MatchKey &Other) const {
+ if (MatcherID != Other.MatcherID)
+ return MatcherID < Other.MatcherID;
+ if (Node != Other.Node)
+ return Node < Other.Node;
+ return BoundNodes < Other.BoundNodes;
+ }
+};
// Used to store the result of a match and possibly bound nodes.
struct MemoizedMatchResult {
bool ResultOfMatch;
- BoundNodesTree Nodes;
+ BoundNodesTreeBuilder Nodes;
};
// A RecursiveASTVisitor that traverses all children or all descendants of
@@ -103,6 +126,12 @@ public:
else if (const TypeLoc *T = DynNode.get<TypeLoc>())
traverse(*T);
// FIXME: Add other base types after adding tests.
+
+ // It's OK to always overwrite the bound nodes, as if there was
+ // no match in this recursive branch, the result set is empty
+ // anyway.
+ *Builder = ResultBindings;
+
return Matches;
}
@@ -220,18 +249,20 @@ private:
return true;
}
if (Bind != ASTMatchFinder::BK_All) {
- if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node),
- Finder, Builder)) {
+ BoundNodesTreeBuilder RecursiveBuilder(*Builder);
+ if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
+ &RecursiveBuilder)) {
Matches = true;
- return false; // Abort as soon as a match is found.
+ ResultBindings.addMatch(RecursiveBuilder);
+ return false; // Abort as soon as a match is found.
}
} else {
- BoundNodesTreeBuilder RecursiveBuilder;
- if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node),
- Finder, &RecursiveBuilder)) {
+ BoundNodesTreeBuilder RecursiveBuilder(*Builder);
+ if (Matcher->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
+ &RecursiveBuilder)) {
// After the first match the matcher succeeds.
Matches = true;
- Builder->addMatch(RecursiveBuilder.build());
+ ResultBindings.addMatch(RecursiveBuilder);
}
}
return true;
@@ -251,6 +282,7 @@ private:
const DynTypedMatcher *const Matcher;
ASTMatchFinder *const Finder;
BoundNodesTreeBuilder *const Builder;
+ BoundNodesTreeBuilder ResultBindings;
int CurrentDepth;
const int MaxDepth;
const ASTMatchFinder::TraversalKind Traversal;
@@ -263,21 +295,31 @@ private:
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
public ASTMatchFinder {
public:
- MatchASTVisitor(std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> > *MatcherCallbackPairs)
- : MatcherCallbackPairs(MatcherCallbackPairs),
- ActiveASTContext(NULL) {
- }
+ MatchASTVisitor(
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *
+ MatcherCallbackPairs)
+ : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(NULL) {}
void onStartOfTranslationUnit() {
- for (std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> >::const_iterator
- I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
+ for (std::vector<std::pair<internal::DynTypedMatcher,
+ MatchCallback *> >::const_iterator
+ I = MatcherCallbackPairs->begin(),
+ E = MatcherCallbackPairs->end();
I != E; ++I) {
I->second->onStartOfTranslationUnit();
}
}
+ void onEndOfTranslationUnit() {
+ for (std::vector<std::pair<internal::DynTypedMatcher,
+ MatchCallback *> >::const_iterator
+ I = MatcherCallbackPairs->begin(),
+ E = MatcherCallbackPairs->end();
+ I != E; ++I) {
+ I->second->onEndOfTranslationUnit();
+ }
+ }
+
void set_active_ast_context(ASTContext *NewActiveASTContext) {
ActiveASTContext = NewActiveASTContext;
}
@@ -285,7 +327,7 @@ public:
// The following Visit*() and Traverse*() functions "override"
// methods in RecursiveASTVisitor.
- bool VisitTypedefDecl(TypedefDecl *DeclNode) {
+ bool VisitTypedefNameDecl(TypedefNameDecl *DeclNode) {
// When we see 'typedef A B', we add name 'B' to the set of names
// A's canonical type maps to. This is necessary for implementing
// isDerivedFrom(x) properly, where x can be the name of the base
@@ -332,25 +374,30 @@ public:
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder, int MaxDepth,
TraversalKind Traversal, BindKind Bind) {
- const UntypedMatchInput input(Matcher.getID(), Node.getMemoizationData());
-
// For AST-nodes that don't have an identity, we can't memoize.
- if (!input.second)
+ if (!Node.getMemoizationData())
return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal,
Bind);
- std::pair<MemoizationMap::iterator, bool> InsertResult
- = ResultCache.insert(std::make_pair(input, MemoizedMatchResult()));
- if (InsertResult.second) {
- BoundNodesTreeBuilder DescendantBoundNodesBuilder;
- InsertResult.first->second.ResultOfMatch =
- matchesRecursively(Node, Matcher, &DescendantBoundNodesBuilder,
- MaxDepth, Traversal, Bind);
- InsertResult.first->second.Nodes =
- DescendantBoundNodesBuilder.build();
+ MatchKey Key;
+ Key.MatcherID = Matcher.getID();
+ Key.Node = Node;
+ // Note that we key on the bindings *before* the match.
+ Key.BoundNodes = *Builder;
+
+ MemoizationMap::iterator I = ResultCache.find(Key);
+ if (I != ResultCache.end()) {
+ *Builder = I->second.Nodes;
+ return I->second.ResultOfMatch;
}
- InsertResult.first->second.Nodes.copyTo(Builder);
- return InsertResult.first->second.ResultOfMatch;
+
+ MemoizedMatchResult Result;
+ Result.Nodes = *Builder;
+ Result.ResultOfMatch = matchesRecursively(Node, Matcher, &Result.Nodes,
+ MaxDepth, Traversal, Bind);
+ ResultCache[Key] = Result;
+ *Builder = Result.Nodes;
+ return Result.ResultOfMatch;
}
// Matches children or descendants of 'Node' with 'BaseMatcher'.
@@ -373,14 +420,18 @@ public:
BoundNodesTreeBuilder *Builder,
TraversalKind Traversal,
BindKind Bind) {
- return matchesRecursively(Node, Matcher, Builder, 1, Traversal,
- Bind);
+ if (ResultCache.size() > MaxMemoizationEntries)
+ ResultCache.clear();
+ return memoizedMatchesRecursively(Node, Matcher, Builder, 1, Traversal,
+ Bind);
}
// Implements ASTMatchFinder::matchesDescendantOf.
virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
BindKind Bind) {
+ if (ResultCache.size() > MaxMemoizationEntries)
+ ResultCache.clear();
return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX,
TK_AsIs, Bind);
}
@@ -389,6 +440,10 @@ public:
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) {
+ // Reset the cache outside of the recursive call to make sure we
+ // don't invalidate any iterators.
+ if (ResultCache.size() > MaxMemoizationEntries)
+ ResultCache.clear();
return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder,
MatchMode);
}
@@ -396,15 +451,15 @@ public:
// Matches all registered matchers on the given node and calls the
// result callback for every node that matches.
void match(const ast_type_traits::DynTypedNode& Node) {
- for (std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> >::const_iterator
- I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
+ for (std::vector<std::pair<internal::DynTypedMatcher,
+ MatchCallback *> >::const_iterator
+ I = MatcherCallbackPairs->begin(),
+ E = MatcherCallbackPairs->end();
I != E; ++I) {
BoundNodesTreeBuilder Builder;
- if (I->first->matches(Node, this, &Builder)) {
- BoundNodesTree BoundNodes = Builder.build();
+ if (I->first.matches(Node, this, &Builder)) {
MatchVisitor Visitor(ActiveASTContext, I->second);
- BoundNodes.visitMatches(&Visitor);
+ Builder.visitMatches(&Visitor);
}
}
}
@@ -450,60 +505,71 @@ private:
assert(false && "Found node that is not in the parent map.");
return false;
}
- const UntypedMatchInput input(Matcher.getID(), Node.getMemoizationData());
- MemoizationMap::iterator I = ResultCache.find(input);
- if (I == ResultCache.end()) {
- BoundNodesTreeBuilder AncestorBoundNodesBuilder;
- bool Matches = false;
- if (Parents.size() == 1) {
- // Only one parent - do recursive memoization.
- const ast_type_traits::DynTypedNode Parent = Parents[0];
- if (Matcher.matches(Parent, this, &AncestorBoundNodesBuilder)) {
- Matches = true;
- } else if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
- Matches = memoizedMatchesAncestorOfRecursively(
- Parent, Matcher, &AncestorBoundNodesBuilder, MatchMode);
+ MatchKey Key;
+ Key.MatcherID = Matcher.getID();
+ Key.Node = Node;
+ Key.BoundNodes = *Builder;
+
+ // Note that we cannot use insert and reuse the iterator, as recursive
+ // calls to match might invalidate the result cache iterators.
+ MemoizationMap::iterator I = ResultCache.find(Key);
+ if (I != ResultCache.end()) {
+ *Builder = I->second.Nodes;
+ return I->second.ResultOfMatch;
+ }
+ MemoizedMatchResult Result;
+ Result.ResultOfMatch = false;
+ Result.Nodes = *Builder;
+ if (Parents.size() == 1) {
+ // Only one parent - do recursive memoization.
+ const ast_type_traits::DynTypedNode Parent = Parents[0];
+ if (Matcher.matches(Parent, this, &Result.Nodes)) {
+ Result.ResultOfMatch = true;
+ } else if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
+ // Reset the results to not include the bound nodes from the failed
+ // match above.
+ Result.Nodes = *Builder;
+ Result.ResultOfMatch = memoizedMatchesAncestorOfRecursively(
+ Parent, Matcher, &Result.Nodes, MatchMode);
+ // Once we get back from the recursive call, the result will be the
+ // same as the parent's result.
+ }
+ } else {
+ // Multiple parents - BFS over the rest of the nodes.
+ llvm::DenseSet<const void *> Visited;
+ std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(),
+ Parents.end());
+ while (!Queue.empty()) {
+ Result.Nodes = *Builder;
+ if (Matcher.matches(Queue.front(), this, &Result.Nodes)) {
+ Result.ResultOfMatch = true;
+ break;
}
- } else {
- // Multiple parents - BFS over the rest of the nodes.
- llvm::DenseSet<const void *> Visited;
- std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(),
- Parents.end());
- while (!Queue.empty()) {
- if (Matcher.matches(Queue.front(), this,
- &AncestorBoundNodesBuilder)) {
- Matches = true;
- break;
- }
- if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
- ASTContext::ParentVector Ancestors =
- ActiveASTContext->getParents(Queue.front());
- for (ASTContext::ParentVector::const_iterator I = Ancestors.begin(),
- E = Ancestors.end();
- I != E; ++I) {
- // Make sure we do not visit the same node twice.
- // Otherwise, we'll visit the common ancestors as often as there
- // are splits on the way down.
- if (Visited.insert(I->getMemoizationData()).second)
- Queue.push_back(*I);
- }
+ if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
+ ASTContext::ParentVector Ancestors =
+ ActiveASTContext->getParents(Queue.front());
+ for (ASTContext::ParentVector::const_iterator I = Ancestors.begin(),
+ E = Ancestors.end();
+ I != E; ++I) {
+ // Make sure we do not visit the same node twice.
+ // Otherwise, we'll visit the common ancestors as often as there
+ // are splits on the way down.
+ if (Visited.insert(I->getMemoizationData()).second)
+ Queue.push_back(*I);
}
- Queue.pop_front();
}
+ Queue.pop_front();
}
-
- I = ResultCache.insert(std::make_pair(input, MemoizedMatchResult()))
- .first;
- I->second.Nodes = AncestorBoundNodesBuilder.build();
- I->second.ResultOfMatch = Matches;
}
- I->second.Nodes.copyTo(Builder);
- return I->second.ResultOfMatch;
+ ResultCache[Key] = Result;
+
+ *Builder = Result.Nodes;
+ return Result.ResultOfMatch;
}
// Implements a BoundNodesTree::Visitor that calls a MatchCallback with
// the aggregated bound nodes for each match.
- class MatchVisitor : public BoundNodesTree::Visitor {
+ class MatchVisitor : public BoundNodesTreeBuilder::Visitor {
public:
MatchVisitor(ASTContext* Context,
MatchFinder::MatchCallback* Callback)
@@ -525,28 +591,74 @@ private:
BoundNodesTreeBuilder *Builder) {
const Type *const CanonicalType =
ActiveASTContext->getCanonicalType(TypeNode);
- const std::set<const TypedefDecl*> &Aliases = TypeAliases[CanonicalType];
- for (std::set<const TypedefDecl*>::const_iterator
+ const std::set<const TypedefNameDecl *> &Aliases =
+ TypeAliases[CanonicalType];
+ for (std::set<const TypedefNameDecl*>::const_iterator
It = Aliases.begin(), End = Aliases.end();
It != End; ++It) {
- if (Matcher.matches(**It, this, Builder))
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(**It, this, &Result)) {
+ *Builder = Result;
return true;
+ }
}
return false;
}
- std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> > *const MatcherCallbackPairs;
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *const
+ MatcherCallbackPairs;
ASTContext *ActiveASTContext;
// Maps a canonical type to its TypedefDecls.
- llvm::DenseMap<const Type*, std::set<const TypedefDecl*> > TypeAliases;
+ llvm::DenseMap<const Type*, std::set<const TypedefNameDecl*> > TypeAliases;
// Maps (matcher, node) -> the match result for memoization.
- typedef llvm::DenseMap<UntypedMatchInput, MemoizedMatchResult> MemoizationMap;
+ typedef std::map<MatchKey, MemoizedMatchResult> MemoizationMap;
MemoizationMap ResultCache;
};
+static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) {
+ // Type::getAs<...>() drills through typedefs.
+ if (TypeNode->getAs<DependentNameType>() != NULL ||
+ TypeNode->getAs<DependentTemplateSpecializationType>() != NULL ||
+ TypeNode->getAs<TemplateTypeParmType>() != NULL)
+ // Dependent names and template TypeNode parameters will be matched when
+ // the template is instantiated.
+ return NULL;
+ TemplateSpecializationType const *TemplateType =
+ TypeNode->getAs<TemplateSpecializationType>();
+ if (TemplateType == NULL) {
+ return TypeNode->getAsCXXRecordDecl();
+ }
+ if (TemplateType->getTemplateName().isDependent())
+ // Dependent template specializations will be matched when the
+ // template is instantiated.
+ return NULL;
+
+ // For template specialization types which are specializing a template
+ // declaration which is an explicit or partial specialization of another
+ // template declaration, getAsCXXRecordDecl() returns the corresponding
+ // ClassTemplateSpecializationDecl.
+ //
+ // For template specialization types which are specializing a template
+ // declaration which is neither an explicit nor partial specialization of
+ // another template declaration, getAsCXXRecordDecl() returns NULL and
+ // we get the CXXRecordDecl of the templated declaration.
+ CXXRecordDecl *SpecializationDecl = TemplateType->getAsCXXRecordDecl();
+ if (SpecializationDecl != NULL) {
+ return SpecializationDecl;
+ }
+ NamedDecl *Templated =
+ TemplateType->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
+ if (CXXRecordDecl *TemplatedRecord = dyn_cast<CXXRecordDecl>(Templated)) {
+ return TemplatedRecord;
+ }
+ // Now it can still be that we have an alias template.
+ TypeAliasDecl *AliasDecl = dyn_cast<TypeAliasDecl>(Templated);
+ assert(AliasDecl);
+ return getAsCXXRecordDecl(AliasDecl->getUnderlyingType().getTypePtr());
+}
+
// Returns true if the given class is directly or indirectly derived
// from a base type with the given name. A class is not considered to be
// derived from itself.
@@ -557,58 +669,26 @@ bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
return false;
typedef CXXRecordDecl::base_class_const_iterator BaseIterator;
for (BaseIterator It = Declaration->bases_begin(),
- End = Declaration->bases_end(); It != End; ++It) {
+ End = Declaration->bases_end();
+ It != End; ++It) {
const Type *TypeNode = It->getType().getTypePtr();
if (typeHasMatchingAlias(TypeNode, Base, Builder))
return true;
- // Type::getAs<...>() drills through typedefs.
- if (TypeNode->getAs<DependentNameType>() != NULL ||
- TypeNode->getAs<DependentTemplateSpecializationType>() != NULL ||
- TypeNode->getAs<TemplateTypeParmType>() != NULL)
- // Dependent names and template TypeNode parameters will be matched when
- // the template is instantiated.
+ CXXRecordDecl *ClassDecl = getAsCXXRecordDecl(TypeNode);
+ if (ClassDecl == NULL)
continue;
- CXXRecordDecl *ClassDecl = NULL;
- TemplateSpecializationType const *TemplateType =
- TypeNode->getAs<TemplateSpecializationType>();
- if (TemplateType != NULL) {
- if (TemplateType->getTemplateName().isDependent())
- // Dependent template specializations will be matched when the
- // template is instantiated.
- continue;
-
- // For template specialization types which are specializing a template
- // declaration which is an explicit or partial specialization of another
- // template declaration, getAsCXXRecordDecl() returns the corresponding
- // ClassTemplateSpecializationDecl.
- //
- // For template specialization types which are specializing a template
- // declaration which is neither an explicit nor partial specialization of
- // another template declaration, getAsCXXRecordDecl() returns NULL and
- // we get the CXXRecordDecl of the templated declaration.
- CXXRecordDecl *SpecializationDecl =
- TemplateType->getAsCXXRecordDecl();
- if (SpecializationDecl != NULL) {
- ClassDecl = SpecializationDecl;
- } else {
- ClassDecl = dyn_cast<CXXRecordDecl>(
- TemplateType->getTemplateName()
- .getAsTemplateDecl()->getTemplatedDecl());
- }
- } else {
- ClassDecl = TypeNode->getAsCXXRecordDecl();
- }
- assert(ClassDecl != NULL);
if (ClassDecl == Declaration) {
// This can happen for recursive template definitions; if the
// current declaration did not match, we can safely return false.
- assert(TemplateType);
return false;
}
- if (Base.matches(*ClassDecl, this, Builder))
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Base.matches(*ClassDecl, this, &Result)) {
+ *Builder = Result;
return true;
+ }
if (classIsDerivedFrom(ClassDecl, Base, Builder))
return true;
}
@@ -664,25 +744,19 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
class MatchASTConsumer : public ASTConsumer {
public:
- MatchASTConsumer(
- std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> > *MatcherCallbackPairs,
- MatchFinder::ParsingDoneTestCallback *ParsingDone)
- : Visitor(MatcherCallbackPairs),
- ParsingDone(ParsingDone) {}
+ MatchASTConsumer(MatchFinder *Finder,
+ MatchFinder::ParsingDoneTestCallback *ParsingDone)
+ : Finder(Finder), ParsingDone(ParsingDone) {}
private:
virtual void HandleTranslationUnit(ASTContext &Context) {
if (ParsingDone != NULL) {
ParsingDone->run();
}
- Visitor.set_active_ast_context(&Context);
- Visitor.onStartOfTranslationUnit();
- Visitor.TraverseDecl(Context.getTranslationUnitDecl());
- Visitor.set_active_ast_context(NULL);
+ Finder->matchAST(Context);
}
- MatchASTVisitor Visitor;
+ MatchFinder *Finder;
MatchFinder::ParsingDoneTestCallback *ParsingDone;
};
@@ -699,53 +773,64 @@ MatchFinder::ParsingDoneTestCallback::~ParsingDoneTestCallback() {}
MatchFinder::MatchFinder() : ParsingDone(NULL) {}
-MatchFinder::~MatchFinder() {
- for (std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> >::const_iterator
- It = MatcherCallbackPairs.begin(), End = MatcherCallbackPairs.end();
- It != End; ++It) {
- delete It->first;
- }
-}
+MatchFinder::~MatchFinder() {}
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new internal::Matcher<Decl>(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new internal::Matcher<QualType>(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new internal::Matcher<Stmt>(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new NestedNameSpecifierMatcher(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new NestedNameSpecifierLocMatcher(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new TypeLocMatcher(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
+}
+
+bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
+ MatchCallback *Action) {
+ if (NodeMatch.canConvertTo<Decl>()) {
+ addMatcher(NodeMatch.convertTo<Decl>(), Action);
+ return true;
+ } else if (NodeMatch.canConvertTo<QualType>()) {
+ addMatcher(NodeMatch.convertTo<QualType>(), Action);
+ return true;
+ } else if (NodeMatch.canConvertTo<Stmt>()) {
+ addMatcher(NodeMatch.convertTo<Stmt>(), Action);
+ return true;
+ } else if (NodeMatch.canConvertTo<NestedNameSpecifier>()) {
+ addMatcher(NodeMatch.convertTo<NestedNameSpecifier>(), Action);
+ return true;
+ } else if (NodeMatch.canConvertTo<NestedNameSpecifierLoc>()) {
+ addMatcher(NodeMatch.convertTo<NestedNameSpecifierLoc>(), Action);
+ return true;
+ } else if (NodeMatch.canConvertTo<TypeLoc>()) {
+ addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
+ return true;
+ }
+ return false;
}
ASTConsumer *MatchFinder::newASTConsumer() {
- return new internal::MatchASTConsumer(&MatcherCallbackPairs, ParsingDone);
+ return new internal::MatchASTConsumer(this, ParsingDone);
}
void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
@@ -755,6 +840,14 @@ void MatchFinder::match(const clang::ast_type_traits::DynTypedNode &Node,
Visitor.match(Node);
}
+void MatchFinder::matchAST(ASTContext &Context) {
+ internal::MatchASTVisitor Visitor(&MatcherCallbackPairs);
+ Visitor.set_active_ast_context(&Context);
+ Visitor.onStartOfTranslationUnit();
+ Visitor.TraverseDecl(Context.getTranslationUnitDecl());
+ Visitor.onEndOfTranslationUnit();
+}
+
void MatchFinder::registerTestCallbackAfterParsing(
MatchFinder::ParsingDoneTestCallback *NewParsingDone) {
ParsingDone = NewParsingDone;
OpenPOWER on IntegriCloud