diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/ASTMatchers/ASTMatchersInternal.h | 51 | ||||
-rw-r--r-- | clang/include/clang/ASTMatchers/Dynamic/VariantValue.h | 91 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 11 | ||||
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/VariantValue.cpp | 44 |
4 files changed, 126 insertions, 71 deletions
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 7eacf23b44d..86ba219c07a 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -342,6 +342,17 @@ public: /// This version enables \c tryBind() on the \c DynTypedMatcher. template <typename T> inline DynTypedMatcher(const BindableMatcher<T> &M); + /// \brief Construct from a variadic function. + typedef bool (*VariadicOperatorFunction)( + const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); + static DynTypedMatcher + constructVariadic(VariadicOperatorFunction Func, + ArrayRef<DynTypedMatcher> InnerMatchers) { + assert(InnerMatchers.size() > 0 && "Array must not be empty."); + return DynTypedMatcher(new VariadicStorage(Func, InnerMatchers)); + } + /// \brief Returns true if the matcher matches the given \c DynNode. bool matches(const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { @@ -372,9 +383,9 @@ public: /// This method verifies that the underlying matcher in \c Other can process /// nodes of types T. template <typename T> bool canConvertTo() const { - return getSupportedKind().isBaseOf( - ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); + return canConvertTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); } + bool canConvertTo(ast_type_traits::ASTNodeKind To) const; /// \brief Construct a \c Matcher<T> interface around the dynamic matcher. /// @@ -416,9 +427,35 @@ private: const uint64_t ID; }; + class VariadicStorage : public MatcherStorage { + public: + VariadicStorage(VariadicOperatorFunction Func, + ArrayRef<DynTypedMatcher> InnerMatchers) + : MatcherStorage(InnerMatchers[0].getSupportedKind(), + reinterpret_cast<uint64_t>(this)), + Func(Func), InnerMatchers(InnerMatchers) {} + + bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { + return Func(DynNode, Finder, Builder, InnerMatchers); + } + + llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const override { + return llvm::None; + } + + private: + VariadicOperatorFunction Func; + std::vector<DynTypedMatcher> InnerMatchers; + }; + /// \brief Typed implementation of \c MatcherStorage. template <typename T> class TypedMatcherStorage; + /// \brief Internal constructor for \c constructVariadic. + DynTypedMatcher(MatcherStorage *Storage) : Storage(Storage) {} + IntrusiveRefCntPtr<const MatcherStorage> Storage; }; @@ -460,16 +497,8 @@ inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M) /// \brief Specialization of the conversion functions for QualType. /// -/// These specializations provide the Matcher<Type>->Matcher<QualType> +/// This specialization provides the Matcher<Type>->Matcher<QualType> /// conversion that the static API does. -template <> inline bool DynTypedMatcher::canConvertTo<QualType>() const { - const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind(); - return SourceKind.isSame( - ast_type_traits::ASTNodeKind::getFromNodeKind<Type>()) || - SourceKind.isSame( - ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>()); -} - template <> inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const { assert(canConvertTo<QualType>()); diff --git a/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h b/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h index 0765aba4716..cf805c685f7 100644 --- a/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -93,13 +93,25 @@ class VariantMatcher { /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. class MatcherOps { public: - virtual ~MatcherOps(); - virtual bool canConstructFrom(const DynTypedMatcher &Matcher, - bool &IsExactMatch) const = 0; - virtual void constructFrom(const DynTypedMatcher &Matcher) = 0; - virtual void constructVariadicOperator( + MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {} + + bool canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const; + + /// \brief Convert \p Matcher the destination type and return it as a new + /// DynTypedMatcher. + virtual DynTypedMatcher + convertMatcher(const DynTypedMatcher &Matcher) const = 0; + + /// \brief Constructs a variadic typed matcher from \p InnerMatchers. + /// Will try to convert each inner matcher to the destination type and + /// return llvm::None if it fails to do so. + llvm::Optional<DynTypedMatcher> constructVariadicOperator( ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> InnerMatchers) = 0; + ArrayRef<VariantMatcher> InnerMatchers) const; + + private: + ast_type_traits::ASTNodeKind NodeKind; }; /// \brief Payload interface to be specialized by each matcher type. @@ -110,7 +122,8 @@ class VariantMatcher { virtual ~Payload(); virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; virtual std::string getTypeAsString() const = 0; - virtual void makeTypedMatcher(MatcherOps &Ops) const = 0; + virtual llvm::Optional<DynTypedMatcher> + getTypedMatcher(const MatcherOps &Ops) const = 0; virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, unsigned *Specificity) const = 0; }; @@ -158,9 +171,8 @@ public: /// that can, the result would be ambiguous and false is returned. template <class T> bool hasTypedMatcher() const { - TypedMatcherOps<T> Ops; - if (Value) Value->makeTypedMatcher(Ops); - return Ops.hasMatcher(); + if (!Value) return false; + return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); } /// \brief Determines if the contained matcher can be converted to \p Kind. @@ -182,10 +194,9 @@ public: /// Asserts that \c hasTypedMatcher<T>() is true. template <class T> ast_matchers::internal::Matcher<T> getTypedMatcher() const { - TypedMatcherOps<T> Ops; - Value->makeTypedMatcher(Ops); - assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false"); - return Ops.matcher(); + assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false"); + return Value->getTypedMatcher(TypedMatcherOps<T>()) + ->template convertTo<T>(); } /// \brief String representation of the type of the value. @@ -197,51 +208,25 @@ public: private: explicit VariantMatcher(Payload *Value) : Value(Value) {} + template <typename T> struct TypedMatcherOps; + class SinglePayload; class PolymorphicPayload; class VariadicOpPayload; - template <typename T> - class TypedMatcherOps : public MatcherOps { - public: - typedef ast_matchers::internal::Matcher<T> MatcherT; - - virtual bool canConstructFrom(const DynTypedMatcher &Matcher, - bool &IsExactMatch) const { - IsExactMatch = Matcher.getSupportedKind().isSame( - ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); - return Matcher.canConvertTo<T>(); - } - - virtual void constructFrom(const DynTypedMatcher& Matcher) { - Out.reset(new MatcherT(Matcher.convertTo<T>())); - } - - virtual void constructVariadicOperator( - ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> InnerMatchers) { - std::vector<DynTypedMatcher> DynMatchers; - for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { - // Abort if any of the inner matchers can't be converted to - // Matcher<T>. - if (!InnerMatchers[i].hasTypedMatcher<T>()) { - return; - } - DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>()); - } - Out.reset(new MatcherT( - new ast_matchers::internal::VariadicOperatorMatcherInterface<T>( - Func, DynMatchers))); - } - - bool hasMatcher() const { return Out.get() != nullptr; } - const MatcherT &matcher() const { return *Out; } + IntrusiveRefCntPtr<const Payload> Value; +}; - private: - std::unique_ptr<MatcherT> Out; - }; +template <typename T> +struct VariantMatcher::TypedMatcherOps : VariantMatcher::MatcherOps { + TypedMatcherOps() + : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {} + typedef ast_matchers::internal::Matcher<T> MatcherT; - IntrusiveRefCntPtr<const Payload> Value; + DynTypedMatcher + convertMatcher(const DynTypedMatcher &Matcher) const override { + return DynTypedMatcher(Matcher.convertTo<T>()); + } }; /// \brief Variant value class. diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index e501ee64f7e..b95004a6d43 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -26,6 +26,17 @@ void BoundNodesTreeBuilder::visitMatches(Visitor *ResultVisitor) { } } +bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const { + const auto From = getSupportedKind(); + auto QualKind = ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>(); + auto TypeKind = ast_type_traits::ASTNodeKind::getFromNodeKind<Type>(); + /// Mimic the implicit conversions of Matcher<>. + /// - From Matcher<Type> to Matcher<QualType> + if (From.isSame(TypeKind) && To.isSame(QualKind)) return true; + /// - From Matcher<Base> to Matcher<Derived> + return From.isBaseOf(To); +} + DynTypedMatcher::MatcherStorage::~MatcherStorage() {} void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) { diff --git a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp index 57c7b80d361..3d14157fcab 100644 --- a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -49,7 +49,32 @@ bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const { return true; } -VariantMatcher::MatcherOps::~MatcherOps() {} +bool +VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const { + IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind); + return Matcher.canConvertTo(NodeKind); +} + +llvm::Optional<DynTypedMatcher> +VariantMatcher::MatcherOps::constructVariadicOperator( + ast_matchers::internal::VariadicOperatorFunction Func, + ArrayRef<VariantMatcher> InnerMatchers) const { + std::vector<DynTypedMatcher> DynMatchers; + for (const auto &InnerMatcher : InnerMatchers) { + // Abort if any of the inner matchers can't be converted to + // Matcher<T>. + if (!InnerMatcher.Value) + return llvm::None; + llvm::Optional<DynTypedMatcher> Inner = + InnerMatcher.Value->getTypedMatcher(*this); + if (!Inner) + return llvm::None; + DynMatchers.push_back(*Inner); + } + return DynTypedMatcher::constructVariadic(Func, DynMatchers); +} + VariantMatcher::Payload::~Payload() {} class VariantMatcher::SinglePayload : public VariantMatcher::Payload { @@ -65,10 +90,12 @@ public: .str(); } - void makeTypedMatcher(MatcherOps &Ops) const override { + llvm::Optional<DynTypedMatcher> + getTypedMatcher(const MatcherOps &Ops) const override { bool Ignore; if (Ops.canConstructFrom(Matcher, Ignore)) - Ops.constructFrom(Matcher); + return Matcher; + return llvm::None; } bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, @@ -104,7 +131,8 @@ public: return (Twine("Matcher<") + Inner + ">").str(); } - void makeTypedMatcher(MatcherOps &Ops) const override { + llvm::Optional<DynTypedMatcher> + getTypedMatcher(const MatcherOps &Ops) const override { bool FoundIsExact = false; const DynTypedMatcher *Found = nullptr; int NumFound = 0; @@ -124,7 +152,8 @@ public: } // We only succeed if we found exactly one, or if we found an exact match. if (Found && (FoundIsExact || NumFound == 1)) - Ops.constructFrom(*Found); + return *Found; + return llvm::None; } bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, @@ -165,8 +194,9 @@ public: return Inner; } - void makeTypedMatcher(MatcherOps &Ops) const override { - Ops.constructVariadicOperator(Func, Args); + llvm::Optional<DynTypedMatcher> + getTypedMatcher(const MatcherOps &Ops) const override { + return Ops.constructVariadicOperator(Func, Args); } bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, |