forked from OSchip/llvm-project
[ASTMatchers] NFC Rearrange declarations to allow more arg adapting
This commit is contained in:
parent
894d88a759
commit
ce24bb0edd
|
@ -1171,6 +1171,232 @@ using HasDeclarationSupportedTypes =
|
||||||
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
|
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
|
||||||
UnresolvedUsingType, ObjCIvarRefExpr>;
|
UnresolvedUsingType, ObjCIvarRefExpr>;
|
||||||
|
|
||||||
|
/// A Matcher that allows binding the node it matches to an id.
|
||||||
|
///
|
||||||
|
/// BindableMatcher provides a \a bind() method that allows binding the
|
||||||
|
/// matched node to an id if the match was successful.
|
||||||
|
template <typename T> class BindableMatcher : public Matcher<T> {
|
||||||
|
public:
|
||||||
|
explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
|
||||||
|
explicit BindableMatcher(MatcherInterface<T> *Implementation)
|
||||||
|
: Matcher<T>(Implementation) {}
|
||||||
|
|
||||||
|
/// Returns a matcher that will bind the matched node on a match.
|
||||||
|
///
|
||||||
|
/// The returned matcher is equivalent to this matcher, but will
|
||||||
|
/// bind the matched node on a match.
|
||||||
|
Matcher<T> bind(StringRef ID) const {
|
||||||
|
return DynTypedMatcher(*this)
|
||||||
|
.tryBind(ID)
|
||||||
|
->template unconditionalConvertTo<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as Matcher<T>'s conversion operator, but enables binding on
|
||||||
|
/// the returned matcher.
|
||||||
|
operator DynTypedMatcher() const {
|
||||||
|
DynTypedMatcher Result = static_cast<const Matcher<T> &>(*this);
|
||||||
|
Result.setAllowBind(true);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Matches any instance of the given NodeType.
|
||||||
|
///
|
||||||
|
/// This is useful when a matcher syntactically requires a child matcher,
|
||||||
|
/// but the context doesn't care. See for example: anything().
|
||||||
|
class TrueMatcher {
|
||||||
|
public:
|
||||||
|
using ReturnTypes = AllNodeBaseTypes;
|
||||||
|
|
||||||
|
template <typename T> operator Matcher<T>() const {
|
||||||
|
return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
|
||||||
|
.template unconditionalConvertTo<T>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Creates a Matcher<T> that matches if all inner matchers match.
|
||||||
|
template <typename T>
|
||||||
|
BindableMatcher<T>
|
||||||
|
makeAllOfComposite(ArrayRef<const Matcher<T> *> InnerMatchers) {
|
||||||
|
// For the size() == 0 case, we return a "true" matcher.
|
||||||
|
if (InnerMatchers.empty()) {
|
||||||
|
return BindableMatcher<T>(TrueMatcher());
|
||||||
|
}
|
||||||
|
// For the size() == 1 case, we simply return that one matcher.
|
||||||
|
// No need to wrap it in a variadic operation.
|
||||||
|
if (InnerMatchers.size() == 1) {
|
||||||
|
return BindableMatcher<T>(*InnerMatchers[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
using PI = llvm::pointee_iterator<const Matcher<T> *const *>;
|
||||||
|
|
||||||
|
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
|
||||||
|
PI(InnerMatchers.end()));
|
||||||
|
return BindableMatcher<T>(
|
||||||
|
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
|
||||||
|
ASTNodeKind::getFromNodeKind<T>(),
|
||||||
|
std::move(DynMatchers))
|
||||||
|
.template unconditionalConvertTo<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a Matcher<T> that matches if
|
||||||
|
/// T is dyn_cast'able into InnerT and all inner matchers match.
|
||||||
|
///
|
||||||
|
/// Returns BindableMatcher, as matchers that use dyn_cast have
|
||||||
|
/// the same object both to match on and to run submatchers on,
|
||||||
|
/// so there is no ambiguity with what gets bound.
|
||||||
|
template <typename T, typename InnerT>
|
||||||
|
BindableMatcher<T>
|
||||||
|
makeDynCastAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
|
||||||
|
return BindableMatcher<T>(
|
||||||
|
makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// given matchers, if SourceT can be dynamically casted into TargetT.
|
||||||
|
///
|
||||||
|
/// For example:
|
||||||
|
/// const VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> record;
|
||||||
|
/// Creates a functor record(...) that creates a Matcher<Decl> given
|
||||||
|
/// a variable number of arguments of type Matcher<CXXRecordDecl>.
|
||||||
|
/// The returned matcher matches if the given Decl can by dynamically
|
||||||
|
/// casted to CXXRecordDecl and all given matchers match.
|
||||||
|
template <typename SourceT, typename TargetT>
|
||||||
|
class VariadicDynCastAllOfMatcher
|
||||||
|
: public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
|
||||||
|
makeDynCastAllOfComposite<SourceT, TargetT>> {
|
||||||
|
public:
|
||||||
|
VariadicDynCastAllOfMatcher() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
|
||||||
|
/// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T
|
||||||
|
/// nodes that are matched by all of the given matchers.
|
||||||
|
///
|
||||||
|
/// For example:
|
||||||
|
/// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
|
||||||
|
/// Creates a functor nestedNameSpecifier(...) that creates a
|
||||||
|
/// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type
|
||||||
|
/// \c Matcher<NestedNameSpecifier>.
|
||||||
|
/// The returned matcher matches if all given matchers match.
|
||||||
|
template <typename T>
|
||||||
|
class VariadicAllOfMatcher
|
||||||
|
: public VariadicFunction<BindableMatcher<T>, Matcher<T>,
|
||||||
|
makeAllOfComposite<T>> {
|
||||||
|
public:
|
||||||
|
VariadicAllOfMatcher() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// VariadicOperatorMatcher related types.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// conversion operator.
|
||||||
|
template <typename... Ps> class VariadicOperatorMatcher {
|
||||||
|
public:
|
||||||
|
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
|
||||||
|
: Op(Op), Params(std::forward<Ps>(Params)...) {}
|
||||||
|
|
||||||
|
template <typename T> operator Matcher<T>() const {
|
||||||
|
return DynTypedMatcher::constructVariadic(
|
||||||
|
Op, ASTNodeKind::getFromNodeKind<T>(),
|
||||||
|
getMatchers<T>(std::index_sequence_for<Ps...>()))
|
||||||
|
.template unconditionalConvertTo<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Helper method to unpack the tuple into a vector.
|
||||||
|
template <typename T, std::size_t... Is>
|
||||||
|
std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const {
|
||||||
|
return {Matcher<T>(std::get<Is>(Params))...};
|
||||||
|
}
|
||||||
|
|
||||||
|
const DynTypedMatcher::VariadicOperator Op;
|
||||||
|
std::tuple<Ps...> Params;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Overloaded function object to generate VariadicOperatorMatcher
|
||||||
|
/// objects from arbitrary matchers.
|
||||||
|
template <unsigned MinCount, unsigned MaxCount>
|
||||||
|
struct VariadicOperatorMatcherFunc {
|
||||||
|
DynTypedMatcher::VariadicOperator Op;
|
||||||
|
|
||||||
|
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)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename F, typename Tuple, std::size_t... I>
|
||||||
|
constexpr auto applyMatcherImpl(F &&f, Tuple &&args,
|
||||||
|
std::index_sequence<I...>) {
|
||||||
|
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F, typename Tuple>
|
||||||
|
constexpr auto applyMatcher(F &&f, Tuple &&args) {
|
||||||
|
return applyMatcherImpl(
|
||||||
|
std::forward<F>(f), std::forward<Tuple>(args),
|
||||||
|
std::make_index_sequence<
|
||||||
|
std::tuple_size<typename std::decay<Tuple>::type>::value>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool IsBaseOf, typename Head, typename Tail>
|
||||||
|
struct GetCladeImpl {
|
||||||
|
using Type = Head;
|
||||||
|
};
|
||||||
|
template <typename T, typename Head, typename Tail>
|
||||||
|
struct GetCladeImpl<T, false, Head, Tail>
|
||||||
|
: GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
|
||||||
|
typename Tail::head, typename Tail::tail> {};
|
||||||
|
|
||||||
|
template <typename T, typename... U>
|
||||||
|
struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
|
||||||
|
|
||||||
|
template <typename CladeType, typename... MatcherTypes>
|
||||||
|
struct MapAnyOfMatcherImpl {
|
||||||
|
|
||||||
|
template <typename... InnerMatchers>
|
||||||
|
BindableMatcher<CladeType>
|
||||||
|
operator()(InnerMatchers &&... InnerMatcher) const {
|
||||||
|
// TODO: Use std::apply from c++17
|
||||||
|
return VariadicAllOfMatcher<CladeType>()(applyMatcher(
|
||||||
|
internal::VariadicOperatorMatcherFunc<
|
||||||
|
0, std::numeric_limits<unsigned>::max()>{
|
||||||
|
internal::DynTypedMatcher::VO_AnyOf},
|
||||||
|
applyMatcher(
|
||||||
|
[&](auto... Matcher) {
|
||||||
|
return std::make_tuple(Matcher(
|
||||||
|
std::forward<decltype(InnerMatcher)>(InnerMatcher)...)...);
|
||||||
|
},
|
||||||
|
std::tuple<
|
||||||
|
VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... MatcherTypes>
|
||||||
|
using MapAnyOfMatcher =
|
||||||
|
MapAnyOfMatcherImpl<typename GetClade<MatcherTypes...>::Type,
|
||||||
|
MatcherTypes...>;
|
||||||
|
|
||||||
|
template <typename... MatcherTypes> struct MapAnyOfHelper {
|
||||||
|
using CladeType = typename GetClade<MatcherTypes...>::Type;
|
||||||
|
|
||||||
|
MapAnyOfMatcher<MatcherTypes...> with;
|
||||||
|
|
||||||
|
operator BindableMatcher<CladeType>() const { return with(); }
|
||||||
|
|
||||||
|
Matcher<CladeType> bind(StringRef ID) const { return with().bind(ID); }
|
||||||
|
};
|
||||||
|
|
||||||
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
|
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
|
||||||
typename T, typename ToTypes>
|
typename T, typename ToTypes>
|
||||||
class ArgumentAdaptingMatcherFuncAdaptor {
|
class ArgumentAdaptingMatcherFuncAdaptor {
|
||||||
|
@ -1327,51 +1553,6 @@ private:
|
||||||
const P2 Param2;
|
const P2 Param2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Matches any instance of the given NodeType.
|
|
||||||
///
|
|
||||||
/// This is useful when a matcher syntactically requires a child matcher,
|
|
||||||
/// but the context doesn't care. See for example: anything().
|
|
||||||
class TrueMatcher {
|
|
||||||
public:
|
|
||||||
using ReturnTypes = AllNodeBaseTypes;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
operator Matcher<T>() const {
|
|
||||||
return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
|
|
||||||
.template unconditionalConvertTo<T>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A Matcher that allows binding the node it matches to an id.
|
|
||||||
///
|
|
||||||
/// BindableMatcher provides a \a bind() method that allows binding the
|
|
||||||
/// matched node to an id if the match was successful.
|
|
||||||
template <typename T>
|
|
||||||
class BindableMatcher : public Matcher<T> {
|
|
||||||
public:
|
|
||||||
explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
|
|
||||||
explicit BindableMatcher(MatcherInterface<T> *Implementation)
|
|
||||||
: Matcher<T>(Implementation) {}
|
|
||||||
|
|
||||||
/// Returns a matcher that will bind the matched node on a match.
|
|
||||||
///
|
|
||||||
/// The returned matcher is equivalent to this matcher, but will
|
|
||||||
/// bind the matched node on a match.
|
|
||||||
Matcher<T> bind(StringRef ID) const {
|
|
||||||
return DynTypedMatcher(*this)
|
|
||||||
.tryBind(ID)
|
|
||||||
->template unconditionalConvertTo<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Same as Matcher<T>'s conversion operator, but enables binding on
|
|
||||||
/// the returned matcher.
|
|
||||||
operator DynTypedMatcher() const {
|
|
||||||
DynTypedMatcher Result = static_cast<const Matcher<T>&>(*this);
|
|
||||||
Result.setAllowBind(true);
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Matches nodes of type T that have child nodes of type ChildT for
|
/// Matches nodes of type T that have child nodes of type ChildT for
|
||||||
/// which a specified child matcher matches.
|
/// which a specified child matcher matches.
|
||||||
///
|
///
|
||||||
|
@ -1415,52 +1596,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// VariadicOperatorMatcher related types.
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
/// conversion operator.
|
|
||||||
template <typename... Ps> class VariadicOperatorMatcher {
|
|
||||||
public:
|
|
||||||
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
|
|
||||||
: Op(Op), Params(std::forward<Ps>(Params)...) {}
|
|
||||||
|
|
||||||
template <typename T> operator Matcher<T>() const {
|
|
||||||
return DynTypedMatcher::constructVariadic(
|
|
||||||
Op, ASTNodeKind::getFromNodeKind<T>(),
|
|
||||||
getMatchers<T>(std::index_sequence_for<Ps...>()))
|
|
||||||
.template unconditionalConvertTo<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Helper method to unpack the tuple into a vector.
|
|
||||||
template <typename T, std::size_t... Is>
|
|
||||||
std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const {
|
|
||||||
return {Matcher<T>(std::get<Is>(Params))...};
|
|
||||||
}
|
|
||||||
|
|
||||||
const DynTypedMatcher::VariadicOperator Op;
|
|
||||||
std::tuple<Ps...> Params;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Overloaded function object to generate VariadicOperatorMatcher
|
|
||||||
/// objects from arbitrary matchers.
|
|
||||||
template <unsigned MinCount, unsigned MaxCount>
|
|
||||||
struct VariadicOperatorMatcherFunc {
|
|
||||||
DynTypedMatcher::VariadicOperator Op;
|
|
||||||
|
|
||||||
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)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -1468,44 +1603,6 @@ inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
|
||||||
return Matcher<T>(*this);
|
return Matcher<T>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Matcher<T> that matches if all inner matchers match.
|
|
||||||
template<typename T>
|
|
||||||
BindableMatcher<T> makeAllOfComposite(
|
|
||||||
ArrayRef<const Matcher<T> *> InnerMatchers) {
|
|
||||||
// For the size() == 0 case, we return a "true" matcher.
|
|
||||||
if (InnerMatchers.empty()) {
|
|
||||||
return BindableMatcher<T>(TrueMatcher());
|
|
||||||
}
|
|
||||||
// For the size() == 1 case, we simply return that one matcher.
|
|
||||||
// No need to wrap it in a variadic operation.
|
|
||||||
if (InnerMatchers.size() == 1) {
|
|
||||||
return BindableMatcher<T>(*InnerMatchers[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
using PI = llvm::pointee_iterator<const Matcher<T> *const *>;
|
|
||||||
|
|
||||||
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
|
|
||||||
PI(InnerMatchers.end()));
|
|
||||||
return BindableMatcher<T>(
|
|
||||||
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
|
|
||||||
ASTNodeKind::getFromNodeKind<T>(),
|
|
||||||
std::move(DynMatchers))
|
|
||||||
.template unconditionalConvertTo<T>());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a Matcher<T> that matches if
|
|
||||||
/// T is dyn_cast'able into InnerT and all inner matchers match.
|
|
||||||
///
|
|
||||||
/// Returns BindableMatcher, as matchers that use dyn_cast have
|
|
||||||
/// the same object both to match on and to run submatchers on,
|
|
||||||
/// so there is no ambiguity with what gets bound.
|
|
||||||
template<typename T, typename InnerT>
|
|
||||||
BindableMatcher<T> makeDynCastAllOfComposite(
|
|
||||||
ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
|
|
||||||
return BindableMatcher<T>(
|
|
||||||
makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Matches nodes of type T that have at least one descendant node of
|
/// Matches nodes of type T that have at least one descendant node of
|
||||||
/// type DescendantT for which the given inner matcher matches.
|
/// type DescendantT for which the given inner matcher matches.
|
||||||
///
|
///
|
||||||
|
@ -1645,43 +1742,6 @@ inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
|
||||||
return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
|
return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
|
||||||
/// given matchers, if SourceT can be dynamically casted into TargetT.
|
|
||||||
///
|
|
||||||
/// For example:
|
|
||||||
/// const VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> record;
|
|
||||||
/// Creates a functor record(...) that creates a Matcher<Decl> given
|
|
||||||
/// a variable number of arguments of type Matcher<CXXRecordDecl>.
|
|
||||||
/// The returned matcher matches if the given Decl can by dynamically
|
|
||||||
/// casted to CXXRecordDecl and all given matchers match.
|
|
||||||
template <typename SourceT, typename TargetT>
|
|
||||||
class VariadicDynCastAllOfMatcher
|
|
||||||
: public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
|
|
||||||
makeDynCastAllOfComposite<SourceT, TargetT>> {
|
|
||||||
public:
|
|
||||||
VariadicDynCastAllOfMatcher() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
|
|
||||||
/// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T
|
|
||||||
/// nodes that are matched by all of the given matchers.
|
|
||||||
///
|
|
||||||
/// For example:
|
|
||||||
/// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
|
|
||||||
/// Creates a functor nestedNameSpecifier(...) that creates a
|
|
||||||
/// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type
|
|
||||||
/// \c Matcher<NestedNameSpecifier>.
|
|
||||||
/// The returned matcher matches if all given matchers match.
|
|
||||||
template <typename T>
|
|
||||||
class VariadicAllOfMatcher
|
|
||||||
: public VariadicFunction<BindableMatcher<T>, Matcher<T>,
|
|
||||||
makeAllOfComposite<T>> {
|
|
||||||
public:
|
|
||||||
VariadicAllOfMatcher() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Matches nodes of type \c TLoc for which the inner
|
/// 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>
|
||||||
|
@ -2180,68 +2240,6 @@ std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
|
||||||
llvm::Regex::RegexFlags Flags,
|
llvm::Regex::RegexFlags Flags,
|
||||||
StringRef MatcherID);
|
StringRef MatcherID);
|
||||||
|
|
||||||
template <typename F, typename Tuple, std::size_t... I>
|
|
||||||
constexpr auto applyMatcherImpl(F &&f, Tuple &&args,
|
|
||||||
std::index_sequence<I...>) {
|
|
||||||
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename F, typename Tuple>
|
|
||||||
constexpr auto applyMatcher(F &&f, Tuple &&args) {
|
|
||||||
return applyMatcherImpl(
|
|
||||||
std::forward<F>(f), std::forward<Tuple>(args),
|
|
||||||
std::make_index_sequence<
|
|
||||||
std::tuple_size<typename std::decay<Tuple>::type>::value>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, bool IsBaseOf, typename Head, typename Tail>
|
|
||||||
struct GetCladeImpl {
|
|
||||||
using Type = Head;
|
|
||||||
};
|
|
||||||
template <typename T, typename Head, typename Tail>
|
|
||||||
struct GetCladeImpl<T, false, Head, Tail>
|
|
||||||
: GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
|
|
||||||
typename Tail::head, typename Tail::tail> {};
|
|
||||||
|
|
||||||
template <typename T, typename... U>
|
|
||||||
struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
|
|
||||||
|
|
||||||
template <typename CladeType, typename... MatcherTypes>
|
|
||||||
struct MapAnyOfMatcherImpl {
|
|
||||||
|
|
||||||
template <typename... InnerMatchers>
|
|
||||||
BindableMatcher<CladeType>
|
|
||||||
operator()(InnerMatchers &&... InnerMatcher) const {
|
|
||||||
// TODO: Use std::apply from c++17
|
|
||||||
return VariadicAllOfMatcher<CladeType>()(applyMatcher(
|
|
||||||
internal::VariadicOperatorMatcherFunc<
|
|
||||||
0, std::numeric_limits<unsigned>::max()>{
|
|
||||||
internal::DynTypedMatcher::VO_AnyOf},
|
|
||||||
applyMatcher(
|
|
||||||
[&](auto... Matcher) {
|
|
||||||
return std::make_tuple(Matcher(
|
|
||||||
std::forward<decltype(InnerMatcher)>(InnerMatcher)...)...);
|
|
||||||
},
|
|
||||||
std::tuple<
|
|
||||||
VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... MatcherTypes>
|
|
||||||
using MapAnyOfMatcher =
|
|
||||||
MapAnyOfMatcherImpl<typename GetClade<MatcherTypes...>::Type,
|
|
||||||
MatcherTypes...>;
|
|
||||||
|
|
||||||
template <typename... MatcherTypes> struct MapAnyOfHelper {
|
|
||||||
using CladeType = typename GetClade<MatcherTypes...>::Type;
|
|
||||||
|
|
||||||
MapAnyOfMatcher<MatcherTypes...> with;
|
|
||||||
|
|
||||||
operator BindableMatcher<CladeType>() const { return with(); }
|
|
||||||
|
|
||||||
Matcher<CladeType> bind(StringRef ID) const { return with().bind(ID); }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
} // namespace ast_matchers
|
} // namespace ast_matchers
|
||||||
|
|
Loading…
Reference in New Issue