|  | //===- ASTMatchersInternal.cpp - Structural query framework ---------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | //  Implements the base layer of the matcher framework. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "clang/ASTMatchers/ASTMatchersInternal.h" | 
|  | #include "clang/AST/ASTContext.h" | 
|  | #include "clang/AST/ASTTypeTraits.h" | 
|  | #include "clang/AST/Decl.h" | 
|  | #include "clang/AST/DeclTemplate.h" | 
|  | #include "clang/AST/PrettyPrinter.h" | 
|  | #include "clang/ASTMatchers/ASTMatchers.h" | 
|  | #include "clang/Basic/LLVM.h" | 
|  | #include "llvm/ADT/ArrayRef.h" | 
|  | #include "llvm/ADT/IntrusiveRefCntPtr.h" | 
|  | #include "llvm/ADT/None.h" | 
|  | #include "llvm/ADT/SmallString.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/Support/Casting.h" | 
|  | #include "llvm/Support/ErrorHandling.h" | 
|  | #include "llvm/Support/ManagedStatic.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  | #include <algorithm> | 
|  | #include <cassert> | 
|  | #include <cstddef> | 
|  | #include <string> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | namespace clang { | 
|  | namespace ast_matchers { | 
|  |  | 
|  | AST_MATCHER_P(ObjCMessageExpr, hasAnySelectorMatcher, std::vector<std::string>, | 
|  | Matches) { | 
|  | std::string SelString = Node.getSelector().getAsString(); | 
|  | for (const std::string &S : Matches) | 
|  | if (S == SelString) | 
|  | return true; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | namespace internal { | 
|  |  | 
|  | bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers); | 
|  |  | 
|  | bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers); | 
|  |  | 
|  | bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers); | 
|  |  | 
|  | bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers); | 
|  |  | 
|  | void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) { | 
|  | if (Bindings.empty()) | 
|  | Bindings.push_back(BoundNodesMap()); | 
|  | for (BoundNodesMap &Binding : Bindings) { | 
|  | ResultVisitor->visitMatch(BoundNodes(Binding)); | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | using VariadicOperatorFunction = bool (*)( | 
|  | const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); | 
|  |  | 
|  | template <VariadicOperatorFunction Func> | 
|  | class VariadicMatcher : public DynMatcherInterface { | 
|  | public: | 
|  | VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers) | 
|  | : InnerMatchers(std::move(InnerMatchers)) {} | 
|  |  | 
|  | bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder) const override { | 
|  | return Func(DynNode, Finder, Builder, InnerMatchers); | 
|  | } | 
|  |  | 
|  | private: | 
|  | std::vector<DynTypedMatcher> InnerMatchers; | 
|  | }; | 
|  |  | 
|  | class IdDynMatcher : public DynMatcherInterface { | 
|  | public: | 
|  | IdDynMatcher(StringRef ID, | 
|  | IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher) | 
|  | : ID(ID), InnerMatcher(std::move(InnerMatcher)) {} | 
|  |  | 
|  | bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder) const override { | 
|  | bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder); | 
|  | if (Result) Builder->setBinding(ID, DynNode); | 
|  | return Result; | 
|  | } | 
|  |  | 
|  | private: | 
|  | const std::string ID; | 
|  | const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher; | 
|  | }; | 
|  |  | 
|  | /// A matcher that always returns true. | 
|  | /// | 
|  | /// We only ever need one instance of this matcher, so we create a global one | 
|  | /// and reuse it to reduce the overhead of the matcher and increase the chance | 
|  | /// of cache hits. | 
|  | class TrueMatcherImpl : public DynMatcherInterface { | 
|  | public: | 
|  | TrueMatcherImpl() { | 
|  | Retain(); // Reference count will never become zero. | 
|  | } | 
|  |  | 
|  | bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *, | 
|  | BoundNodesTreeBuilder *) const override { | 
|  | return true; | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // namespace | 
|  |  | 
|  | static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance; | 
|  |  | 
|  | DynTypedMatcher DynTypedMatcher::constructVariadic( | 
|  | DynTypedMatcher::VariadicOperator Op, | 
|  | ast_type_traits::ASTNodeKind SupportedKind, | 
|  | std::vector<DynTypedMatcher> InnerMatchers) { | 
|  | assert(!InnerMatchers.empty() && "Array must not be empty."); | 
|  | assert(llvm::all_of(InnerMatchers, | 
|  | [SupportedKind](const DynTypedMatcher &M) { | 
|  | return M.canConvertTo(SupportedKind); | 
|  | }) && | 
|  | "InnerMatchers must be convertible to SupportedKind!"); | 
|  |  | 
|  | // We must relax the restrict kind here. | 
|  | // The different operators might deal differently with a mismatch. | 
|  | // Make it the same as SupportedKind, since that is the broadest type we are | 
|  | // allowed to accept. | 
|  | auto RestrictKind = SupportedKind; | 
|  |  | 
|  | switch (Op) { | 
|  | case VO_AllOf: | 
|  | // In the case of allOf() we must pass all the checks, so making | 
|  | // RestrictKind the most restrictive can save us time. This way we reject | 
|  | // invalid types earlier and we can elide the kind checks inside the | 
|  | // matcher. | 
|  | for (auto &IM : InnerMatchers) { | 
|  | RestrictKind = ast_type_traits::ASTNodeKind::getMostDerivedType( | 
|  | RestrictKind, IM.RestrictKind); | 
|  | } | 
|  | return DynTypedMatcher( | 
|  | SupportedKind, RestrictKind, | 
|  | new VariadicMatcher<AllOfVariadicOperator>(std::move(InnerMatchers))); | 
|  |  | 
|  | case VO_AnyOf: | 
|  | return DynTypedMatcher( | 
|  | SupportedKind, RestrictKind, | 
|  | new VariadicMatcher<AnyOfVariadicOperator>(std::move(InnerMatchers))); | 
|  |  | 
|  | case VO_EachOf: | 
|  | return DynTypedMatcher( | 
|  | SupportedKind, RestrictKind, | 
|  | new VariadicMatcher<EachOfVariadicOperator>(std::move(InnerMatchers))); | 
|  |  | 
|  | case VO_UnaryNot: | 
|  | // FIXME: Implement the Not operator to take a single matcher instead of a | 
|  | // vector. | 
|  | return DynTypedMatcher( | 
|  | SupportedKind, RestrictKind, | 
|  | new VariadicMatcher<NotUnaryOperator>(std::move(InnerMatchers))); | 
|  | } | 
|  | llvm_unreachable("Invalid Op value."); | 
|  | } | 
|  |  | 
|  | DynTypedMatcher DynTypedMatcher::trueMatcher( | 
|  | ast_type_traits::ASTNodeKind NodeKind) { | 
|  | return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance); | 
|  | } | 
|  |  | 
|  | bool DynTypedMatcher::canMatchNodesOfKind( | 
|  | ast_type_traits::ASTNodeKind Kind) const { | 
|  | return RestrictKind.isBaseOf(Kind); | 
|  | } | 
|  |  | 
|  | DynTypedMatcher DynTypedMatcher::dynCastTo( | 
|  | const ast_type_traits::ASTNodeKind Kind) const { | 
|  | auto Copy = *this; | 
|  | Copy.SupportedKind = Kind; | 
|  | Copy.RestrictKind = | 
|  | ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind); | 
|  | return Copy; | 
|  | } | 
|  |  | 
|  | bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder) const { | 
|  | if (RestrictKind.isBaseOf(DynNode.getNodeKind()) && | 
|  | Implementation->dynMatches(DynNode, Finder, Builder)) { | 
|  | return true; | 
|  | } | 
|  | // Delete all bindings when a matcher does not match. | 
|  | // This prevents unexpected exposure of bound nodes in unmatches | 
|  | // branches of the match tree. | 
|  | Builder->removeBindings([](const BoundNodesMap &) { return true; }); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool DynTypedMatcher::matchesNoKindCheck( | 
|  | const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder) const { | 
|  | assert(RestrictKind.isBaseOf(DynNode.getNodeKind())); | 
|  | if (Implementation->dynMatches(DynNode, Finder, Builder)) { | 
|  | return true; | 
|  | } | 
|  | // Delete all bindings when a matcher does not match. | 
|  | // This prevents unexpected exposure of bound nodes in unmatches | 
|  | // branches of the match tree. | 
|  | Builder->removeBindings([](const BoundNodesMap &) { return true; }); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const { | 
|  | if (!AllowBind) return llvm::None; | 
|  | auto Result = *this; | 
|  | Result.Implementation = | 
|  | new IdDynMatcher(ID, std::move(Result.Implementation)); | 
|  | return std::move(Result); | 
|  | } | 
|  |  | 
|  | bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const { | 
|  | const auto From = getSupportedKind(); | 
|  | auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>(); | 
|  | auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>(); | 
|  | /// Mimic the implicit conversions of Matcher<>. | 
|  | /// - From Matcher<Type> to Matcher<QualType> | 
|  | if (From.isSame(TypeKind) && To.isSame(QualKind)) return true; | 
|  | /// - From Matcher<Base> to Matcher<Derived> | 
|  | return From.isBaseOf(To); | 
|  | } | 
|  |  | 
|  | void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) { | 
|  | Bindings.append(Other.Bindings.begin(), Other.Bindings.end()); | 
|  | } | 
|  |  | 
|  | bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers) { | 
|  | if (InnerMatchers.size() != 1) | 
|  | return false; | 
|  |  | 
|  | // The 'unless' matcher will always discard the result: | 
|  | // If the inner matcher doesn't match, unless returns true, | 
|  | // but the inner matcher cannot have bound anything. | 
|  | // If the inner matcher matches, the result is false, and | 
|  | // any possible binding will be discarded. | 
|  | // We still need to hand in all the bound nodes up to this | 
|  | // point so the inner matcher can depend on bound nodes, | 
|  | // and we need to actively discard the bound nodes, otherwise | 
|  | // the inner matcher will reset the bound nodes if it doesn't | 
|  | // match, but this would be inversed by 'unless'. | 
|  | BoundNodesTreeBuilder Discard(*Builder); | 
|  | return !InnerMatchers[0].matches(DynNode, Finder, &Discard); | 
|  | } | 
|  |  | 
|  | bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers) { | 
|  | // allOf leads to one matcher for each alternative in the first | 
|  | // matcher combined with each alternative in the second matcher. | 
|  | // Thus, we can reuse the same Builder. | 
|  | for (const DynTypedMatcher &InnerMatcher : InnerMatchers) { | 
|  | if (!InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder)) | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers) { | 
|  | BoundNodesTreeBuilder Result; | 
|  | bool Matched = false; | 
|  | for (const DynTypedMatcher &InnerMatcher : InnerMatchers) { | 
|  | BoundNodesTreeBuilder BuilderInner(*Builder); | 
|  | if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) { | 
|  | Matched = true; | 
|  | Result.addMatch(BuilderInner); | 
|  | } | 
|  | } | 
|  | *Builder = std::move(Result); | 
|  | return Matched; | 
|  | } | 
|  |  | 
|  | bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, | 
|  | ASTMatchFinder *Finder, | 
|  | BoundNodesTreeBuilder *Builder, | 
|  | ArrayRef<DynTypedMatcher> InnerMatchers) { | 
|  | for (const DynTypedMatcher &InnerMatcher : InnerMatchers) { | 
|  | BoundNodesTreeBuilder Result = *Builder; | 
|  | if (InnerMatcher.matches(DynNode, Finder, &Result)) { | 
|  | *Builder = std::move(Result); | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | inline static | 
|  | std::vector<std::string> vectorFromRefs(ArrayRef<const StringRef *> NameRefs) { | 
|  | std::vector<std::string> Names; | 
|  | for (auto *Name : NameRefs) | 
|  | Names.emplace_back(*Name); | 
|  | return Names; | 
|  | } | 
|  |  | 
|  | Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) { | 
|  | std::vector<std::string> Names = vectorFromRefs(NameRefs); | 
|  | return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names)); | 
|  | } | 
|  |  | 
|  | Matcher<ObjCMessageExpr> hasAnySelectorFunc( | 
|  | ArrayRef<const StringRef *> NameRefs) { | 
|  | return hasAnySelectorMatcher(vectorFromRefs(NameRefs)); | 
|  | } | 
|  |  | 
|  | HasNameMatcher::HasNameMatcher(std::vector<std::string> N) | 
|  | : UseUnqualifiedMatch(std::all_of( | 
|  | N.begin(), N.end(), | 
|  | [](StringRef Name) { return Name.find("::") == Name.npos; })), | 
|  | Names(std::move(N)) { | 
|  | #ifndef NDEBUG | 
|  | for (StringRef Name : Names) | 
|  | assert(!Name.empty()); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | static bool consumeNameSuffix(StringRef &FullName, StringRef Suffix) { | 
|  | StringRef Name = FullName; | 
|  | if (!Name.endswith(Suffix)) | 
|  | return false; | 
|  | Name = Name.drop_back(Suffix.size()); | 
|  | if (!Name.empty()) { | 
|  | if (!Name.endswith("::")) | 
|  | return false; | 
|  | Name = Name.drop_back(2); | 
|  | } | 
|  | FullName = Name; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static StringRef getNodeName(const NamedDecl &Node, | 
|  | llvm::SmallString<128> &Scratch) { | 
|  | // Simple name. | 
|  | if (Node.getIdentifier()) | 
|  | return Node.getName(); | 
|  |  | 
|  | if (Node.getDeclName()) { | 
|  | // Name needs to be constructed. | 
|  | Scratch.clear(); | 
|  | llvm::raw_svector_ostream OS(Scratch); | 
|  | Node.printName(OS); | 
|  | return OS.str(); | 
|  | } | 
|  |  | 
|  | return "(anonymous)"; | 
|  | } | 
|  |  | 
|  | static StringRef getNodeName(const RecordDecl &Node, | 
|  | llvm::SmallString<128> &Scratch) { | 
|  | if (Node.getIdentifier()) { | 
|  | return Node.getName(); | 
|  | } | 
|  | Scratch.clear(); | 
|  | return ("(anonymous " + Node.getKindName() + ")").toStringRef(Scratch); | 
|  | } | 
|  |  | 
|  | static StringRef getNodeName(const NamespaceDecl &Node, | 
|  | llvm::SmallString<128> &Scratch) { | 
|  | return Node.isAnonymousNamespace() ? "(anonymous namespace)" : Node.getName(); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class PatternSet { | 
|  | public: | 
|  | PatternSet(ArrayRef<std::string> Names) { | 
|  | for (StringRef Name : Names) | 
|  | Patterns.push_back({Name, Name.startswith("::")}); | 
|  | } | 
|  |  | 
|  | /// Consumes the name suffix from each pattern in the set and removes the ones | 
|  | /// that didn't match. | 
|  | /// Return true if there are still any patterns left. | 
|  | bool consumeNameSuffix(StringRef NodeName, bool CanSkip) { | 
|  | for (size_t I = 0; I < Patterns.size();) { | 
|  | if (::clang::ast_matchers::internal::consumeNameSuffix(Patterns[I].P, | 
|  | NodeName) || | 
|  | CanSkip) { | 
|  | ++I; | 
|  | } else { | 
|  | Patterns.erase(Patterns.begin() + I); | 
|  | } | 
|  | } | 
|  | return !Patterns.empty(); | 
|  | } | 
|  |  | 
|  | /// Check if any of the patterns are a match. | 
|  | /// A match will be a pattern that was fully consumed, that also matches the | 
|  | /// 'fully qualified' requirement. | 
|  | bool foundMatch(bool AllowFullyQualified) const { | 
|  | for (auto& P: Patterns) | 
|  | if (P.P.empty() && (AllowFullyQualified || !P.IsFullyQualified)) | 
|  | return true; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | private: | 
|  | struct Pattern { | 
|  | StringRef P; | 
|  | bool IsFullyQualified; | 
|  | }; | 
|  |  | 
|  | llvm::SmallVector<Pattern, 8> Patterns; | 
|  | }; | 
|  |  | 
|  | } // namespace | 
|  |  | 
|  | bool HasNameMatcher::matchesNodeUnqualified(const NamedDecl &Node) const { | 
|  | assert(UseUnqualifiedMatch); | 
|  | llvm::SmallString<128> Scratch; | 
|  | StringRef NodeName = getNodeName(Node, Scratch); | 
|  | return llvm::any_of(Names, [&](StringRef Name) { | 
|  | return consumeNameSuffix(Name, NodeName) && Name.empty(); | 
|  | }); | 
|  | } | 
|  |  | 
|  | bool HasNameMatcher::matchesNodeFullFast(const NamedDecl &Node) const { | 
|  | PatternSet Patterns(Names); | 
|  | llvm::SmallString<128> Scratch; | 
|  |  | 
|  | // This function is copied and adapted from NamedDecl::printQualifiedName() | 
|  | // By matching each part individually we optimize in a couple of ways: | 
|  | //  - We can exit early on the first failure. | 
|  | //  - We can skip inline/anonymous namespaces without another pass. | 
|  | //  - We print one name at a time, reducing the chance of overflowing the | 
|  | //    inlined space of the SmallString. | 
|  |  | 
|  | // First, match the name. | 
|  | if (!Patterns.consumeNameSuffix(getNodeName(Node, Scratch), | 
|  | /*CanSkip=*/false)) | 
|  | return false; | 
|  |  | 
|  | // Try to match each declaration context. | 
|  | // We are allowed to skip anonymous and inline namespaces if they don't match. | 
|  | const DeclContext *Ctx = Node.getDeclContext(); | 
|  |  | 
|  | if (Ctx->isFunctionOrMethod()) | 
|  | return Patterns.foundMatch(/*AllowFullyQualified=*/false); | 
|  |  | 
|  | for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) { | 
|  | if (Patterns.foundMatch(/*AllowFullyQualified=*/false)) | 
|  | return true; | 
|  |  | 
|  | if (const auto *ND = dyn_cast<NamespaceDecl>(Ctx)) { | 
|  | // If it matches (or we can skip it), continue. | 
|  | if (Patterns.consumeNameSuffix(getNodeName(*ND, Scratch), | 
|  | /*CanSkip=*/ND->isAnonymousNamespace() || | 
|  | ND->isInline())) | 
|  | continue; | 
|  | return false; | 
|  | } | 
|  | if (const auto *RD = dyn_cast<RecordDecl>(Ctx)) { | 
|  | if (!isa<ClassTemplateSpecializationDecl>(Ctx)) { | 
|  | if (Patterns.consumeNameSuffix(getNodeName(*RD, Scratch), | 
|  | /*CanSkip=*/false)) | 
|  | continue; | 
|  |  | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // We don't know how to deal with this DeclContext. | 
|  | // Fallback to the slow version of the code. | 
|  | return matchesNodeFullSlow(Node); | 
|  | } | 
|  |  | 
|  | return Patterns.foundMatch(/*AllowFullyQualified=*/true); | 
|  | } | 
|  |  | 
|  | bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const { | 
|  | const bool SkipUnwrittenCases[] = {false, true}; | 
|  | for (bool SkipUnwritten : SkipUnwrittenCases) { | 
|  | llvm::SmallString<128> NodeName = StringRef("::"); | 
|  | llvm::raw_svector_ostream OS(NodeName); | 
|  |  | 
|  | if (SkipUnwritten) { | 
|  | PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy(); | 
|  | Policy.SuppressUnwrittenScope = true; | 
|  | Node.printQualifiedName(OS, Policy); | 
|  | } else { | 
|  | Node.printQualifiedName(OS); | 
|  | } | 
|  |  | 
|  | const StringRef FullName = OS.str(); | 
|  |  | 
|  | for (const StringRef Pattern : Names) { | 
|  | if (Pattern.startswith("::")) { | 
|  | if (FullName == Pattern) | 
|  | return true; | 
|  | } else if (FullName.endswith(Pattern) && | 
|  | FullName.drop_back(Pattern.size()).endswith("::")) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool HasNameMatcher::matchesNode(const NamedDecl &Node) const { | 
|  | assert(matchesNodeFullFast(Node) == matchesNodeFullSlow(Node)); | 
|  | if (UseUnqualifiedMatch) { | 
|  | assert(matchesNodeUnqualified(Node) == matchesNodeFullFast(Node)); | 
|  | return matchesNodeUnqualified(Node); | 
|  | } | 
|  | return matchesNodeFullFast(Node); | 
|  | } | 
|  |  | 
|  | } // end namespace internal | 
|  |  | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAutoreleasePoolStmt> | 
|  | autoreleasePoolStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> | 
|  | translationUnitDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> | 
|  | typedefNameDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl> | 
|  | typeAliasTemplateDecl; | 
|  | const internal::VariadicAllOfMatcher<Decl> decl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> | 
|  | linkageSpecDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl> | 
|  | namespaceAliasDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> cxxRecordDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl> | 
|  | classTemplateDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, | 
|  | ClassTemplateSpecializationDecl> | 
|  | classTemplateSpecializationDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher< | 
|  | Decl, ClassTemplatePartialSpecializationDecl> | 
|  | classTemplatePartialSpecializationDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> | 
|  | declaratorDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl> | 
|  | accessSpecDecl; | 
|  | const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer; | 
|  | const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; | 
|  | const internal::VariadicAllOfMatcher<TemplateName> templateName; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl> | 
|  | nonTypeTemplateParmDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl> | 
|  | templateTypeParmDecl; | 
|  | const internal::VariadicAllOfMatcher<QualType> qualType; | 
|  | const internal::VariadicAllOfMatcher<Type> type; | 
|  | const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryExprOrTypeTraitExpr> | 
|  | unaryExprOrTypeTraitExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl> | 
|  | cxxConstructorDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> | 
|  | cxxDestructorDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> | 
|  | enumConstantDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> | 
|  | cxxConversionDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, IndirectFieldDecl> | 
|  | indirectFieldDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl> | 
|  | functionTemplateDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; | 
|  | const internal::VariadicAllOfMatcher<Stmt> stmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedMemberExpr> | 
|  | unresolvedMemberExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDependentScopeMemberExpr> | 
|  | cxxDependentScopeMemberExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> | 
|  | cxxMemberCallExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr> | 
|  | objcMessageExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl> | 
|  | objcInterfaceDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl> | 
|  | objcImplementationDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl> | 
|  | objcProtocolDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl> | 
|  | objcCategoryDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl> | 
|  | objcCategoryImplDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl> | 
|  | objcMethodDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, BlockDecl> | 
|  | blockDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> objcIvarDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl> | 
|  | objcPropertyDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt> | 
|  | objcThrowStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt> objcTryStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt> | 
|  | objcCatchStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt> | 
|  | objcFinallyStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups> | 
|  | exprWithCleanups; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStdInitializerListExpr> | 
|  | cxxStdInitializerListExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr> | 
|  | implicitValueInitExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr> | 
|  | substNonTypeTemplateParmExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl> | 
|  | usingDirectiveDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr> | 
|  | unresolvedLookupExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingValueDecl> | 
|  | unresolvedUsingValueDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingTypenameDecl> | 
|  | unresolvedUsingTypenameDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ConstantExpr> constantExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr> | 
|  | cxxConstructExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXUnresolvedConstructExpr> | 
|  | cxxUnresolvedConstructExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr> | 
|  | cxxBindTemporaryExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, MaterializeTemporaryExpr> | 
|  | materializeTemporaryExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr> | 
|  | arraySubscriptExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr> | 
|  | cxxDefaultArgExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr> | 
|  | cxxOperatorCallExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr> objcIvarRefExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, BlockExpr> blockExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> | 
|  | cxxForRangeStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr> | 
|  | cxxBoolLiteral; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral> stringLiteral; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral> | 
|  | characterLiteral; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral> | 
|  | integerLiteral; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> floatLiteral; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral> imaginaryLiteral; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral> | 
|  | userDefinedLiteral; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr> | 
|  | compoundLiteralExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> | 
|  | cxxNullPtrLiteralExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator> | 
|  | binaryOperator; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> unaryOperator; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator> | 
|  | conditionalOperator; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryConditionalOperator> | 
|  | binaryConditionalOperator; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr> | 
|  | opaqueValueExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl> | 
|  | staticAssertDecl; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr> | 
|  | cxxReinterpretCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr> | 
|  | cxxStaticCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr> | 
|  | cxxDynamicCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr> | 
|  | cxxConstCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr> | 
|  | cStyleCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr> | 
|  | explicitCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr> | 
|  | implicitCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr> | 
|  | cxxFunctionalCastExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr> | 
|  | cxxTemporaryObjectExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr> | 
|  | predefinedExpr; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr> | 
|  | designatedInitExpr; | 
|  | const internal::VariadicOperatorMatcherFunc< | 
|  | 2, std::numeric_limits<unsigned>::max()> | 
|  | eachOf = {internal::DynTypedMatcher::VO_EachOf}; | 
|  | const internal::VariadicOperatorMatcherFunc< | 
|  | 2, std::numeric_limits<unsigned>::max()> | 
|  | anyOf = {internal::DynTypedMatcher::VO_AnyOf}; | 
|  | const internal::VariadicOperatorMatcherFunc< | 
|  | 2, std::numeric_limits<unsigned>::max()> | 
|  | allOf = {internal::DynTypedMatcher::VO_AllOf}; | 
|  | const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef, | 
|  | internal::hasAnyNameFunc> | 
|  | hasAnyName = {}; | 
|  | const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, StringRef, | 
|  | internal::hasAnySelectorFunc> | 
|  | hasAnySelector = {}; | 
|  | const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has = {}; | 
|  | const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher> | 
|  | hasDescendant = {}; | 
|  | const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> forEach = | 
|  | {}; | 
|  | const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher> | 
|  | forEachDescendant = {}; | 
|  | const internal::ArgumentAdaptingMatcherFunc< | 
|  | internal::HasParentMatcher, | 
|  | internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>, | 
|  | internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> | 
|  | hasParent = {}; | 
|  | const internal::ArgumentAdaptingMatcherFunc< | 
|  | internal::HasAncestorMatcher, | 
|  | internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>, | 
|  | internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> | 
|  | hasAncestor = {}; | 
|  | const internal::VariadicOperatorMatcherFunc<1, 1> unless = { | 
|  | internal::DynTypedMatcher::VO_UnaryNot}; | 
|  | const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; | 
|  | const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc> | 
|  | nestedNameSpecifierLoc; | 
|  | const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr> | 
|  | cudaKernelCallExpr; | 
|  | const AstTypeMatcher<BuiltinType> builtinType; | 
|  | const AstTypeMatcher<ArrayType> arrayType; | 
|  | const AstTypeMatcher<ComplexType> complexType; | 
|  | const AstTypeMatcher<ConstantArrayType> constantArrayType; | 
|  | const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType; | 
|  | const AstTypeMatcher<IncompleteArrayType> incompleteArrayType; | 
|  | const AstTypeMatcher<VariableArrayType> variableArrayType; | 
|  | const AstTypeMatcher<AtomicType> atomicType; | 
|  | const AstTypeMatcher<AutoType> autoType; | 
|  | const AstTypeMatcher<DecltypeType> decltypeType; | 
|  | const AstTypeMatcher<FunctionType> functionType; | 
|  | const AstTypeMatcher<FunctionProtoType> functionProtoType; | 
|  | const AstTypeMatcher<ParenType> parenType; | 
|  | const AstTypeMatcher<BlockPointerType> blockPointerType; | 
|  | const AstTypeMatcher<MemberPointerType> memberPointerType; | 
|  | const AstTypeMatcher<PointerType> pointerType; | 
|  | const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType; | 
|  | const AstTypeMatcher<ReferenceType> referenceType; | 
|  | const AstTypeMatcher<LValueReferenceType> lValueReferenceType; | 
|  | const AstTypeMatcher<RValueReferenceType> rValueReferenceType; | 
|  | const AstTypeMatcher<TypedefType> typedefType; | 
|  | const AstTypeMatcher<EnumType> enumType; | 
|  | const AstTypeMatcher<TemplateSpecializationType> templateSpecializationType; | 
|  | const AstTypeMatcher<UnaryTransformType> unaryTransformType; | 
|  | const AstTypeMatcher<RecordType> recordType; | 
|  | const AstTypeMatcher<TagType> tagType; | 
|  | const AstTypeMatcher<ElaboratedType> elaboratedType; | 
|  | const AstTypeMatcher<SubstTemplateTypeParmType> substTemplateTypeParmType; | 
|  | const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType; | 
|  | const AstTypeMatcher<InjectedClassNameType> injectedClassNameType; | 
|  | const AstTypeMatcher<DecayedType> decayedType; | 
|  | AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasElementType, | 
|  | AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType, | 
|  | ComplexType)); | 
|  | AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasValueType, | 
|  | AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType)); | 
|  | AST_TYPELOC_TRAVERSE_MATCHER_DEF( | 
|  | pointee, | 
|  | AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType, | 
|  | PointerType, ReferenceType)); | 
|  |  | 
|  | } // end namespace ast_matchers | 
|  | } // end namespace clang |