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 bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const { 30 const auto From = getSupportedKind(); 31 auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>(); 32 auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>(); 33 /// Mimic the implicit conversions of Matcher<>. 34 /// - From Matcher<Type> to Matcher<QualType> 35 if (From.isSame(TypeKind) && To.isSame(QualKind)) return true; 36 /// - From Matcher<Base> to Matcher<Derived> 37 return From.isBaseOf(To); 38 } 39 40 DynTypedMatcher::MatcherStorage::~MatcherStorage() {} 41 42 void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) { 43 for (unsigned i = 0, e = Other.Bindings.size(); i != e; ++i) { 44 Bindings.push_back(Other.Bindings[i]); 45 } 46 } 47 48 bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode, 49 ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, 50 ArrayRef<DynTypedMatcher> InnerMatchers) { 51 if (InnerMatchers.size() != 1) 52 return false; 53 54 // The 'unless' matcher will always discard the result: 55 // If the inner matcher doesn't match, unless returns true, 56 // but the inner matcher cannot have bound anything. 57 // If the inner matcher matches, the result is false, and 58 // any possible binding will be discarded. 59 // We still need to hand in all the bound nodes up to this 60 // point so the inner matcher can depend on bound nodes, 61 // and we need to actively discard the bound nodes, otherwise 62 // the inner matcher will reset the bound nodes if it doesn't 63 // match, but this would be inversed by 'unless'. 64 BoundNodesTreeBuilder Discard(*Builder); 65 return !InnerMatchers[0].matches(DynNode, Finder, &Discard); 66 } 67 68 bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, 69 ASTMatchFinder *Finder, 70 BoundNodesTreeBuilder *Builder, 71 ArrayRef<DynTypedMatcher> InnerMatchers) { 72 // allOf leads to one matcher for each alternative in the first 73 // matcher combined with each alternative in the second matcher. 74 // Thus, we can reuse the same Builder. 75 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { 76 if (!InnerMatchers[i].matches(DynNode, Finder, Builder)) 77 return false; 78 } 79 return true; 80 } 81 82 bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, 83 ASTMatchFinder *Finder, 84 BoundNodesTreeBuilder *Builder, 85 ArrayRef<DynTypedMatcher> InnerMatchers) { 86 BoundNodesTreeBuilder Result; 87 bool Matched = false; 88 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { 89 BoundNodesTreeBuilder BuilderInner(*Builder); 90 if (InnerMatchers[i].matches(DynNode, Finder, &BuilderInner)) { 91 Matched = true; 92 Result.addMatch(BuilderInner); 93 } 94 } 95 *Builder = std::move(Result); 96 return Matched; 97 } 98 99 bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, 100 ASTMatchFinder *Finder, 101 BoundNodesTreeBuilder *Builder, 102 ArrayRef<DynTypedMatcher> InnerMatchers) { 103 for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { 104 BoundNodesTreeBuilder Result = *Builder; 105 if (InnerMatchers[i].matches(DynNode, Finder, &Result)) { 106 *Builder = std::move(Result); 107 return true; 108 } 109 } 110 return false; 111 } 112 113 } // end namespace internal 114 } // end namespace ast_matchers 115 } // end namespace clang 116