diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2993,6 +2993,37 @@ new internal::HasNameMatcher({std::string(Name)})); } +template +inline internal::Matcher withTag(std::string BeforeTag, std::string AfterTag, + const internal::Matcher &InnerMatcher) { + return internal::Matcher( + new internal::WithTagMatcher(BeforeTag, AfterTag, InnerMatcher)); +} + +template class MatcherT, + typename ReturnTypesF, typename... ParamTypes> +inline MatcherT +withTag(std::string BeforeTag, std::string AfterTag, + const internal::PolymorphicMatcher &InnerMatcher) { + return internal::Matcher(new internal::WithTagMatcher( + BeforeTag, AfterTag, internal::Matcher(InnerMatcher))); +} + +template +inline internal::Matcher withTag(const internal::Matcher &InnerMatcher) { + return internal::Matcher(new internal::WithTagMatcher(InnerMatcher)); +} + +template class MatcherT, + typename ReturnTypesF, typename... ParamTypes> +inline MatcherT +withTag(const internal::PolymorphicMatcher &InnerMatcher) { + return internal::Matcher( + new internal::WithTagMatcher(internal::Matcher(InnerMatcher))); +} + /// Matches NamedDecl nodes that have any of the specified names. /// /// This matcher is only provided as a performance optimization of hasName. diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -43,6 +43,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -1042,6 +1043,44 @@ std::vector Names; }; +template class WithTagMatcher : public MatcherInterface { +public: + explicit WithTagMatcher(std::string _BeforeTag, std::string _AfterTag, + internal::Matcher _InnerMatcher) + : BeforeTag(std::move(_BeforeTag)), AfterTag(std::move(_AfterTag)), + InnerMatcher(_InnerMatcher) {} + explicit WithTagMatcher(internal::Matcher _InnerMatcher) + : BeforeTag("⭐ Attempting new match"), + AfterTag("✔️ Concluding attempt"), InnerMatcher(_InnerMatcher) {} + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { + DynTypedNode DTN = DynTypedNode::create(Node); + + llvm::errs() << BeforeTag << "\n"; + + llvm::errs() << "Matcher Name: " << InnerMatcher.getMatcherName() << "\n"; + + llvm::errs() << "Node Kind: " << DTN.getNodeKind().asStringRef() << "\n" + << "Node Value:\n```\n"; + DTN.print(llvm::errs(), PrintingPolicy(LangOptions())); + llvm::errs() << "\n```\n" + << "Node AST:\n"; + DTN.dump(llvm::errs(), Finder->getASTContext()); + + bool result = InnerMatcher.matches(Node, Finder, Builder); + llvm::errs() << "Result: " << (result ? "Successful\n" : "Unsuccessful\n"); + + llvm::errs() << AfterTag << "\n\n"; + + return result; + } + +private: + std::string BeforeTag; + std::string AfterTag; + internal::Matcher InnerMatcher; +}; + /// Matches named declarations with a specific name. /// /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details.