[ASTMatchers] Factor wrapping matcher classes into a common base class.

The deduplication here is negligible, but it allows the compiler to
skip emission of many templated base class destructors. Shrinks
clang-query by 53k. No functionality change intended.

llvm-svn: 232924
This commit is contained in:
Benjamin Kramer 2015-03-22 21:57:53 +00:00
parent abd9f5bfb6
commit 70f19df90d
1 changed files with 76 additions and 86 deletions

View File

@ -142,7 +142,7 @@ public:
void setBinding(const std::string &Id, void setBinding(const std::string &Id,
const ast_type_traits::DynTypedNode &DynNode) { const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty()) if (Bindings.empty())
Bindings.push_back(BoundNodesMap()); Bindings.emplace_back();
for (BoundNodesMap &Binding : Bindings) for (BoundNodesMap &Binding : Bindings)
Binding.addNode(Id, DynNode); Binding.addNode(Id, DynNode);
} }
@ -384,6 +384,19 @@ private:
IntrusiveRefCntPtr<DynMatcherInterface> Implementation; IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
}; };
/// \brief Wrapper base class for a wrapping matcher.
///
/// This is just a container for a DynTypedMatcher that can be used as a base
/// class for another matcher.
template <typename T>
class WrapperMatcherInterface : public MatcherInterface<T> {
protected:
explicit WrapperMatcherInterface(DynTypedMatcher &&InnerMatcher)
: InnerMatcher(std::move(InnerMatcher)) {}
const DynTypedMatcher InnerMatcher;
};
/// \brief Wrapper of a MatcherInterface<T> *that allows copying. /// \brief Wrapper of a MatcherInterface<T> *that allows copying.
/// ///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is /// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@ -456,19 +469,18 @@ public:
/// does only matches in the absence of qualifiers, or not, i.e. simply /// does only matches in the absence of qualifiers, or not, i.e. simply
/// ignores any qualifiers. /// ignores any qualifiers.
template <typename TypeT> template <typename TypeT>
class TypeToQualType : public MatcherInterface<QualType> { class TypeToQualType : public WrapperMatcherInterface<QualType> {
public: public:
TypeToQualType(const Matcher<TypeT> &InnerMatcher) TypeToQualType(const Matcher<TypeT> &InnerMatcher)
: InnerMatcher(InnerMatcher) {} : TypeToQualType::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const QualType &Node, ASTMatchFinder *Finder, bool matches(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
if (Node.isNull()) if (Node.isNull())
return false; return false;
return InnerMatcher.matches(*Node, Finder, Builder); return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
} }
private:
const Matcher<TypeT> InnerMatcher;
}; };
private: private:
@ -632,13 +644,13 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
/// not actually used. /// not actually used.
template <typename T, typename DeclMatcherT> template <typename T, typename DeclMatcherT>
class HasDeclarationMatcher : public MatcherInterface<T> { class HasDeclarationMatcher : public WrapperMatcherInterface<T> {
static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value, static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
"instantiated with wrong types"); "instantiated with wrong types");
public: public:
explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher) explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
: InnerMatcher(InnerMatcher) {} : HasDeclarationMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
@ -701,13 +713,12 @@ private:
/// \brief Returns whether the inner matcher \c Node. Returns false if \c Node /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node
/// is \c NULL. /// is \c NULL.
bool matchesDecl(const Decl *Node, bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const { BoundNodesTreeBuilder *Builder) const {
return Node != nullptr && InnerMatcher.matches(*Node, Finder, Builder); return Node != nullptr &&
this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
} }
const Matcher<Decl> InnerMatcher;
}; };
/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST /// \brief IsBaseType<T>::value is true if T is a "base" type in the AST
@ -1070,24 +1081,21 @@ public:
/// ///
/// ChildT must be an AST base type. /// ChildT must be an AST base type.
template <typename T, typename ChildT> template <typename T, typename ChildT>
class HasMatcher : public MatcherInterface<T> { class HasMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value, static_assert(IsBaseType<ChildT>::value,
"has only accepts base type matcher"); "has only accepts base type matcher");
public: public:
explicit HasMatcher(const Matcher<ChildT> &ChildMatcher) explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {} : HasMatcher::WrapperMatcherInterface(ChildMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf( return Finder->matchesChildOf(
Node, ChildMatcher, Builder, Node, this->InnerMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_First); ASTMatchFinder::BK_First);
} }
private:
const Matcher<ChildT> ChildMatcher;
}; };
/// \brief Matches nodes of type T that have child nodes of type ChildT for /// \brief Matches nodes of type T that have child nodes of type ChildT for
@ -1096,24 +1104,21 @@ public:
/// As opposed to the HasMatcher, the ForEachMatcher will produce a match /// As opposed to the HasMatcher, the ForEachMatcher will produce a match
/// for each child that matches. /// for each child that matches.
template <typename T, typename ChildT> template <typename T, typename ChildT>
class ForEachMatcher : public MatcherInterface<T> { class ForEachMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value, static_assert(IsBaseType<ChildT>::value,
"for each only accepts base type matcher"); "for each only accepts base type matcher");
public: public:
explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher) explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {} : ForEachMatcher::WrapperMatcherInterface(ChildMatcher) {}
bool matches(const T& Node, ASTMatchFinder* Finder, bool matches(const T& Node, ASTMatchFinder* Finder,
BoundNodesTreeBuilder* Builder) const override { BoundNodesTreeBuilder* Builder) const override {
return Finder->matchesChildOf( return Finder->matchesChildOf(
Node, ChildMatcher, Builder, Node, this->InnerMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_All); ASTMatchFinder::BK_All);
} }
private:
const Matcher<ChildT> ChildMatcher;
}; };
/// \brief VariadicOperatorMatcher related types. /// \brief VariadicOperatorMatcher related types.
@ -1182,11 +1187,9 @@ BindableMatcher<T> makeAllOfComposite(
return BindableMatcher<T>(*InnerMatchers[0]); return BindableMatcher<T>(*InnerMatchers[0]);
} }
std::vector<DynTypedMatcher> DynMatchers; typedef llvm::pointee_iterator<const Matcher<T> *const *> PI;
DynMatchers.reserve(InnerMatchers.size()); std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
for (const auto *InnerMatcher : InnerMatchers) { PI(InnerMatchers.end()));
DynMatchers.push_back(*InnerMatcher);
}
return BindableMatcher<T>( return BindableMatcher<T>(
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf, DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
std::move(DynMatchers)) std::move(DynMatchers))
@ -1211,22 +1214,19 @@ BindableMatcher<T> makeDynCastAllOfComposite(
/// ///
/// DescendantT must be an AST base type. /// DescendantT must be an AST base type.
template <typename T, typename DescendantT> template <typename T, typename DescendantT>
class HasDescendantMatcher : public MatcherInterface<T> { class HasDescendantMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value, static_assert(IsBaseType<DescendantT>::value,
"has descendant only accepts base type matcher"); "has descendant only accepts base type matcher");
public: public:
explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher) explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {} : HasDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf( return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First); ASTMatchFinder::BK_First);
} }
private:
const Matcher<DescendantT> DescendantMatcher;
}; };
/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT /// \brief Matches nodes of type \c T that have a parent node of type \c ParentT
@ -1234,22 +1234,19 @@ public:
/// ///
/// \c ParentT must be an AST base type. /// \c ParentT must be an AST base type.
template <typename T, typename ParentT> template <typename T, typename ParentT>
class HasParentMatcher : public MatcherInterface<T> { class HasParentMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ParentT>::value, static_assert(IsBaseType<ParentT>::value,
"has parent only accepts base type matcher"); "has parent only accepts base type matcher");
public: public:
explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher) explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
: ParentMatcher(ParentMatcher) {} : HasParentMatcher::WrapperMatcherInterface(ParentMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf( return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly); ASTMatchFinder::AMM_ParentOnly);
} }
private:
const Matcher<ParentT> ParentMatcher;
}; };
/// \brief Matches nodes of type \c T that have at least one ancestor node of /// \brief Matches nodes of type \c T that have at least one ancestor node of
@ -1257,22 +1254,19 @@ public:
/// ///
/// \c AncestorT must be an AST base type. /// \c AncestorT must be an AST base type.
template <typename T, typename AncestorT> template <typename T, typename AncestorT>
class HasAncestorMatcher : public MatcherInterface<T> { class HasAncestorMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<AncestorT>::value, static_assert(IsBaseType<AncestorT>::value,
"has ancestor only accepts base type matcher"); "has ancestor only accepts base type matcher");
public: public:
explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher) explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
: AncestorMatcher(AncestorMatcher) {} : HasAncestorMatcher::WrapperMatcherInterface(AncestorMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf( return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All); ASTMatchFinder::AMM_All);
} }
private:
const Matcher<AncestorT> AncestorMatcher;
}; };
/// \brief Matches nodes of type T that have at least one descendant node of /// \brief Matches nodes of type T that have at least one descendant node of
@ -1282,23 +1276,20 @@ public:
/// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match /// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match
/// for each descendant node that matches instead of only for the first. /// for each descendant node that matches instead of only for the first.
template <typename T, typename DescendantT> template <typename T, typename DescendantT>
class ForEachDescendantMatcher : public MatcherInterface<T> { class ForEachDescendantMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value, static_assert(IsBaseType<DescendantT>::value,
"for each descendant only accepts base type matcher"); "for each descendant only accepts base type matcher");
public: public:
explicit ForEachDescendantMatcher( explicit ForEachDescendantMatcher(
const Matcher<DescendantT>& DescendantMatcher) const Matcher<DescendantT> &DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {} : ForEachDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
bool matches(const T& Node, ASTMatchFinder* Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder* Builder) const override { BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder, return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::BK_All); ASTMatchFinder::BK_All);
} }
private:
const Matcher<DescendantT> DescendantMatcher;
}; };
/// \brief Matches on nodes that have a getValue() method if getValue() equals /// \brief Matches on nodes that have a getValue() method if getValue() equals
@ -1391,66 +1382,64 @@ public:
/// \brief Matches nodes of type \c TLoc for which the inner /// \brief Matches nodes of type \c TLoc for which the inner
/// \c Matcher<T> matches. /// \c Matcher<T> matches.
template <typename TLoc, typename T> template <typename TLoc, typename T>
class LocMatcher : public MatcherInterface<TLoc> { class LocMatcher : public WrapperMatcherInterface<TLoc> {
public: public:
explicit LocMatcher(const Matcher<T> &InnerMatcher) explicit LocMatcher(const Matcher<T> &InnerMatcher)
: InnerMatcher(InnerMatcher) {} : LocMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const TLoc &Node, ASTMatchFinder *Finder, bool matches(const TLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
if (!Node) if (!Node)
return false; return false;
return InnerMatcher.matches(*extract(Node), Finder, Builder); return this->InnerMatcher.matches(extract(Node), Finder, Builder);
} }
private: private:
const NestedNameSpecifier *extract(const NestedNameSpecifierLoc &Loc) const { static ast_type_traits::DynTypedNode
return Loc.getNestedNameSpecifier(); extract(const NestedNameSpecifierLoc &Loc) {
return ast_type_traits::DynTypedNode::create(*Loc.getNestedNameSpecifier());
} }
const Matcher<T> InnerMatcher;
}; };
/// \brief Matches \c TypeLocs based on an inner matcher matching a certain /// \brief Matches \c TypeLocs based on an inner matcher matching a certain
/// \c QualType. /// \c QualType.
/// ///
/// Used to implement the \c loc() matcher. /// Used to implement the \c loc() matcher.
class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> { class TypeLocTypeMatcher : public WrapperMatcherInterface<TypeLoc> {
public: public:
explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher) explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
: InnerMatcher(InnerMatcher) {} : TypeLocTypeMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const TypeLoc &Node, ASTMatchFinder *Finder, bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
if (!Node) if (!Node)
return false; return false;
return InnerMatcher.matches(Node.getType(), Finder, Builder); return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(Node.getType()), Finder, Builder);
} }
private:
const Matcher<QualType> InnerMatcher;
}; };
/// \brief Matches nodes of type \c T for which the inner matcher matches on a /// \brief Matches nodes of type \c T for which the inner matcher matches on a
/// another node of type \c T that can be reached using a given traverse /// another node of type \c T that can be reached using a given traverse
/// function. /// function.
template <typename T> template <typename T>
class TypeTraverseMatcher : public MatcherInterface<T> { class TypeTraverseMatcher : public WrapperMatcherInterface<T> {
public: public:
explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher, explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
QualType (T::*TraverseFunction)() const) QualType (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} : TypeTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
QualType NextNode = (Node.*TraverseFunction)(); QualType NextNode = (Node.*TraverseFunction)();
if (NextNode.isNull()) if (NextNode.isNull())
return false; return false;
return InnerMatcher.matches(NextNode, Finder, Builder); return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
} }
private: private:
const Matcher<QualType> InnerMatcher;
QualType (T::*TraverseFunction)() const; QualType (T::*TraverseFunction)() const;
}; };
@ -1458,22 +1447,23 @@ private:
/// matcher matches on a another node of type \c T that can be reached using a /// matcher matches on a another node of type \c T that can be reached using a
/// given traverse function. /// given traverse function.
template <typename T> template <typename T>
class TypeLocTraverseMatcher : public MatcherInterface<T> { class TypeLocTraverseMatcher : public WrapperMatcherInterface<T> {
public: public:
explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher, explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
TypeLoc (T::*TraverseFunction)() const) TypeLoc (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {} : TypeLocTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder, bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override { BoundNodesTreeBuilder *Builder) const override {
TypeLoc NextNode = (Node.*TraverseFunction)(); TypeLoc NextNode = (Node.*TraverseFunction)();
if (!NextNode) if (!NextNode)
return false; return false;
return InnerMatcher.matches(NextNode, Finder, Builder); return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
} }
private: private:
const Matcher<TypeLoc> InnerMatcher;
TypeLoc (T::*TraverseFunction)() const; TypeLoc (T::*TraverseFunction)() const;
}; };