summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers/ASTMatchersInternal.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchersInternal.h')
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h390
1 files changed, 137 insertions, 253 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index ebe5cdd..cbaa4ba 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -38,9 +38,13 @@
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/VariadicFunction.h"
@@ -139,7 +143,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);
}
@@ -206,7 +210,7 @@ public:
template <typename T>
class MatcherInterface : public DynMatcherInterface {
public:
- virtual ~MatcherInterface() {}
+ ~MatcherInterface() override {}
/// \brief Returns true if 'Node' can be matched.
///
@@ -381,6 +385,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
@@ -453,19 +470,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:
@@ -629,13 +645,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 {
@@ -698,13 +714,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
@@ -847,19 +862,11 @@ protected:
/// \brief A type-list implementation.
///
-/// A list is declared as a tree of type list nodes, where the leafs are the
-/// types.
-/// However, it is used as a "linked list" of types, by using the ::head and
-/// ::tail typedefs.
-/// Each node supports up to 4 children (instead of just 2) to reduce the
-/// nesting required by large lists.
-template <typename T1 = void, typename T2 = void, typename T3 = void,
- typename T4 = void>
-struct TypeList {
- /// \brief Implementation detail. Combined with the specializations below,
- /// this typedef allows for flattening of nested structures.
- typedef TypeList<T1, T2, T3, T4> self;
+/// A "linked list" of types, accessible by using the ::head and ::tail
+/// typedefs.
+template <typename... Ts> struct TypeList {}; // Empty sentinel type list.
+template <typename T1, typename... Ts> struct TypeList<T1, Ts...> {
/// \brief The first type on the list.
typedef T1 head;
@@ -867,24 +874,7 @@ struct TypeList {
///
/// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
/// end of the list.
- typedef typename TypeList<T2, T3, T4>::self tail;
-};
-
-/// \brief Template specialization to allow nested lists.
-///
-/// First element is a typelist. Pop its first element.
-template <typename Sub1, typename Sub2, typename Sub3, typename Sub4,
- typename T2, typename T3, typename T4>
-struct TypeList<TypeList<Sub1, Sub2, Sub3, Sub4>, T2, T3,
- T4> : public TypeList<Sub1,
- typename TypeList<Sub2, Sub3, Sub4>::self,
- typename TypeList<T2, T3, T4>::self> {};
-
-/// \brief Template specialization to allow nested lists.
-///
-/// First element is an empty typelist. Skip it.
-template <typename T2, typename T3, typename T4>
-struct TypeList<TypeList<>, T2, T3, T4> : public TypeList<T2, T3, T4> {
+ typedef TypeList<Ts...> tail;
};
/// \brief The empty type list.
@@ -906,14 +896,13 @@ struct TypeListContainsSuperOf<EmptyTypeList, T> {
/// \brief A "type list" that contains all types.
///
/// Useful for matchers like \c anything and \c unless.
-typedef TypeList<
- TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc>,
- TypeList<QualType, Type, TypeLoc, CXXCtorInitializer> > AllNodeBaseTypes;
+typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
+ QualType, Type, TypeLoc, CXXCtorInitializer> AllNodeBaseTypes;
/// \brief Helper meta-function to extract the argument out of a function of
/// type void(Arg).
///
-/// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details.
+/// See AST_POLYMORPHIC_SUPPORTED_TYPES for details.
template <class T> struct ExtractFunctionArgMeta;
template <class T> struct ExtractFunctionArgMeta<void(T)> {
typedef T type;
@@ -921,17 +910,15 @@ template <class T> struct ExtractFunctionArgMeta<void(T)> {
/// \brief Default type lists for ArgumentAdaptingMatcher matchers.
typedef AllNodeBaseTypes AdaptativeDefaultFromTypes;
-typedef TypeList<TypeList<Decl, Stmt, NestedNameSpecifier>,
- TypeList<NestedNameSpecifierLoc, TypeLoc, QualType> >
-AdaptativeDefaultToTypes;
+typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
+ TypeLoc, QualType> AdaptativeDefaultToTypes;
/// \brief All types that are supported by HasDeclarationMatcher above.
-typedef TypeList<TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType>,
- TypeList<InjectedClassNameType, LabelStmt, MemberExpr>,
- TypeList<QualType, RecordType, TagType>,
- TypeList<TemplateSpecializationType, TemplateTypeParmType,
- TypedefType, UnresolvedUsingType> >
-HasDeclarationSupportedTypes;
+typedef TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType,
+ InjectedClassNameType, LabelStmt, MemberExpr, QualType,
+ RecordType, TagType, TemplateSpecializationType,
+ TemplateTypeParmType, TypedefType,
+ UnresolvedUsingType> HasDeclarationSupportedTypes;
/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
/// "adapting" a \c To into a \c T.
@@ -1095,24 +1082,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
@@ -1121,176 +1105,65 @@ 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.
/// @{
-/// \brief "No argument" placeholder to use as template paratemers.
-struct VariadicOperatorNoArg {};
-
/// \brief Polymorphic matcher object that uses a \c
/// DynTypedMatcher::VariadicOperator operator.
///
/// Input matchers can have any type (including other polymorphic matcher
/// types), and the actual Matcher<T> is generated on demand with an implicit
/// coversion operator.
-template <typename P1, typename P2 = VariadicOperatorNoArg,
- typename P3 = VariadicOperatorNoArg,
- typename P4 = VariadicOperatorNoArg,
- typename P5 = VariadicOperatorNoArg,
- typename P6 = VariadicOperatorNoArg,
- typename P7 = VariadicOperatorNoArg,
- typename P8 = VariadicOperatorNoArg,
- typename P9 = VariadicOperatorNoArg>
-class VariadicOperatorMatcher {
+template <typename... Ps> class VariadicOperatorMatcher {
public:
- VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
- const P1 &Param1,
- const P2 &Param2 = VariadicOperatorNoArg(),
- const P3 &Param3 = VariadicOperatorNoArg(),
- const P4 &Param4 = VariadicOperatorNoArg(),
- const P5 &Param5 = VariadicOperatorNoArg(),
- const P6 &Param6 = VariadicOperatorNoArg(),
- const P7 &Param7 = VariadicOperatorNoArg(),
- const P8 &Param8 = VariadicOperatorNoArg(),
- const P9 &Param9 = VariadicOperatorNoArg())
- : Op(Op), Param1(Param1), Param2(Param2), Param3(Param3),
- Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7),
- Param8(Param8), Param9(Param9) {}
+ VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
+ : Op(Op), Params(std::forward<Ps>(Params)...) {}
template <typename T> operator Matcher<T>() const {
- std::vector<DynTypedMatcher> Matchers;
- addMatcher<T>(Param1, Matchers);
- addMatcher<T>(Param2, Matchers);
- addMatcher<T>(Param3, Matchers);
- addMatcher<T>(Param4, Matchers);
- addMatcher<T>(Param5, Matchers);
- addMatcher<T>(Param6, Matchers);
- addMatcher<T>(Param7, Matchers);
- addMatcher<T>(Param8, Matchers);
- addMatcher<T>(Param9, Matchers);
- return DynTypedMatcher::constructVariadic(Op, std::move(Matchers))
+ return DynTypedMatcher::constructVariadic(
+ Op, getMatchers<T>(llvm::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
private:
- template <typename T>
- static void addMatcher(const Matcher<T> &M,
- std::vector<DynTypedMatcher> &Matchers) {
- Matchers.push_back(M);
+ // Helper method to unpack the tuple into a vector.
+ template <typename T, std::size_t... Is>
+ std::vector<DynTypedMatcher> getMatchers(llvm::index_sequence<Is...>) const {
+ return {Matcher<T>(std::get<Is>(Params))...};
}
- /// \brief Overload to ignore \c VariadicOperatorNoArg arguments.
- template <typename T>
- static void addMatcher(VariadicOperatorNoArg,
- std::vector<DynTypedMatcher> &Matchers) {}
-
const DynTypedMatcher::VariadicOperator Op;
- const P1 Param1;
- const P2 Param2;
- const P3 Param3;
- const P4 Param4;
- const P5 Param5;
- const P6 Param6;
- const P7 Param7;
- const P8 Param8;
- const P9 Param9;
+ std::tuple<Ps...> Params;
};
/// \brief Overloaded function object to generate VariadicOperatorMatcher
/// objects from arbitrary matchers.
-///
-/// It supports 1-9 argument overloaded operator(). More can be added if needed.
template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
DynTypedMatcher::VariadicOperator Op;
- template <unsigned Count, typename T>
- struct EnableIfValidArity
- : public std::enable_if<MinCount <= Count && Count <= MaxCount, T> {};
-
- template <typename M1>
- typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type
- operator()(const M1 &P1) const {
- return VariadicOperatorMatcher<M1>(Op, P1);
- }
- template <typename M1, typename M2>
- typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type
- operator()(const M1 &P1, const M2 &P2) const {
- return VariadicOperatorMatcher<M1, M2>(Op, P1, P2);
- }
- template <typename M1, typename M2, typename M3>
- typename EnableIfValidArity<3, VariadicOperatorMatcher<M1, M2, M3> >::type
- operator()(const M1 &P1, const M2 &P2, const M3 &P3) const {
- return VariadicOperatorMatcher<M1, M2, M3>(Op, P1, P2, P3);
- }
- template <typename M1, typename M2, typename M3, typename M4>
- typename EnableIfValidArity<4, VariadicOperatorMatcher<M1, M2, M3, M4> >::type
- operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4>(Op, P1, P2, P3, P4);
- }
- template <typename M1, typename M2, typename M3, typename M4, typename M5>
- typename EnableIfValidArity<
- 5, VariadicOperatorMatcher<M1, M2, M3, M4, M5> >::type
- operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
- const M5 &P5) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Op, P1, P2, P3, P4, P5);
- }
- template <typename M1, typename M2, typename M3, typename M4, typename M5,
- typename M6>
- typename EnableIfValidArity<
- 6, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6> >::type
- operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
- const M5 &P5, const M6 &P6) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6>(
- Op, P1, P2, P3, P4, P5, P6);
- }
- template <typename M1, typename M2, typename M3, typename M4, typename M5,
- typename M6, typename M7>
- typename EnableIfValidArity<
- 7, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7> >::type
- operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
- const M5 &P5, const M6 &P6, const M7 &P7) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7>(
- Op, P1, P2, P3, P4, P5, P6, P7);
- }
- template <typename M1, typename M2, typename M3, typename M4, typename M5,
- typename M6, typename M7, typename M8>
- typename EnableIfValidArity<
- 8, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8> >::type
- operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
- const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8>(
- Op, P1, P2, P3, P4, P5, P6, P7, P8);
- }
- template <typename M1, typename M2, typename M3, typename M4, typename M5,
- typename M6, typename M7, typename M8, typename M9>
- typename EnableIfValidArity<
- 9, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9> >::type
- operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
- const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8,
- const M9 &P9) const {
- return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9>(
- Op, P1, P2, P3, P4, P5, P6, P7, P8, P9);
+ template <typename... Ms>
+ VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const {
+ static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount,
+ "invalid number of parameters for variadic matcher");
+ return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
}
};
@@ -1315,11 +1188,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))
@@ -1344,22 +1215,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
@@ -1367,22 +1235,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
@@ -1390,22 +1255,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
@@ -1415,23 +1277,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
@@ -1456,6 +1315,32 @@ private:
const ValueT ExpectedValue;
};
+/// \brief Template specializations to easily write matchers for floating point
+/// literals.
+template <>
+inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
+ const FloatingLiteral &Node) const {
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
+ return Node.getValue().convertToFloat() == ExpectedValue;
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
+ return Node.getValue().convertToDouble() == ExpectedValue;
+ return false;
+}
+template <>
+inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
+ const FloatingLiteral &Node) const {
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
+ return Node.getValue().convertToFloat() == ExpectedValue;
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
+ return Node.getValue().convertToDouble() == ExpectedValue;
+ return false;
+}
+template <>
+inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
+ const FloatingLiteral &Node) const {
+ return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
+}
+
/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
/// variadic functor that takes a number of Matcher<TargetT> and returns a
/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
@@ -1498,66 +1383,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;
};
@@ -1565,22 +1448,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;
};
OpenPOWER on IntegriCloud