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 @@ -83,6 +83,81 @@ namespace internal { +/// Helper function that obtains a name for a matcher based on its type, which +/// can be useful for cases like debugging matchers. +template std::string makeMatcherNameFromType() { + return "Matcher"; +} + +#define TYPELOC(CLASS, PARENT) \ + template <> inline std::string makeMatcherNameFromType() { \ + return "`" #CLASS "TypeLoc` Node"; \ + } +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#include "clang/AST/TypeLocNodes.def" + +template <> inline std::string makeMatcherNameFromType() { + return "`TypeLoc` Node"; +} + +#define DECL(CLASS, PARENT) \ + template <> inline std::string makeMatcherNameFromType() { \ + return "`" #CLASS "Decl` Node"; \ + } +#define ABSTRACT_DECL(CLASS) +#include "clang/AST/DeclNodes.inc" + +template <> inline std::string makeMatcherNameFromType() { + return "`Decl` Node"; +} + +#define STMT(CLASS, PARENT) \ + template <> inline std::string makeMatcherNameFromType() { \ + return "`" #CLASS "` Node"; \ + } +#define ABSTRACT_STMT(CLASS) +#include "clang/AST/StmtNodes.inc" + +template <> inline std::string makeMatcherNameFromType() { + return "`Stmt` Node"; +} + +#define TYPE(CLASS, PARENT) \ + template <> inline std::string makeMatcherNameFromType() { \ + return "`" #CLASS "Type` Node"; \ + } +#define ABSTRACT_TYPE(CLASS, PARENT) +#include "clang/AST/TypeNodes.inc" + +template <> inline std::string makeMatcherNameFromType() { + return "`Type` Node"; +} + +#define ATTR(A) \ + template <> inline std::string makeMatcherNameFromType() { \ + return "`" #A "Attr` Node"; \ + } +#include "clang/Basic/AttrList.inc" + +template <> inline std::string makeMatcherNameFromType() { + return "`Attr` Node"; +} + +#define MAKE_MATCHER_NAME_FROM_TYPE(CLASS) \ + template <> inline std::string makeMatcherNameFromType() { \ + return "`" #CLASS "` Node"; \ + } +MAKE_MATCHER_NAME_FROM_TYPE(TemplateArgument) +MAKE_MATCHER_NAME_FROM_TYPE(TemplateArgumentLoc) +MAKE_MATCHER_NAME_FROM_TYPE(TemplateName) +MAKE_MATCHER_NAME_FROM_TYPE(NestedNameSpecifier) +MAKE_MATCHER_NAME_FROM_TYPE(NestedNameSpecifierLoc) +MAKE_MATCHER_NAME_FROM_TYPE(QualType) +MAKE_MATCHER_NAME_FROM_TYPE(CXXBaseSpecifier) +MAKE_MATCHER_NAME_FROM_TYPE(CXXCtorInitializer) +MAKE_MATCHER_NAME_FROM_TYPE(LambdaCapture) +#undef MAKE_MATCHER_NAME_FROM_TYPE + /// A type-list implementation. /// /// A "linked list" of types, accessible by using the ::head and ::tail @@ -357,6 +432,8 @@ virtual llvm::Optional TraversalKind() const { return llvm::None; } + + virtual std::string getName() const = 0; }; /// Generic interface for matchers on an AST node of type T. @@ -381,6 +458,10 @@ BoundNodesTreeBuilder *Builder) const override { return matches(DynNode.getUnchecked(), Finder, Builder); } + + std::string getName() const override { + return ::clang::ast_matchers::internal::makeMatcherNameFromType(); + } }; /// Interface for matchers that only evaluate properties on a single @@ -467,12 +548,18 @@ /// restricts the node types for \p Kind. DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const; - /// Return a matcher that that points to the same implementation, but sets the + /// Return a matcher that points to the same implementation, but sets the /// traversal kind. /// /// If the traversal kind is already set, then \c TK overrides it. DynTypedMatcher withTraversalKind(TraversalKind TK); + /// Return a matcher that points to the same implementation, but sets the + /// name. + /// + /// If the name is already set, then \c MatcherName overrides it. + DynTypedMatcher withMatcherName(std::string MatcherName) const; + /// Returns true if the matcher matches the given \c DynNode. bool matches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const; @@ -544,6 +631,8 @@ return Implementation->TraversalKind(); } + std::string getMatcherName() const { return Implementation->getName(); } + private: DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind, IntrusiveRefCntPtr Implementation) @@ -663,6 +752,8 @@ } }; + std::string getMatcherName() const { return Implementation.getMatcherName(); } + private: // For Matcher <=> Matcher conversions. template friend class Matcher; @@ -927,6 +1018,10 @@ return matchesSpecialized(Node); } + std::string getName() const override { + return "HasOverloadedOperatorNameMatcher"; + } + private: /// CXXOperatorCallExpr exist only for calls to overloaded operators @@ -956,6 +1051,8 @@ bool matchesNode(const NamedDecl &Node) const override; + std::string getName() const override { return "HasNameMatcher"; } + private: /// Unqualified match routine. /// @@ -1011,6 +1108,8 @@ return matchesSpecialized(Node, Finder, Builder); } + std::string getName() const override { return "HasDeclarationMatcher"; } + private: /// Forwards to matching on the underlying type of the QualType. bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, @@ -1232,6 +1331,10 @@ template class BindableMatcher : public Matcher { public: explicit BindableMatcher(const Matcher &M) : Matcher(M) {} + explicit BindableMatcher(const Matcher &M, std::string MatcherName) + : Matcher(DynTypedMatcher(M) + .withMatcherName(MatcherName) + .unconditionalConvertTo()) {} explicit BindableMatcher(MatcherInterface *Implementation) : Matcher(Implementation) {} @@ -1303,7 +1406,8 @@ BindableMatcher makeDynCastAllOfComposite(ArrayRef *> InnerMatchers) { return BindableMatcher( - makeAllOfComposite(InnerMatchers).template dynCastTo()); + makeAllOfComposite(InnerMatchers).template dynCastTo(), + makeMatcherNameFromType()); } /// A VariadicDynCastAllOfMatcher object is a @@ -1773,6 +1877,8 @@ return Node.getValue() == ExpectedValue; } + std::string getName() const override { return "ValueEqualsMatcher"; } + private: ValueT ExpectedValue; }; @@ -2251,6 +2357,8 @@ return OptOpName && llvm::is_contained(Names, *OptOpName); } + std::string getName() const override { return "HasAnyOperatorNameMatcher"; } + private: static Optional getOpName(const UnaryOperator &Node) { return Node.getOpcodeStr(Node.getOpcode()); diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h --- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -101,6 +101,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ *Builder) const override; \ + std::string getName() const override { return #DefineMatcher; } \ }; \ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher() { \ @@ -141,6 +142,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ *Builder) const override; \ + std::string getName() const override { return #DefineMatcher; } \ \ private: \ ParamType Param; \ @@ -190,6 +192,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ *Builder) const override; \ + std::string getName() const override { return #DefineMatcher; } \ \ private: \ ParamType1 Param1; \ @@ -237,6 +240,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ *Builder) const override; \ + std::string getName() const override { return #DefineMatcher; } \ }; \ } \ inline ::clang::ast_matchers::internal::PolymorphicMatcher< \ @@ -279,6 +283,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ *Builder) const override; \ + std::string getName() const override { return #DefineMatcher; } \ \ private: \ ParamType Param; \ @@ -331,6 +336,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \ *Builder) const override; \ + std::string getName() const override { return #DefineMatcher; } \ \ private: \ ParamType1 Param1; \ diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -115,15 +115,19 @@ template class VariadicMatcher : public DynMatcherInterface { public: - VariadicMatcher(std::vector InnerMatchers) - : InnerMatchers(std::move(InnerMatchers)) {} + VariadicMatcher(std::string MatcherName, + std::vector InnerMatchers) + : MatcherName(MatcherName), InnerMatchers(std::move(InnerMatchers)) {} bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { return Func(DynNode, Finder, Builder, InnerMatchers); } + std::string getName() const override { return MatcherName; } + private: + const std::string MatcherName; std::vector InnerMatchers; }; @@ -144,11 +148,39 @@ return InnerMatcher->TraversalKind(); } + std::string getName() const override { return InnerMatcher->getName(); } + private: const std::string ID; const IntrusiveRefCntPtr InnerMatcher; }; +/// A matcher that specifies a particular name. +/// +/// The name provided to the constructor overrides any name that may be +/// specified by the `InnerMatcher`. +class NameMatcherImpl : public DynMatcherInterface { +public: + NameMatcherImpl(std::string _MatcherName, + IntrusiveRefCntPtr InnerMatcher) + : MatcherName(_MatcherName), InnerMatcher(std::move(InnerMatcher)) {} + + bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { + return InnerMatcher->dynMatches(DynNode, Finder, Builder); + } + + std::string getName() const override { return MatcherName; } + + llvm::Optional TraversalKind() const override { + return InnerMatcher->TraversalKind(); + } + +private: + const std::string MatcherName; + const IntrusiveRefCntPtr InnerMatcher; +}; + /// A matcher that always returns true. class TrueMatcherImpl : public DynMatcherInterface { public: @@ -158,6 +190,8 @@ BoundNodesTreeBuilder *) const override { return true; } + + std::string getName() const override { return "TrueMatcher"; } }; /// A matcher that specifies a particular \c TraversalKind. @@ -180,6 +214,8 @@ return TK; } + std::string getName() const override { return InnerMatcher->getName(); } + private: clang::TraversalKind TK; IntrusiveRefCntPtr InnerMatcher; @@ -219,31 +255,31 @@ RestrictKind = ASTNodeKind::getMostDerivedType(RestrictKind, IM.RestrictKind); } - return DynTypedMatcher( - SupportedKind, RestrictKind, - new VariadicMatcher(std::move(InnerMatchers))); + return DynTypedMatcher(SupportedKind, RestrictKind, + new VariadicMatcher( + "allOf", std::move(InnerMatchers))); case VO_AnyOf: - return DynTypedMatcher( - SupportedKind, RestrictKind, - new VariadicMatcher(std::move(InnerMatchers))); + return DynTypedMatcher(SupportedKind, RestrictKind, + new VariadicMatcher( + "anyOf", std::move(InnerMatchers))); case VO_EachOf: - return DynTypedMatcher( - SupportedKind, RestrictKind, - new VariadicMatcher(std::move(InnerMatchers))); + return DynTypedMatcher(SupportedKind, RestrictKind, + new VariadicMatcher( + "eachOf", std::move(InnerMatchers))); case VO_Optionally: return DynTypedMatcher(SupportedKind, RestrictKind, new VariadicMatcher( - std::move(InnerMatchers))); + "optionally", 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(std::move(InnerMatchers))); + new VariadicMatcher("not", std::move(InnerMatchers))); } llvm_unreachable("Invalid Op value."); } @@ -263,6 +299,14 @@ return Copy; } +DynTypedMatcher +DynTypedMatcher::withMatcherName(std::string MatcherName) const { + auto Copy = *this; + Copy.Implementation = + new NameMatcherImpl(MatcherName, std::move(Copy.Implementation)); + return Copy; +} + DynTypedMatcher DynTypedMatcher::trueMatcher(ASTNodeKind NodeKind) { // We only ever need one instance of TrueMatcherImpl, so we create a static // instance and reuse it to reduce the overhead of the matcher and increase