diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/ASTMatchers/Dynamic/VariantValue.h | 79 | ||||
| -rw-r--r-- | clang/lib/ASTMatchers/Dynamic/VariantValue.cpp | 134 |
2 files changed, 135 insertions, 78 deletions
diff --git a/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h b/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h index abfce078b3c..bee5d661db2 100644 --- a/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -21,6 +21,7 @@ #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/type_traits.h" @@ -44,13 +45,30 @@ using ast_matchers::internal::DynTypedMatcher; /// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if /// the underlying matcher(s) can unambiguously return a Matcher<T>. class VariantMatcher { + /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. + class MatcherOps { + public: + virtual ~MatcherOps(); + virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0; + }; + + /// \brief Payload interface to be specialized by each matcher type. + /// + /// It follows a similar interface as VariantMatcher itself. + class Payload : public RefCountedBaseVPTR { + public: + virtual ~Payload(); + virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const = 0; + virtual std::string getTypeAsString() const = 0; + virtual bool hasTypedMatcher(const MatcherOps &Ops) const = 0; + virtual const DynTypedMatcher * + getTypedMatcher(const MatcherOps &Ops) const = 0; + }; + public: /// \brief A null matcher. VariantMatcher(); - /// \brief Clones the matcher objects. - VariantMatcher(const VariantMatcher &Other); - /// \brief Clones the provided matcher. static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); @@ -60,46 +78,42 @@ public: static VariantMatcher PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers); - ~VariantMatcher(); - - /// \brief Copy the \c VariantMatcher, by making a copy of its representation. - VariantMatcher &operator=(const VariantMatcher &Other); - /// \brief Makes the matcher the "null" matcher. void reset(); /// \brief Whether the matcher is null. - bool isNull() const { return List.empty(); } + bool isNull() const { return !Value; } /// \brief Return a single matcher, if there is no ambiguity. /// - /// \returns True, and set Out to the matcher, if there is only one matcher. - /// False, if the underlying matcher is a polymorphic matcher with + /// \returns \c true, and set Out to the matcher, if there is only one + /// matcher. \c false, if the underlying matcher is a polymorphic matcher with /// more than one representation. bool getSingleMatcher(const DynTypedMatcher *&Out) const; - /// \brief Determines if any of the contained matchers can be converted - /// to \c Matcher<T>. + /// \brief Determines if the contained matcher can be converted to + /// \c Matcher<T>. /// - /// Returns true if one, and only one, of the contained matchers can be - /// converted to \c Matcher<T>. If there are more than one that can, the - /// result would be ambigous and false is returned. + /// For the Single case, it returns true if it can be converted to + /// \c Matcher<T>. + /// For the Polymorphic case, it returns true if one, and only one, of the + /// overloads can be converted to \c Matcher<T>. If there are more than one + /// that can, the result would be ambiguous and false is returned. template <class T> bool hasTypedMatcher() const { - return getTypedMatcher( - &ast_matchers::internal::Matcher<T>::canConstructFrom) != NULL; + if (Value) return Value->hasTypedMatcher(TypedMatcherOps<T>()); + return false; } - /// \brief Wrap the correct matcher as a \c Matcher<T>. + /// \brief Return this matcher as a \c Matcher<T>. /// - /// Selects the appropriate matcher from the wrapped matchers and returns it - /// as a \c Matcher<T>. + /// Handles the different types (Single, Polymorphic) accordingly. /// Asserts that \c hasTypedMatcher<T>() is true. template <class T> ast_matchers::internal::Matcher<T> getTypedMatcher() const { assert(hasTypedMatcher<T>()); - return ast_matchers::internal::Matcher<T>::constructFrom(*getTypedMatcher( - &ast_matchers::internal::Matcher<T>::canConstructFrom)); + return ast_matchers::internal::Matcher<T>::constructFrom( + *Value->getTypedMatcher(TypedMatcherOps<T>())); } /// \brief String representation of the type of the value. @@ -109,13 +123,20 @@ public: std::string getTypeAsString() const; private: - /// \brief Returns the matcher that passes the callback. - /// - /// Returns NULL if no matcher passes the test, or if more than one do. - const DynTypedMatcher * - getTypedMatcher(bool (*CanConstructCallback)(const DynTypedMatcher &)) const; + explicit VariantMatcher(Payload *Value) : Value(Value) {} + + class SinglePayload; + class PolymorphicPayload; + + template <typename T> + class TypedMatcherOps : public MatcherOps { + public: + virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const { + return ast_matchers::internal::Matcher<T>::canConstructFrom(Matcher); + } + }; - std::vector<const DynTypedMatcher *> List; + IntrusiveRefCntPtr<const Payload> Value; }; /// \brief Variant value class. diff --git a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp index a8fd7c6bbb9..87aca7da853 100644 --- a/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp +++ b/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -21,69 +21,105 @@ namespace clang { namespace ast_matchers { namespace dynamic { -VariantMatcher::VariantMatcher() : List() {} +VariantMatcher::MatcherOps::~MatcherOps() {} +VariantMatcher::Payload::~Payload() {} -VariantMatcher::VariantMatcher(const VariantMatcher& Other) { - *this = Other; -} +class VariantMatcher::SinglePayload : public VariantMatcher::Payload { +public: + SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher.clone()) {} -VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { - VariantMatcher Out; - Out.List.push_back(Matcher.clone()); - return Out; -} + virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const { + Out = Matcher.get(); + return true; + } -VariantMatcher -VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) { - VariantMatcher Out; - for (size_t i = 0, e = Matchers.size(); i != e; ++i) { - Out.List.push_back(Matchers[i]->clone()); + virtual std::string getTypeAsString() const { + return (Twine("Matcher<") + Matcher->getSupportedKind().asStringRef() + ">") + .str(); } - return Out; -} -VariantMatcher::~VariantMatcher() { - reset(); -} + virtual bool hasTypedMatcher(const MatcherOps &Ops) const { + return Ops.canConstructFrom(*Matcher); + } -VariantMatcher &VariantMatcher::operator=(const VariantMatcher &Other) { - if (this == &Other) return *this; - reset(); - for (size_t i = 0, e = Other.List.size(); i != e; ++i) { - List.push_back(Other.List[i]->clone()); + virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const { + assert(hasTypedMatcher(Ops)); + return Matcher.get(); } - return *this; -} -bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const { - if (List.size() != 1) return false; - Out = List[0]; - return true; -} +private: + OwningPtr<const DynTypedMatcher> Matcher; +}; -void VariantMatcher::reset() { - llvm::DeleteContainerPointers(List); -} +class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload { +public: + PolymorphicPayload(ArrayRef<const DynTypedMatcher *> MatchersIn) { + for (size_t i = 0, e = MatchersIn.size(); i != e; ++i) { + Matchers.push_back(MatchersIn[i]->clone()); + } + } -std::string VariantMatcher::getTypeAsString() const { - std::string Inner; - for (size_t I = 0, E = List.size(); I != E; ++I) { - if (I != 0) Inner += "|"; - Inner += List[I]->getSupportedKind().asStringRef(); + virtual ~PolymorphicPayload() { + llvm::DeleteContainerPointers(Matchers); } - return (Twine("Matcher<") + Inner + ">").str(); -} -const DynTypedMatcher *VariantMatcher::getTypedMatcher( - bool (*CanConstructCallback)(const DynTypedMatcher &)) const { - const DynTypedMatcher *Out = NULL; - for (size_t i = 0, e = List.size(); i != e; ++i) { - if (CanConstructCallback(*List[i])) { - if (Out) return NULL; - Out = List[i]; + virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const { + if (Matchers.size() != 1) + return false; + Out = Matchers[0]; + return true; + } + + virtual std::string getTypeAsString() const { + std::string Inner; + for (size_t i = 0, e = Matchers.size(); i != e; ++i) { + if (i != 0) + Inner += "|"; + Inner += Matchers[i]->getSupportedKind().asStringRef(); } + return (Twine("Matcher<") + Inner + ">").str(); + } + + virtual bool hasTypedMatcher(const MatcherOps &Ops) const { + return getTypedMatcher(Ops) != NULL; } - return Out; + + virtual const DynTypedMatcher *getTypedMatcher(const MatcherOps &Ops) const { + const DynTypedMatcher* Found = NULL; + for (size_t i = 0, e = Matchers.size(); i != e; ++i) { + if (Ops.canConstructFrom(*Matchers[i])) { + if (Found) return NULL; + Found = Matchers[i]; + } + } + return Found; + } + +private: + std::vector<const DynTypedMatcher *> Matchers; +}; + +VariantMatcher::VariantMatcher() {} + +VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) { + return VariantMatcher(new SinglePayload(Matcher)); +} + +VariantMatcher +VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) { + return VariantMatcher(new PolymorphicPayload(Matchers)); +} + +bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const { + if (Value) return Value->getSingleMatcher(Out); + return false; +} + +void VariantMatcher::reset() { Value.reset(); } + +std::string VariantMatcher::getTypeAsString() const { + if (Value) return Value->getTypeAsString(); + return "<Nothing>"; } VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) { |

