diff options
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchersInternal.h')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersInternal.h | 390 |
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; }; |