1 //===--- ASTMatchersInternal.cpp - Structural query framework -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Implements the base layer of the matcher framework. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/ASTMatchers/ASTMatchers.h" 15 #include "clang/ASTMatchers/ASTMatchersInternal.h" 16 17 namespace clang { 18 namespace ast_matchers { 19 namespace internal { 20 21 void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) { 22 if (Bindings.empty()) 23 Bindings.push_back(BoundNodesMap()); 24 for (unsigned i = 0, e = Bindings.size(); i != e; ++i) { 25 ResultVisitor->visitMatch(BoundNodes(Bindings[i])); 26 } 27 } 28 29 DynTypedMatcher::MatcherStorage::~MatcherStorage() {} 30 31 void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) { 32 for (unsigned i = 0, e = Other.Bindings.size(); i != e; ++i) { 33 Bindings.push_back(Other.Bindings[i]); 34 } 35 } 36 37 bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode, 38 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, 39 ArrayRef<DynTypedMatcher> InnerMatchers) { 40 if (InnerMatchers.size() != 1) 41 return false; 42 43 // The 'unless' matcher will always discard the result: 44 // If the inner matcher doesn't match, unless returns true, 45 // but the inner matcher cannot have bound anything. 46 // If the inner matcher matches, the result is false, and 47 // any possible binding will be discarded. 48 // We still need to hand in all the bound nodes up to this 49 // point so the inner matcher can depend on bound nodes, 50 // and we need to actively discard the bound nodes, otherwise 51 // the inner matcher will reset the bound nodes if it doesn't 52 // match, but this would be inversed by 'unless'. 53 BoundNodesTreeBuilder Discard(*Builder); 54 return !InnerMatchers[0].matches(DynNode, Finder, &Discard); 55 } 56 57 bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, 58 ASTMatchFinder *Finder, 59 BoundNodesTreeBuilder *Builder, 60 ArrayRef<DynTypedMatcher> InnerMatchers) { 61 // allOf leads to one matcher for each alternative in the first 62 // matcher combined with each alternative in the second matcher. 63 // Thus, we can reuse the same Builder. 64 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { 65 if (!InnerMatchers[i].matches(DynNode, Finder, Builder)) 66 return false; 67 } 68 return true; 69 } 70 71 bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, 72 ASTMatchFinder *Finder, 73 BoundNodesTreeBuilder *Builder, 74 ArrayRef<DynTypedMatcher> InnerMatchers) { 75 BoundNodesTreeBuilder Result; 76 bool Matched = false; 77 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { 78 BoundNodesTreeBuilder BuilderInner(*Builder); 79 if (InnerMatchers[i].matches(DynNode, Finder, &BuilderInner)) { 80 Matched = true; 81 Result.addMatch(BuilderInner); 82 } 83 } 84 *Builder = Result; 85 return Matched; 86 } 87 88 bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, 89 ASTMatchFinder *Finder, 90 BoundNodesTreeBuilder *Builder, 91 ArrayRef<DynTypedMatcher> InnerMatchers) { 92 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { 93 BoundNodesTreeBuilder Result = *Builder; 94 if (InnerMatchers[i].matches(DynNode, Finder, &Result)) { 95 *Builder = Result; 96 return true; 97 } 98 } 99 return false; 100 } 101 102 } // end namespace internal 103 } // end namespace ast_matchers 104 } // end namespace clang 105