Home | History | Annotate | Download | only in ASTMatchers
      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