[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,
const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.push_back(BoundNodesMap());
Bindings.emplace_back();
for (BoundNodesMap &Binding : Bindings)
Binding.addNode(Id, DynNode);
}
@ -384,6 +384,19 @@ private:
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.
///
/// 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
/// ignores any qualifiers.
template <typename TypeT>
class TypeToQualType : public MatcherInterface<QualType> {
public:
class TypeToQualType : public WrapperMatcherInterface<QualType> {
public:
TypeToQualType(const Matcher<TypeT> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: TypeToQualType::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (Node.isNull())
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:
@ -632,13 +644,13 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
/// not actually used.
template <typename T, typename DeclMatcherT>
class HasDeclarationMatcher : public MatcherInterface<T> {
class HasDeclarationMatcher : public WrapperMatcherInterface<T> {
static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
"instantiated with wrong types");
public:
explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: HasDeclarationMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
@ -701,13 +713,12 @@ private:
/// \brief Returns whether the inner matcher \c Node. Returns false if \c Node
/// is \c NULL.
bool matchesDecl(const Decl *Node,
ASTMatchFinder *Finder,
bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
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
@ -1070,24 +1081,21 @@ public:
///
/// ChildT must be an AST base type.
template <typename T, typename ChildT>
class HasMatcher : public MatcherInterface<T> {
class HasMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value,
"has only accepts base type matcher");
public:
explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {}
: HasMatcher::WrapperMatcherInterface(ChildMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf(
Node, ChildMatcher, Builder,
Node, this->InnerMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_First);
}
private:
const Matcher<ChildT> ChildMatcher;
};
/// \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
/// for each child that matches.
template <typename T, typename ChildT>
class ForEachMatcher : public MatcherInterface<T> {
class ForEachMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value,
"for each only accepts base type matcher");
public:
explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {}
explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
: ForEachMatcher::WrapperMatcherInterface(ChildMatcher) {}
bool matches(const T& Node, ASTMatchFinder* Finder,
BoundNodesTreeBuilder* Builder) const override {
return Finder->matchesChildOf(
Node, ChildMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_All);
Node, this->InnerMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_All);
}
private:
const Matcher<ChildT> ChildMatcher;
};
/// \brief VariadicOperatorMatcher related types.
@ -1182,11 +1187,9 @@ BindableMatcher<T> makeAllOfComposite(
return BindableMatcher<T>(*InnerMatchers[0]);
}
std::vector<DynTypedMatcher> DynMatchers;
DynMatchers.reserve(InnerMatchers.size());
for (const auto *InnerMatcher : InnerMatchers) {
DynMatchers.push_back(*InnerMatcher);
}
typedef llvm::pointee_iterator<const Matcher<T> *const *> PI;
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
std::move(DynMatchers))
@ -1211,22 +1214,19 @@ BindableMatcher<T> makeDynCastAllOfComposite(
///
/// DescendantT must be an AST base type.
template <typename T, typename DescendantT>
class HasDescendantMatcher : public MatcherInterface<T> {
class HasDescendantMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"has descendant only accepts base type matcher");
public:
explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {}
: HasDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(
Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First);
return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::BK_First);
}
private:
const Matcher<DescendantT> DescendantMatcher;
};
/// \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.
template <typename T, typename ParentT>
class HasParentMatcher : public MatcherInterface<T> {
class HasParentMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ParentT>::value,
"has parent only accepts base type matcher");
public:
explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
: ParentMatcher(ParentMatcher) {}
: HasParentMatcher::WrapperMatcherInterface(ParentMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(
Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly);
return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::AMM_ParentOnly);
}
private:
const Matcher<ParentT> ParentMatcher;
};
/// \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.
template <typename T, typename AncestorT>
class HasAncestorMatcher : public MatcherInterface<T> {
class HasAncestorMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<AncestorT>::value,
"has ancestor only accepts base type matcher");
public:
explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
: AncestorMatcher(AncestorMatcher) {}
: HasAncestorMatcher::WrapperMatcherInterface(AncestorMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(
Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All);
return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::AMM_All);
}
private:
const Matcher<AncestorT> AncestorMatcher;
};
/// \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
/// for each descendant node that matches instead of only for the first.
template <typename T, typename DescendantT>
class ForEachDescendantMatcher : public MatcherInterface<T> {
class ForEachDescendantMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"for each descendant only accepts base type matcher");
public:
public:
explicit ForEachDescendantMatcher(
const Matcher<DescendantT>& DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {}
const Matcher<DescendantT> &DescendantMatcher)
: ForEachDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
bool matches(const T& Node, ASTMatchFinder* Finder,
BoundNodesTreeBuilder* Builder) const override {
return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder,
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::BK_All);
}
private:
const Matcher<DescendantT> DescendantMatcher;
};
/// \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
/// \c Matcher<T> matches.
template <typename TLoc, typename T>
class LocMatcher : public MatcherInterface<TLoc> {
class LocMatcher : public WrapperMatcherInterface<TLoc> {
public:
explicit LocMatcher(const Matcher<T> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: LocMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const TLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (!Node)
return false;
return InnerMatcher.matches(*extract(Node), Finder, Builder);
return this->InnerMatcher.matches(extract(Node), Finder, Builder);
}
private:
const NestedNameSpecifier *extract(const NestedNameSpecifierLoc &Loc) const {
return Loc.getNestedNameSpecifier();
static ast_type_traits::DynTypedNode
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
/// \c QualType.
///
/// Used to implement the \c loc() matcher.
class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> {
class TypeLocTypeMatcher : public WrapperMatcherInterface<TypeLoc> {
public:
explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: TypeLocTypeMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (!Node)
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
/// another node of type \c T that can be reached using a given traverse
/// function.
template <typename T>
class TypeTraverseMatcher : public MatcherInterface<T> {
class TypeTraverseMatcher : public WrapperMatcherInterface<T> {
public:
explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
QualType (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
: TypeTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
QualType NextNode = (Node.*TraverseFunction)();
if (NextNode.isNull())
return false;
return InnerMatcher.matches(NextNode, Finder, Builder);
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
}
private:
const Matcher<QualType> InnerMatcher;
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
/// given traverse function.
template <typename T>
class TypeLocTraverseMatcher : public MatcherInterface<T> {
class TypeLocTraverseMatcher : public WrapperMatcherInterface<T> {
public:
explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
TypeLoc (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
: TypeLocTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
TypeLoc NextNode = (Node.*TraverseFunction)();
if (!NextNode)
return false;
return InnerMatcher.matches(NextNode, Finder, Builder);
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
}
private:
const Matcher<TypeLoc> InnerMatcher;
TypeLoc (T::*TraverseFunction)() const;
};