clang API Documentation

ASTMatchersInternal.cpp
Go to the documentation of this file.
00001 //===--- ASTMatchersInternal.cpp - Structural query framework -------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  Implements the base layer of the matcher framework.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/ASTMatchers/ASTMatchers.h"
00015 #include "clang/ASTMatchers/ASTMatchersInternal.h"
00016 #include "llvm/ADT/SmallString.h"
00017 #include "llvm/Support/ManagedStatic.h"
00018 
00019 namespace clang {
00020 namespace ast_matchers {
00021 namespace internal {
00022 
00023 void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) {
00024   if (Bindings.empty())
00025     Bindings.push_back(BoundNodesMap());
00026   for (BoundNodesMap &Binding : Bindings) {
00027     ResultVisitor->visitMatch(BoundNodes(Binding));
00028   }
00029 }
00030 
00031 namespace {
00032 
00033 class VariadicMatcher : public DynMatcherInterface {
00034  public:
00035   VariadicMatcher(DynTypedMatcher::VariadicOperatorFunction Func,
00036                   std::vector<DynTypedMatcher> InnerMatchers)
00037       : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
00038 
00039   bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
00040                   ASTMatchFinder *Finder,
00041                   BoundNodesTreeBuilder *Builder) const override {
00042     return Func(DynNode, Finder, Builder, InnerMatchers);
00043   }
00044 
00045  private:
00046   DynTypedMatcher::VariadicOperatorFunction Func;
00047   std::vector<DynTypedMatcher> InnerMatchers;
00048 };
00049 
00050 class IdDynMatcher : public DynMatcherInterface {
00051  public:
00052   IdDynMatcher(StringRef ID,
00053                const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
00054       : ID(ID), InnerMatcher(InnerMatcher) {}
00055 
00056   bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
00057                   ASTMatchFinder *Finder,
00058                   BoundNodesTreeBuilder *Builder) const override {
00059     bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder);
00060     if (Result) Builder->setBinding(ID, DynNode);
00061     return Result;
00062   }
00063 
00064  private:
00065   const std::string ID;
00066   const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
00067 };
00068 
00069 /// \brief A matcher that always returns true.
00070 ///
00071 /// We only ever need one instance of this matcher, so we create a global one
00072 /// and reuse it to reduce the overhead of the matcher and increase the chance
00073 /// of cache hits.
00074 class TrueMatcherImpl : public DynMatcherInterface {
00075 public:
00076   TrueMatcherImpl() {
00077     Retain(); // Reference count will never become zero.
00078   }
00079   bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *,
00080                   BoundNodesTreeBuilder *) const override {
00081     return true;
00082   }
00083 };
00084 static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
00085 
00086 }  // namespace
00087 
00088 DynTypedMatcher DynTypedMatcher::constructVariadic(
00089     DynTypedMatcher::VariadicOperatorFunction Func,
00090     std::vector<DynTypedMatcher> InnerMatchers) {
00091   assert(InnerMatchers.size() > 0 && "Array must not be empty.");
00092   assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
00093                      [&InnerMatchers](const DynTypedMatcher &M) {
00094            return InnerMatchers[0].SupportedKind.isSame(M.SupportedKind);
00095          }) &&
00096          "SupportedKind must match!");
00097 
00098   // We must relax the restrict kind here.
00099   // The different operators might deal differently with a mismatch.
00100   // Make it the same as SupportedKind, since that is the broadest type we are
00101   // allowed to accept.
00102   auto SupportedKind = InnerMatchers[0].SupportedKind;
00103   return DynTypedMatcher(SupportedKind, SupportedKind,
00104                          new VariadicMatcher(Func, std::move(InnerMatchers)));
00105 }
00106 
00107 DynTypedMatcher DynTypedMatcher::trueMatcher(
00108     ast_type_traits::ASTNodeKind NodeKind) {
00109   return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
00110 }
00111 
00112 DynTypedMatcher DynTypedMatcher::dynCastTo(
00113     const ast_type_traits::ASTNodeKind Kind) const {
00114   auto Copy = *this;
00115   Copy.SupportedKind = Kind;
00116   Copy.RestrictKind =
00117       ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind);
00118   return Copy;
00119 }
00120 
00121 bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode,
00122                               ASTMatchFinder *Finder,
00123                               BoundNodesTreeBuilder *Builder) const {
00124   if (RestrictKind.isBaseOf(DynNode.getNodeKind()) &&
00125       Implementation->dynMatches(DynNode, Finder, Builder)) {
00126     return true;
00127   }
00128   // Delete all bindings when a matcher does not match.
00129   // This prevents unexpected exposure of bound nodes in unmatches
00130   // branches of the match tree.
00131   Builder->removeBindings([](const BoundNodesMap &) { return true; });
00132   return false;
00133 }
00134 
00135 llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
00136   if (!AllowBind) return llvm::None;
00137   auto Result = *this;
00138   Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
00139   return Result;
00140 }
00141 
00142 bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
00143   const auto From = getSupportedKind();
00144   auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>();
00145   auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>();
00146   /// Mimic the implicit conversions of Matcher<>.
00147   /// - From Matcher<Type> to Matcher<QualType>
00148   if (From.isSame(TypeKind) && To.isSame(QualKind)) return true;
00149   /// - From Matcher<Base> to Matcher<Derived>
00150   return From.isBaseOf(To);
00151 }
00152 
00153 void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
00154   Bindings.append(Other.Bindings.begin(), Other.Bindings.end());
00155 }
00156 
00157 bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
00158                       ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
00159                       ArrayRef<DynTypedMatcher> InnerMatchers) {
00160   if (InnerMatchers.size() != 1)
00161     return false;
00162 
00163   // The 'unless' matcher will always discard the result:
00164   // If the inner matcher doesn't match, unless returns true,
00165   // but the inner matcher cannot have bound anything.
00166   // If the inner matcher matches, the result is false, and
00167   // any possible binding will be discarded.
00168   // We still need to hand in all the bound nodes up to this
00169   // point so the inner matcher can depend on bound nodes,
00170   // and we need to actively discard the bound nodes, otherwise
00171   // the inner matcher will reset the bound nodes if it doesn't
00172   // match, but this would be inversed by 'unless'.
00173   BoundNodesTreeBuilder Discard(*Builder);
00174   return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
00175 }
00176 
00177 bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
00178                            ASTMatchFinder *Finder,
00179                            BoundNodesTreeBuilder *Builder,
00180                            ArrayRef<DynTypedMatcher> InnerMatchers) {
00181   // allOf leads to one matcher for each alternative in the first
00182   // matcher combined with each alternative in the second matcher.
00183   // Thus, we can reuse the same Builder.
00184   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
00185     if (!InnerMatcher.matches(DynNode, Finder, Builder))
00186       return false;
00187   }
00188   return true;
00189 }
00190 
00191 bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
00192                             ASTMatchFinder *Finder,
00193                             BoundNodesTreeBuilder *Builder,
00194                             ArrayRef<DynTypedMatcher> InnerMatchers) {
00195   BoundNodesTreeBuilder Result;
00196   bool Matched = false;
00197   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
00198     BoundNodesTreeBuilder BuilderInner(*Builder);
00199     if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) {
00200       Matched = true;
00201       Result.addMatch(BuilderInner);
00202     }
00203   }
00204   *Builder = std::move(Result);
00205   return Matched;
00206 }
00207 
00208 bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
00209                            ASTMatchFinder *Finder,
00210                            BoundNodesTreeBuilder *Builder,
00211                            ArrayRef<DynTypedMatcher> InnerMatchers) {
00212   for (const DynTypedMatcher &InnerMatcher : InnerMatchers) {
00213     BoundNodesTreeBuilder Result = *Builder;
00214     if (InnerMatcher.matches(DynNode, Finder, &Result)) {
00215       *Builder = std::move(Result);
00216       return true;
00217     }
00218   }
00219   return false;
00220 }
00221 
00222 HasNameMatcher::HasNameMatcher(StringRef NameRef)
00223     : UseUnqualifiedMatch(NameRef.find("::") == NameRef.npos), Name(NameRef) {
00224   assert(!Name.empty());
00225 }
00226 
00227 bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const {
00228   assert(UseUnqualifiedMatch);
00229   if (Node.getIdentifier()) {
00230     // Simple name.
00231     return Name == Node.getName();
00232   }
00233   if (Node.getDeclName()) {
00234     // Name needs to be constructed.
00235     llvm::SmallString<128> NodeName;
00236     llvm::raw_svector_ostream OS(NodeName);
00237     Node.printName(OS);
00238     return Name == OS.str();
00239   }
00240   return false;
00241 }
00242 
00243 bool HasNameMatcher::matchesNodeFull(const NamedDecl &Node) const {
00244   llvm::SmallString<128> NodeName = StringRef("::");
00245   llvm::raw_svector_ostream OS(NodeName);
00246   Node.printQualifiedName(OS);
00247   const StringRef FullName = OS.str();
00248   const StringRef Pattern = Name;
00249 
00250   if (Pattern.startswith("::"))
00251     return FullName == Pattern;
00252 
00253   return FullName.endswith(Pattern) &&
00254          FullName.drop_back(Pattern.size()).endswith("::");
00255 }
00256 
00257 bool HasNameMatcher::matchesNode(const NamedDecl &Node) const {
00258   // FIXME: There is still room for improvement, but it would require copying a
00259   // lot of the logic from NamedDecl::printQualifiedName(). The benchmarks do
00260   // not show like that extra complexity is needed right now.
00261   if (UseUnqualifiedMatch) {
00262     assert(matchesNodeUnqualified(Node) == matchesNodeFull(Node));
00263     return matchesNodeUnqualified(Node);
00264   }
00265   return matchesNodeFull(Node);
00266 }
00267 
00268 } // end namespace internal
00269 } // end namespace ast_matchers
00270 } // end namespace clang