/// \brief Matches \c TypeLocs in the clang AST.
const internal::VariadicDynCastAllOfMatcher<TypeLoc, TypeLoc> typeLoc;
+/// \brief Matches if any of the given matchers matches.
+///
+/// Unlike \c anyOf, \c eachOf will generate a match result for each
+/// matching submatcher.
+///
+/// For example, in:
+/// \code
+/// class A { int a; int b; };
+/// \endcode
+/// The matcher:
+/// \code
+/// recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+/// has(fieldDecl(hasName("b")).bind("v"))))
+/// \endcode
+/// will generate two results binding "v", the first of which binds
+/// the field declaration of \c a, the second the field declaration of
+/// \c b.
+///
+/// Usable as: Any Matcher
+template <typename M1, typename M2>
+internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, M2>
+eachOf(const M1 &P1, const M2 &P2) {
+ return internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1,
+ M2>(P1, P2);
+}
+
/// \brief Various overloads for the anyOf matcher.
/// @{
const Matcher<T> InnerMatcher2;
};
+/// \brief Matches nodes of type T for which at least one of the two provided
+/// matchers matches.
+///
+/// Type arguments MatcherT1 and MatcherT2 are
+/// required by PolymorphicMatcherWithParam2 but not actually
+/// used. They will always be instantiated with types convertible to
+/// Matcher<T>.
+template <typename T, typename MatcherT1, typename MatcherT2>
+class EachOfMatcher : public MatcherInterface<T> {
+public:
+ EachOfMatcher(const Matcher<T> &InnerMatcher1,
+ const Matcher<T> &InnerMatcher2)
+ : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {
+ }
+
+ virtual bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ BoundNodesTreeBuilder Builder1;
+ bool Matched1 = InnerMatcher1.matches(Node, Finder, &Builder1);
+ if (Matched1)
+ Builder->addMatch(Builder1.build());
+
+ BoundNodesTreeBuilder Builder2;
+ bool Matched2 = InnerMatcher2.matches(Node, Finder, &Builder2);
+ if (Matched2)
+ Builder->addMatch(Builder2.build());
+
+ return Matched1 || Matched2;
+ }
+
+private:
+ const Matcher<T> InnerMatcher1;
+ const Matcher<T> InnerMatcher2;
+};
+
/// \brief Matches nodes of type T for which at least one of the two provided
/// matchers matches.
///
class AnyOfMatcher : public MatcherInterface<T> {
public:
AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2)
- : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {}
+ : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
virtual bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
return InnerMatcher1.matches(Node, Finder, Builder) ||
- InnertMatcher2.matches(Node, Finder, Builder);
+ InnerMatcher2.matches(Node, Finder, Builder);
}
private:
const Matcher<T> InnerMatcher1;
- const Matcher<T> InnertMatcher2;
+ const Matcher<T> InnerMatcher2;
};
/// \brief Creates a Matcher<T> that matches if all inner matchers match.
new VerifyIdIsBoundTo<FunctionDecl>("decl", 1)));
}
+TEST(EachOf, TriggersForEachMatch) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class A { int a; int b; };",
+ recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+ has(fieldDecl(hasName("b")).bind("v")))),
+ new VerifyIdIsBoundTo<FieldDecl>("v", 2)));
+}
+
+TEST(EachOf, BehavesLikeAnyOfUnlessBothMatch) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class A { int a; int c; };",
+ recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+ has(fieldDecl(hasName("b")).bind("v")))),
+ new VerifyIdIsBoundTo<FieldDecl>("v", 1)));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class A { int c; int b; };",
+ recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+ has(fieldDecl(hasName("b")).bind("v")))),
+ new VerifyIdIsBoundTo<FieldDecl>("v", 1)));
+ EXPECT_TRUE(notMatches(
+ "class A { int c; int d; };",
+ recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+ has(fieldDecl(hasName("b")).bind("v"))))));
+}
TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
// Make sure that we can both match the class by name (::X) and by the type