diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/ASTMatchers/ASTMatchers.h | 15 | ||||
-rw-r--r-- | clang/include/clang/ASTMatchers/ASTMatchersInternal.h | 68 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 20 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Marshallers.h | 27 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Registry.cpp | 2 | ||||
-rw-r--r-- | clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp | 23 |
6 files changed, 97 insertions, 58 deletions
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 0a3157dde81..31571a66b58 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1317,21 +1317,21 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; /// \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::ArgumentAdaptingMatcherFunc< /// \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. diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index e1f30151fd3..bcc26db5de9 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -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, diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index d15eb54002f..47b8b6d2f27 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -34,6 +34,26 @@ void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) { } } +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, diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index ae0c300d094..2f9db9c56b7 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -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<ArgumentAdapterT, FromTypes, ToTypes>::collect( } /// \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 diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 70e956e6546..a19cdc06e9f 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -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); diff --git a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index e716484e207..dad9499ad4b 100644 --- a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -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()); |