r195466 - Add support for the 'unless' matcher in the dynamic layer.
Samuel Benzaquen
sbenza at google.com
Fri Nov 22 06:41:48 PST 2013
Author: sbenza
Date: Fri Nov 22 08:41:48 2013
New Revision: 195466
URL: http://llvm.org/viewvc/llvm-project?rev=195466&view=rev
Log:
Add support for the 'unless' matcher in the dynamic layer.
Summary: Add support for the 'unless' matcher in the dynamic layer.
Reviewers: klimek
CC: cfe-commits, revane, klimek
Differential Revision: http://llvm-reviews.chandlerc.com/D2247
Modified:
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp
cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=195466&r1=195465&r2=195466&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Fri Nov 22 08:41:48 2013
@@ -1317,21 +1317,21 @@ const internal::VariadicAllOfMatcher<Typ
/// \c b.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc eachOf = {
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = {
internal::EachOfVariadicOperator
};
/// \brief Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc anyOf = {
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = {
internal::AnyOfVariadicOperator
};
/// \brief Matches if all given matchers match.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc allOf = {
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
internal::AllOfVariadicOperator
};
@@ -1671,12 +1671,9 @@ const internal::ArgumentAdaptingMatcherF
/// \endcode
///
/// Usable as: Any Matcher
-template <typename M>
-internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M>
-unless(const M &InnerMatcher) {
- return internal::PolymorphicMatcherWithParam1<
- internal::NotMatcher, M>(InnerMatcher);
-}
+const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
+ internal::NotUnaryOperator
+};
/// \brief Matches a node if the declaration associated with that node
/// matches the given matcher.
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=195466&r1=195465&r2=195466&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Fri Nov 22 08:41:48 2013
@@ -1098,38 +1098,6 @@ private:
const Matcher<ChildT> ChildMatcher;
};
-/// \brief Matches nodes of type T if the given Matcher<T> does not match.
-///
-/// Type argument MatcherT is required by PolymorphicMatcherWithParam1
-/// but not actually used. It will always be instantiated with a type
-/// convertible to Matcher<T>.
-template <typename T, typename MatcherT>
-class NotMatcher : public MatcherInterface<T> {
-public:
- explicit NotMatcher(const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
-
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- // The 'unless' matcher will always discard the result:
- // If the inner matcher doesn't match, unless returns true,
- // but the inner matcher cannot have bound anything.
- // If the inner matcher matches, the result is false, and
- // any possible binding will be discarded.
- // We still need to hand in all the bound nodes up to this
- // point so the inner matcher can depend on bound nodes,
- // and we need to actively discard the bound nodes, otherwise
- // the inner matcher will reset the bound nodes if it doesn't
- // match, but this would be inversed by 'unless'.
- BoundNodesTreeBuilder Discard(*Builder);
- return !InnerMatcher.matches(Node, Finder, &Discard);
- }
-
-private:
- const Matcher<T> InnerMatcher;
-};
-
/// \brief VariadicOperatorMatcher related types.
/// @{
@@ -1167,14 +1135,14 @@ struct VariadicOperatorNoArg {};
/// 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,
+template <typename P1, typename P2 = VariadicOperatorNoArg,
typename P3 = VariadicOperatorNoArg,
typename P4 = VariadicOperatorNoArg,
typename P5 = VariadicOperatorNoArg>
class VariadicOperatorMatcher {
public:
VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1,
- const P2 &Param2,
+ const P2 &Param2 = VariadicOperatorNoArg(),
const P3 &Param3 = VariadicOperatorNoArg(),
const P4 &Param4 = VariadicOperatorNoArg(),
const P5 &Param5 = VariadicOperatorNoArg())
@@ -1183,7 +1151,6 @@ public:
template <typename T> operator Matcher<T>() const {
std::vector<DynTypedMatcher> Matchers;
-
addMatcher<T>(Param1, Matchers);
addMatcher<T>(Param2, Matchers);
addMatcher<T>(Param3, Matchers);
@@ -1215,26 +1182,38 @@ private:
/// \brief Overloaded function object to generate VariadicOperatorMatcher
/// objects from arbitrary matchers.
///
-/// It supports 2-5 argument overloaded operator(). More can be added if needed.
+/// It supports 1-5 argument overloaded operator(). More can be added if needed.
+template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
VariadicOperatorFunction Func;
+ template <unsigned Count, typename T>
+ struct EnableIfValidArity
+ : public llvm::enable_if_c<MinCount <= Count &&Count <= MaxCount, T> {};
+
+ template <typename M1>
+ typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type
+ operator()(const M1 &P1) const {
+ return VariadicOperatorMatcher<M1>(Func, P1);
+ }
template <typename M1, typename M2>
- VariadicOperatorMatcher<M1, M2> operator()(const M1 &P1, const M2 &P2) const {
+ typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type
+ operator()(const M1 &P1, const M2 &P2) const {
return VariadicOperatorMatcher<M1, M2>(Func, P1, P2);
}
template <typename M1, typename M2, typename M3>
- VariadicOperatorMatcher<M1, M2, M3> operator()(const M1 &P1, const M2 &P2,
- const M3 &P3) const {
+ typename EnableIfValidArity<3, VariadicOperatorMatcher<M1, M2, M3> >::type
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3) const {
return VariadicOperatorMatcher<M1, M2, M3>(Func, P1, P2, P3);
}
template <typename M1, typename M2, typename M3, typename M4>
- VariadicOperatorMatcher<M1, M2, M3, 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>(Func, P1, P2, P3, P4);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5>
- VariadicOperatorMatcher<M1, M2, M3, M4, 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>(Func, P1, P2, P3, P4,
@@ -1244,6 +1223,13 @@ struct VariadicOperatorMatcherFunc {
/// @}
+/// \brief Matches nodes that do not match the provided matcher.
+///
+/// Uses the variadic matcher interface, but fails if InnerMatchers.size()!=1.
+bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
+
/// \brief Matches nodes for which all provided matchers match.
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
ASTMatchFinder *Finder,
Modified: cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp?rev=195466&r1=195465&r2=195466&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp Fri Nov 22 08:41:48 2013
@@ -34,6 +34,26 @@ void BoundNodesTreeBuilder::addMatch(con
}
}
+bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers) {
+ if (InnerMatchers.size() != 1)
+ return false;
+
+ // The 'unless' matcher will always discard the result:
+ // If the inner matcher doesn't match, unless returns true,
+ // but the inner matcher cannot have bound anything.
+ // If the inner matcher matches, the result is false, and
+ // any possible binding will be discarded.
+ // We still need to hand in all the bound nodes up to this
+ // point so the inner matcher can depend on bound nodes,
+ // and we need to actively discard the bound nodes, otherwise
+ // the inner matcher will reset the bound nodes if it doesn't
+ // match, but this would be inversed by 'unless'.
+ BoundNodesTreeBuilder Discard(*Builder);
+ return !InnerMatchers[0].matches(DynNode, Finder, &Discard);
+}
+
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h?rev=195466&r1=195465&r2=195466&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Marshallers.h Fri Nov 22 08:41:48 2013
@@ -347,12 +347,22 @@ private:
class VariadicOperatorMatcherCreateCallback : public MatcherCreateCallback {
public:
typedef ast_matchers::internal::VariadicOperatorFunction VarFunc;
- VariadicOperatorMatcherCreateCallback(VarFunc Func, StringRef MatcherName)
- : Func(Func), MatcherName(MatcherName) {}
+ VariadicOperatorMatcherCreateCallback(unsigned MinCount, unsigned MaxCount,
+ VarFunc Func, StringRef MatcherName)
+ : MinCount(MinCount), MaxCount(MaxCount), Func(Func),
+ MatcherName(MatcherName) {}
virtual VariantMatcher run(const SourceRange &NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) const {
+ if (Args.size() < MinCount || MaxCount < Args.size()) {
+ const std::string MaxStr =
+ (MaxCount == UINT_MAX ? "" : Twine(MaxCount)).str();
+ Error->addError(NameRange, Error->ET_RegistryWrongArgCount)
+ << ("(" + Twine(MinCount) + ", " + MaxStr + ")") << Args.size();
+ return VariantMatcher();
+ }
+
std::vector<VariantMatcher> InnerArgs;
for (size_t i = 0, e = Args.size(); i != e; ++i) {
const ParserValue &Arg = Args[i];
@@ -368,6 +378,8 @@ public:
}
private:
+ const unsigned MinCount;
+ const unsigned MaxCount;
const VarFunc Func;
const StringRef MatcherName;
};
@@ -439,10 +451,13 @@ AdaptativeOverloadCollector<ArgumentAdap
}
/// \brief Variadic operator overload.
-MatcherCreateCallback *makeMatcherAutoMarshall(
- ast_matchers::internal::VariadicOperatorMatcherFunc Func,
- StringRef MatcherName) {
- return new VariadicOperatorMatcherCreateCallback(Func.Func, MatcherName);
+template <unsigned MinCount, unsigned MaxCount>
+MatcherCreateCallback *
+makeMatcherAutoMarshall(ast_matchers::internal::VariadicOperatorMatcherFunc<
+ MinCount, MaxCount> Func,
+ StringRef MatcherName) {
+ return new VariadicOperatorMatcherCreateCallback(MinCount, MaxCount,
+ Func.Func, MatcherName);
}
} // namespace internal
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=195466&r1=195465&r2=195466&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Fri Nov 22 08:41:48 2013
@@ -76,7 +76,6 @@ RegistryMaps::RegistryMaps() {
// ofKind
//
// Polymorphic + argument overload:
- // unless
// findAll
//
// Other:
@@ -285,6 +284,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(typedefType);
REGISTER_MATCHER(unaryExprOrTypeTraitExpr);
REGISTER_MATCHER(unaryOperator);
+ REGISTER_MATCHER(unless);
REGISTER_MATCHER(userDefinedLiteral);
REGISTER_MATCHER(usingDecl);
REGISTER_MATCHER(varDecl);
Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=195466&r1=195465&r2=195466&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Fri Nov 22 08:41:48 2013
@@ -295,6 +295,17 @@ TEST_F(RegistryTest, VariadicOp) {
EXPECT_FALSE(matches("int i = 0;", D));
EXPECT_TRUE(matches("class Bar{};", D));
EXPECT_FALSE(matches("class OtherBar{};", D));
+
+ D = constructMatcher(
+ "recordDecl",
+ constructMatcher(
+ "unless",
+ constructMatcher("namedDecl",
+ constructMatcher("hasName", std::string("Bar")))))
+ .getTypedMatcher<Decl>();
+
+ EXPECT_FALSE(matches("class Bar{};", D));
+ EXPECT_TRUE(matches("class OtherBar{};", D));
}
TEST_F(RegistryTest, Errors) {
@@ -307,6 +318,15 @@ TEST_F(RegistryTest, Errors) {
EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Error->toString());
+ Error.reset(new Diagnostics());
+ EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
+ EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
+ Error->toString());
+ Error.reset(new Diagnostics());
+ EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(),
+ Error.get()).isNull());
+ EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
+ Error->toString());
// Bad argument type
Error.reset(new Diagnostics());
@@ -324,7 +344,8 @@ TEST_F(RegistryTest, Errors) {
// Bad argument type with variadic.
Error.reset(new Diagnostics());
- EXPECT_TRUE(constructMatcher("anyOf", std::string(), Error.get()).isNull());
+ EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
+ Error.get()).isNull());
EXPECT_EQ(
"Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
Error->toString());
More information about the cfe-commits
mailing list