diff options
Diffstat (limited to 'clang/lib/ASTMatchers/ASTMatchersInternal.cpp')
-rw-r--r-- | clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 282 |
1 files changed, 200 insertions, 82 deletions
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 199a6d839e2eb..4b9baf7a0e751 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -15,9 +15,11 @@ #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ParentMapContext.h" #include "clang/AST/PrettyPrinter.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Basic/LLVM.h" +#include "clang/Lex/Lexer.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/None.h" @@ -27,6 +29,8 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -40,39 +44,56 @@ 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; + return llvm::is_contained(Matches, Node.getSelector().getAsString()); } namespace internal { -bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, +bool NotUnaryOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); -bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, +bool AllOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); -bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, +bool EachOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); -bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, +bool AnyOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); -bool OptionallyVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, +bool OptionallyVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); +bool matchesAnyBase(const CXXRecordDecl &Node, + const Matcher<CXXBaseSpecifier> &BaseSpecMatcher, + ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) { + if (!Node.hasDefinition()) + return false; + + CXXBasePaths Paths; + Paths.setOrigin(&Node); + + const auto basePredicate = + [Finder, Builder, &BaseSpecMatcher](const CXXBaseSpecifier *BaseSpec, + CXXBasePath &IgnoredParam) { + BoundNodesTreeBuilder Result(*Builder); + if (BaseSpecMatcher.matches(*BaseSpec, Finder, Builder)) { + *Builder = std::move(Result); + return true; + } + return false; + }; + + return Node.lookupInBases(basePredicate, Paths, + /*LookupInDependent =*/true); +} + void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) { if (Bindings.empty()) Bindings.push_back(BoundNodesMap()); @@ -84,7 +105,7 @@ void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) { namespace { using VariadicOperatorFunction = bool (*)( - const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, + const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); template <VariadicOperatorFunction Func> @@ -93,8 +114,7 @@ public: VariadicMatcher(std::vector<DynTypedMatcher> InnerMatchers) : InnerMatchers(std::move(InnerMatchers)) {} - bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, + bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { return Func(DynNode, Finder, Builder, InnerMatchers); } @@ -109,16 +129,14 @@ public: IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher) : ID(ID), InnerMatcher(std::move(InnerMatcher)) {} - bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, + bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { bool Result = InnerMatcher->dynMatches(DynNode, Finder, Builder); if (Result) Builder->setBinding(ID, DynNode); return Result; } - llvm::Optional<ast_type_traits::TraversalKind> - TraversalKind() const override { + llvm::Optional<clang::TraversalKind> TraversalKind() const override { return InnerMatcher->TraversalKind(); } @@ -138,20 +156,45 @@ public: Retain(); // Reference count will never become zero. } - bool dynMatches(const ast_type_traits::DynTypedNode &, ASTMatchFinder *, + bool dynMatches(const DynTypedNode &, ASTMatchFinder *, BoundNodesTreeBuilder *) const override { return true; } }; +/// A matcher that specifies a particular \c TraversalKind. +/// +/// The kind provided to the constructor overrides any kind that may be +/// specified by the `InnerMatcher`. +class DynTraversalMatcherImpl : public DynMatcherInterface { +public: + explicit DynTraversalMatcherImpl( + clang::TraversalKind TK, + IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher) + : TK(TK), InnerMatcher(std::move(InnerMatcher)) {} + + bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { + return this->InnerMatcher->dynMatches(DynNode, Finder, Builder); + } + + llvm::Optional<clang::TraversalKind> TraversalKind() const override { + return TK; + } + +private: + clang::TraversalKind TK; + IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher; +}; + } // namespace static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance; -DynTypedMatcher DynTypedMatcher::constructVariadic( - DynTypedMatcher::VariadicOperator Op, - ast_type_traits::ASTNodeKind SupportedKind, - std::vector<DynTypedMatcher> InnerMatchers) { +DynTypedMatcher +DynTypedMatcher::constructVariadic(DynTypedMatcher::VariadicOperator Op, + ASTNodeKind SupportedKind, + std::vector<DynTypedMatcher> InnerMatchers) { assert(!InnerMatchers.empty() && "Array must not be empty."); assert(llvm::all_of(InnerMatchers, [SupportedKind](const DynTypedMatcher &M) { @@ -172,8 +215,8 @@ DynTypedMatcher DynTypedMatcher::constructVariadic( // 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); + RestrictKind = + ASTNodeKind::getMostDerivedType(RestrictKind, IM.RestrictKind); } return DynTypedMatcher( SupportedKind, RestrictKind, @@ -204,40 +247,45 @@ DynTypedMatcher DynTypedMatcher::constructVariadic( llvm_unreachable("Invalid Op value."); } -DynTypedMatcher DynTypedMatcher::constructRestrictedWrapper( - const DynTypedMatcher &InnerMatcher, - ast_type_traits::ASTNodeKind RestrictKind) { +DynTypedMatcher +DynTypedMatcher::constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher, + ASTNodeKind RestrictKind) { DynTypedMatcher Copy = InnerMatcher; Copy.RestrictKind = RestrictKind; return Copy; } -DynTypedMatcher DynTypedMatcher::trueMatcher( - ast_type_traits::ASTNodeKind NodeKind) { +DynTypedMatcher +DynTypedMatcher::withTraversalKind(ast_type_traits::TraversalKind TK) { + auto Copy = *this; + Copy.Implementation = + new DynTraversalMatcherImpl(TK, std::move(Copy.Implementation)); + return Copy; +} + +DynTypedMatcher DynTypedMatcher::trueMatcher(ASTNodeKind NodeKind) { return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance); } -bool DynTypedMatcher::canMatchNodesOfKind( - ast_type_traits::ASTNodeKind Kind) const { +bool DynTypedMatcher::canMatchNodesOfKind(ASTNodeKind Kind) const { return RestrictKind.isBaseOf(Kind); } -DynTypedMatcher DynTypedMatcher::dynCastTo( - const ast_type_traits::ASTNodeKind Kind) const { +DynTypedMatcher DynTypedMatcher::dynCastTo(const ASTNodeKind Kind) const { auto Copy = *this; Copy.SupportedKind = Kind; - Copy.RestrictKind = - ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind); + Copy.RestrictKind = ASTNodeKind::getMostDerivedType(Kind, RestrictKind); return Copy; } -bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode, +bool DynTypedMatcher::matches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { TraversalKindScope RAII(Finder->getASTContext(), Implementation->TraversalKind()); - auto N = Finder->getASTContext().traverseIgnored(DynNode); + auto N = + Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode); if (RestrictKind.isBaseOf(N.getNodeKind()) && Implementation->dynMatches(N, Finder, Builder)) { @@ -250,13 +298,14 @@ bool DynTypedMatcher::matches(const ast_type_traits::DynTypedNode &DynNode, return false; } -bool DynTypedMatcher::matchesNoKindCheck( - const ast_type_traits::DynTypedNode &DynNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { +bool DynTypedMatcher::matchesNoKindCheck(const DynTypedNode &DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { TraversalKindScope raii(Finder->getASTContext(), Implementation->TraversalKind()); - auto N = Finder->getASTContext().traverseIgnored(DynNode); + auto N = + Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode); assert(RestrictKind.isBaseOf(N.getNodeKind())); if (Implementation->dynMatches(N, Finder, Builder)) { @@ -277,10 +326,10 @@ llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const { return std::move(Result); } -bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const { +bool DynTypedMatcher::canConvertTo(ASTNodeKind To) const { const auto From = getSupportedKind(); - auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>(); - auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>(); + auto QualKind = ASTNodeKind::getFromNodeKind<QualType>(); + auto TypeKind = ASTNodeKind::getFromNodeKind<Type>(); /// Mimic the implicit conversions of Matcher<>. /// - From Matcher<Type> to Matcher<QualType> if (From.isSame(TypeKind) && To.isSame(QualKind)) return true; @@ -292,8 +341,8 @@ 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, +bool NotUnaryOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers) { if (InnerMatchers.size() != 1) return false; @@ -312,22 +361,18 @@ bool NotUnaryOperator(const ast_type_traits::DynTypedNode &DynNode, return !InnerMatchers[0].matches(DynNode, Finder, &Discard); } -bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, +bool AllOfVariadicOperator(const 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; + return llvm::all_of(InnerMatchers, [&](const DynTypedMatcher &InnerMatcher) { + return InnerMatcher.matchesNoKindCheck(DynNode, Finder, Builder); + }); } -bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, +bool EachOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers) { BoundNodesTreeBuilder Result; @@ -343,8 +388,7 @@ bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, return Matched; } -bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, - ASTMatchFinder *Finder, +bool AnyOfVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers) { for (const DynTypedMatcher &InnerMatcher : InnerMatchers) { @@ -357,31 +401,31 @@ bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, return false; } -bool OptionallyVariadicOperator(const ast_type_traits::DynTypedNode &DynNode, +bool OptionallyVariadicOperator(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers) { - BoundNodesTreeBuilder Result; - for (const DynTypedMatcher &InnerMatcher : InnerMatchers) { - BoundNodesTreeBuilder BuilderInner(*Builder); - if (InnerMatcher.matches(DynNode, Finder, &BuilderInner)) - Result.addMatch(BuilderInner); - } - *Builder = std::move(Result); + if (InnerMatchers.size() != 1) + return false; + + BoundNodesTreeBuilder Result(*Builder); + if (InnerMatchers[0].matches(DynNode, Finder, &Result)) + *Builder = std::move(Result); return true; } inline static std::vector<std::string> vectorFromRefs(ArrayRef<const StringRef *> NameRefs) { std::vector<std::string> Names; + Names.reserve(NameRefs.size()); 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)); + return internal::Matcher<NamedDecl>( + new internal::HasNameMatcher(vectorFromRefs(NameRefs))); } Matcher<ObjCMessageExpr> hasAnySelectorFunc( @@ -389,10 +433,18 @@ Matcher<ObjCMessageExpr> hasAnySelectorFunc( return hasAnySelectorMatcher(vectorFromRefs(NameRefs)); } +HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs) { + return HasOpNameMatcher(vectorFromRefs(NameRefs)); +} + +HasOverloadOpNameMatcher +hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs) { + return HasOverloadOpNameMatcher(vectorFromRefs(NameRefs)); +} + HasNameMatcher::HasNameMatcher(std::vector<std::string> N) - : UseUnqualifiedMatch(std::all_of( - N.begin(), N.end(), - [](StringRef Name) { return Name.find("::") == Name.npos; })), + : UseUnqualifiedMatch(llvm::all_of( + N, [](StringRef Name) { return Name.find("::") == Name.npos; })), Names(std::move(N)) { #ifndef NDEBUG for (StringRef Name : Names) @@ -450,6 +502,7 @@ namespace { class PatternSet { public: PatternSet(ArrayRef<std::string> Names) { + Patterns.reserve(Names.size()); for (StringRef Name : Names) Patterns.push_back({Name, Name.startswith("::")}); } @@ -474,10 +527,10 @@ public: /// 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; + return llvm::any_of(Patterns, [&](const Pattern &Pattern) { + return Pattern.P.empty() && + (AllowFullyQualified || !Pattern.IsFullyQualified); + }); } private: @@ -523,7 +576,13 @@ bool HasNameMatcher::matchesNodeFullFast(const NamedDecl &Node) const { if (Ctx->isFunctionOrMethod()) return Patterns.foundMatch(/*AllowFullyQualified=*/false); - for (; Ctx && isa<NamedDecl>(Ctx); Ctx = Ctx->getParent()) { + for (; Ctx; Ctx = Ctx->getParent()) { + // Linkage Spec can just be ignored + // FIXME: Any other DeclContext kinds that can be safely disregarded + if (isa<LinkageSpecDecl>(Ctx)) + continue; + if (!isa<NamedDecl>(Ctx)) + break; if (Patterns.foundMatch(/*AllowFullyQualified=*/false)) return true; @@ -592,6 +651,52 @@ bool HasNameMatcher::matchesNode(const NamedDecl &Node) const { return matchesNodeFullFast(Node); } +// Checks whether \p Loc points to a token with source text of \p TokenText. +static bool isTokenAtLoc(const SourceManager &SM, const LangOptions &LangOpts, + StringRef Text, SourceLocation Loc) { + llvm::SmallString<16> Buffer; + bool Invalid = false; + // Since `Loc` may point into an expansion buffer, which has no corresponding + // source, we need to look at the spelling location to read the actual source. + StringRef TokenText = Lexer::getSpelling(SM.getSpellingLoc(Loc), Buffer, SM, + LangOpts, &Invalid); + return !Invalid && Text == TokenText; +} + +llvm::Optional<SourceLocation> +getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc, + const ASTContext &Context) { + auto &SM = Context.getSourceManager(); + const LangOptions &LangOpts = Context.getLangOpts(); + while (Loc.isMacroID()) { + SrcMgr::ExpansionInfo Expansion = + SM.getSLocEntry(SM.getFileID(Loc)).getExpansion(); + if (Expansion.isMacroArgExpansion()) + // Check macro argument for an expansion of the given macro. For example, + // `F(G(3))`, where `MacroName` is `G`. + if (llvm::Optional<SourceLocation> ArgLoc = getExpansionLocOfMacro( + MacroName, Expansion.getSpellingLoc(), Context)) + return ArgLoc; + Loc = Expansion.getExpansionLocStart(); + if (isTokenAtLoc(SM, LangOpts, MacroName, Loc)) + return Loc; + } + return llvm::None; +} + +std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex, + llvm::Regex::RegexFlags Flags, + StringRef MatcherID) { + assert(!Regex.empty() && "Empty regex string"); + auto SharedRegex = std::make_shared<llvm::Regex>(Regex, Flags); + std::string Error; + if (!SharedRegex->isValid(Error)) { + llvm::WithColor::error() + << "building matcher '" << MatcherID << "': " << Error << "\n"; + llvm::WithColor::note() << " input was '" << Regex << "'\n"; + } + return SharedRegex; +} } // end namespace internal const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAutoreleasePoolStmt> @@ -647,6 +752,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> enumConstantDecl; +const internal::VariadicDynCastAllOfMatcher<Decl, TagDecl> tagDecl; const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> cxxConversionDecl; @@ -727,6 +833,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, MaterializeTemporaryExpr> materializeTemporaryExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr> + cxxNoexceptExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr> arraySubscriptExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr> @@ -768,6 +876,8 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral> integerLiteral; const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> floatLiteral; const internal::VariadicDynCastAllOfMatcher<Stmt, ImaginaryLiteral> imaginaryLiteral; +const internal::VariadicDynCastAllOfMatcher<Stmt, FixedPointLiteral> + fixedPointLiteral; const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral> userDefinedLiteral; const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr> @@ -821,12 +931,18 @@ const internal::VariadicOperatorMatcherFunc< const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits<unsigned>::max()> allOf = {internal::DynTypedMatcher::VO_AllOf}; -const internal::VariadicOperatorMatcherFunc< - 1, std::numeric_limits<unsigned>::max()> - optionally = {internal::DynTypedMatcher::VO_Optionally}; +const internal::VariadicOperatorMatcherFunc<1, 1> optionally = { + internal::DynTypedMatcher::VO_Optionally}; const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef, internal::hasAnyNameFunc> hasAnyName = {}; + +const internal::VariadicFunction<internal::HasOpNameMatcher, StringRef, + internal::hasAnyOperatorNameFunc> + hasAnyOperatorName = {}; +const internal::VariadicFunction<internal::HasOverloadOpNameMatcher, StringRef, + internal::hasAnyOverloadedOperatorNameFunc> + hasAnyOverloadedOperatorName = {}; const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, StringRef, internal::hasAnySelectorFunc> hasAnySelector = {}; @@ -858,6 +974,8 @@ const AstTypeMatcher<BuiltinType> builtinType; const AstTypeMatcher<ArrayType> arrayType; const AstTypeMatcher<ComplexType> complexType; const AstTypeMatcher<ConstantArrayType> constantArrayType; +const AstTypeMatcher<DeducedTemplateSpecializationType> + deducedTemplateSpecializationType; const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType; const AstTypeMatcher<IncompleteArrayType> incompleteArrayType; const AstTypeMatcher<VariableArrayType> variableArrayType; |