Summary: This resubmits r193100, plus a fix for a breakage with MSVC.
Reviewers: klimek, rnk
CC: cfe-commits, revane
Differential Revision: http://llvm-reviews.chandlerc.com/D2005
llvm-svn: 193613
private:
/// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
/// when it matches.
- std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> >
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> >
MatcherCallbackPairs;
/// \brief Called when parsing is done.
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
#include "clang/AST/ASTTypeTraits.h"
-#include "clang/AST/DeclCXX.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtCXX.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/AST/Type.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/VariadicFunction.h"
#include "llvm/Support/type_traits.h"
#include <map>
}
};
-/// \brief Base class for all matchers that works on a \c DynTypedNode.
-///
-/// Matcher implementations will check whether the \c DynTypedNode is
-/// convertible into the respecitve types and then do the actual match
-/// on the actual node, or return false if it is not convertible.
-class DynTypedMatcher {
-public:
- virtual ~DynTypedMatcher();
-
- /// \brief Returns true if the matcher matches the given \c DynNode.
- virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const = 0;
-
- /// \brief Makes a copy of this matcher object.
- virtual DynTypedMatcher *clone() const = 0;
-
- /// \brief Returns a unique ID for the matcher.
- virtual uint64_t getID() const = 0;
-
- /// \brief Bind the specified \p ID to the matcher.
- /// \return A new matcher with the \p ID bound to it if this matcher supports
- /// binding. Otherwise, returns NULL. Returns NULL by default.
- virtual DynTypedMatcher* tryBind(StringRef ID) const;
-
- /// \brief Returns the type this matcher works on.
- ///
- /// \c matches() will always return false unless the node passed is of this
- /// or a derived type.
- virtual ast_type_traits::ASTNodeKind getSupportedKind() const = 0;
-};
-
/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
/// operator rather than a type hierarchy to be able to templatize the
/// type hierarchy instead of spelling it out.
template <typename T>
-class Matcher : public DynTypedMatcher {
+class Matcher {
public:
/// \brief Takes ownership of the provided implementation pointer.
explicit Matcher(MatcherInterface<T> *Implementation)
llvm::is_same<TypeT, Type>::value >::type* = 0)
: Implementation(new TypeToQualType<TypeT>(Other)) {}
- /// \brief Returns \c true if the passed DynTypedMatcher can be converted
- /// to a \c Matcher<T>.
- ///
- /// This method verifies that the underlying matcher in \c Other can process
- /// nodes of types T.
- static bool canConstructFrom(const DynTypedMatcher &Other) {
- return Other.getSupportedKind()
- .isBaseOf(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
- }
-
- /// \brief Construct a Matcher<T> interface around the dynamic matcher
- /// \c Other.
- ///
- /// This method asserts that canConstructFrom(Other) is \c true. Callers
- /// should call canConstructFrom(Other) first to make sure that Other is
- /// compatible with T.
- static Matcher<T> constructFrom(const DynTypedMatcher &Other) {
- assert(canConstructFrom(Other));
- return constructFromUnsafe(Other);
- }
-
- /// \brief Same as constructFrom(), but does not check that the underlying
- /// matcher can handle a value of T.
- ///
- /// If it is not compatible, then this matcher will never match anything.
- static Matcher<T> constructFromUnsafe(const DynTypedMatcher &Other) {
- return Matcher<T>(new WrappedMatcher(Other));
- }
-
/// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
bool matches(const T &Node,
ASTMatchFinder *Finder,
return reinterpret_cast<uint64_t>(Implementation.getPtr());
}
- /// \brief Returns the type this matcher works on.
- ast_type_traits::ASTNodeKind getSupportedKind() const {
- return ast_type_traits::ASTNodeKind::getFromNodeKind<T>();
- }
-
- /// \brief Returns whether the matcher matches on the given \c DynNode.
- virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- const T *Node = DynNode.get<T>();
- if (!Node) return false;
- return matches(*Node, Finder, Builder);
- }
-
- /// \brief Makes a copy of this matcher object.
- virtual Matcher<T> *clone() const { return new Matcher<T>(*this); }
-
/// \brief Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
///
const Matcher<Base> From;
};
- /// \brief Simple MatcherInterface<T> wrapper around a DynTypedMatcher.
- class WrappedMatcher : public MatcherInterface<T> {
- public:
- explicit WrappedMatcher(const DynTypedMatcher &Matcher)
- : Inner(Matcher.clone()) {}
- virtual ~WrappedMatcher() {}
-
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return Inner->matches(ast_type_traits::DynTypedNode::create(Node), Finder,
- Builder);
- }
-
- private:
- const OwningPtr<DynTypedMatcher> Inner;
- };
-
IntrusiveRefCntPtr< MatcherInterface<T> > Implementation;
}; // class Matcher
return Matcher<T>(Implementation);
}
+template <typename T> class BindableMatcher;
+
+/// \brief Matcher that works on a \c DynTypedNode.
+///
+/// It is constructed from a \c Matcher<T> object and redirects most calls to
+/// underlying matcher.
+/// It checks whether the \c DynTypedNode is convertible into the type of the
+/// underlying matcher and then do the actual match on the actual node, or
+/// return false if it is not convertible.
+class DynTypedMatcher {
+public:
+ /// \brief Construct from a \c Matcher<T>. Copies the matcher.
+ template <typename T> inline DynTypedMatcher(const Matcher<T> &M);
+
+ /// \brief Construct from a bindable \c Matcher<T>. Copies the matcher.
+ ///
+ /// This version enables \c tryBind() on the \c DynTypedMatcher.
+ template <typename T> inline DynTypedMatcher(const BindableMatcher<T> &M);
+
+ /// \brief Returns true if the matcher matches the given \c DynNode.
+ bool matches(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const {
+ return Storage->matches(DynNode, Finder, Builder);
+ }
+
+ /// \brief Bind the specified \p ID to the matcher.
+ /// \return A new matcher with the \p ID bound to it if this matcher supports
+ /// binding. Otherwise, returns an empty \c Optional<>.
+ llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const {
+ return Storage->tryBind(ID);
+ }
+
+ /// \brief Returns a unique \p ID for the matcher.
+ uint64_t getID() const { return Storage->getID(); }
+
+ /// \brief Returns the type this matcher works on.
+ ///
+ /// \c matches() will always return false unless the node passed is of this
+ /// or a derived type.
+ ast_type_traits::ASTNodeKind getSupportedKind() const {
+ return Storage->getSupportedKind();
+ }
+
+ /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
+ /// to a \c Matcher<T>.
+ ///
+ /// 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>());
+ }
+
+ /// \brief Construct a \c Matcher<T> interface around the dynamic matcher.
+ ///
+ /// This method asserts that \c canConvertTo() is \c true. Callers
+ /// should call \c canConvertTo() first to make sure that \c this is
+ /// compatible with T.
+ template <typename T> Matcher<T> convertTo() const {
+ assert(canConvertTo<T>());
+ return unconditionalConvertTo<T>();
+ }
+
+ /// \brief Same as \c convertTo(), but does not check that the underlying
+ /// matcher can handle a value of T.
+ ///
+ /// If it is not compatible, then this matcher will never match anything.
+ template <typename T> Matcher<T> unconditionalConvertTo() const {
+ return Matcher<T>(new WrappedMatcher<T>(*this));
+ }
+
+private:
+ class MatcherStorage : public RefCountedBaseVPTR {
+ public:
+ MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID)
+ : SupportedKind(SupportedKind), ID(ID) {}
+ virtual ~MatcherStorage();
+
+ virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const = 0;
+
+ virtual llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const = 0;
+
+ ast_type_traits::ASTNodeKind getSupportedKind() const {
+ return SupportedKind;
+ }
+
+ uint64_t getID() const { return ID; }
+
+ private:
+ const ast_type_traits::ASTNodeKind SupportedKind;
+ const uint64_t ID;
+ };
+
+ /// \brief Typed implementation of \c MatcherStorage.
+ template <typename T> class TypedMatcherStorage;
+
+ /// \brief Simple MatcherInterface<T> wrapper around a DynTypedMatcher.
+ template <typename T> class WrappedMatcher;
+
+ IntrusiveRefCntPtr<const MatcherStorage> Storage;
+};
+
+template <typename T>
+class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage {
+public:
+ TypedMatcherStorage(const Matcher<T> &Other, bool AllowBind)
+ : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ Other.getID()),
+ InnerMatcher(Other), AllowBind(AllowBind) {}
+
+ bool matches(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const
+ LLVM_OVERRIDE {
+ if (const T *Node = DynNode.get<T>()) {
+ return InnerMatcher.matches(*Node, Finder, Builder);
+ }
+ return false;
+ }
+
+ llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const LLVM_OVERRIDE {
+ if (!AllowBind)
+ return llvm::Optional<DynTypedMatcher>();
+ return DynTypedMatcher(BindableMatcher<T>(InnerMatcher).bind(ID));
+ }
+
+private:
+ const Matcher<T> InnerMatcher;
+ const bool AllowBind;
+};
+
+template <typename T>
+inline DynTypedMatcher::DynTypedMatcher(const Matcher<T> &M)
+ : Storage(new TypedMatcherStorage<T>(M, false)) {}
+
+template <typename T>
+inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M)
+ : Storage(new TypedMatcherStorage<T>(M, true)) {}
+
+template <typename T>
+class DynTypedMatcher::WrappedMatcher : public MatcherInterface<T> {
+public:
+ explicit WrappedMatcher(const DynTypedMatcher &Matcher) : Inner(Matcher) {}
+ virtual ~WrappedMatcher() {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return Inner.matches(ast_type_traits::DynTypedNode::create(Node), Finder,
+ Builder);
+ }
+
+private:
+ const DynTypedMatcher Inner;
+};
+
/// \brief Specialization of the conversion functions for QualType.
///
/// These specializations provide the Matcher<Type>->Matcher<QualType>
/// conversion that the static API does.
-template <>
-inline bool
-Matcher<QualType>::canConstructFrom(const DynTypedMatcher &Other) {
- ast_type_traits::ASTNodeKind SourceKind = Other.getSupportedKind();
- // We support implicit conversion from Matcher<Type> to Matcher<QualType>
+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(
}
template <>
-inline Matcher<QualType>
-Matcher<QualType>::constructFrom(const DynTypedMatcher &Other) {
- assert(canConstructFrom(Other));
- ast_type_traits::ASTNodeKind SourceKind = Other.getSupportedKind();
+inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
+ assert(canConvertTo<QualType>());
+ const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
if (SourceKind.isSame(
ast_type_traits::ASTNodeKind::getFromNodeKind<Type>())) {
// We support implicit conversion from Matcher<Type> to Matcher<QualType>
- return Matcher<Type>::constructFrom(Other);
+ return unconditionalConvertTo<Type>();
}
- return makeMatcher(new WrappedMatcher(Other));
+ return unconditionalConvertTo<QualType>();
}
/// \brief Finds the first node in a range that matches the given matcher.
Matcher<T> bind(StringRef ID) const {
return Matcher<T>(new IdMatcher<T>(ID, *this));
}
-
- /// \brief Makes a copy of this matcher object.
- virtual BindableMatcher<T>* clone() const {
- return new BindableMatcher<T>(*this);
- }
-
- /// \brief Bind the specified \c ID to the matcher.
- virtual Matcher<T>* tryBind(StringRef ID) const {
- return new Matcher<T>(bind(ID));
- }
};
/// \brief Matches nodes of type T that have child nodes of type ChildT for
/// matchers as an array of DynTypedMatcher.
typedef bool (*VariadicOperatorFunction)(
const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder,
- ArrayRef<const DynTypedMatcher *> InnerMatchers);
+ BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
/// \brief \c MatcherInterface<T> implementation for an variadic operator.
template <typename T>
ArrayRef<const Matcher<T> *> InputMatchers)
: Func(Func) {
for (size_t i = 0, e = InputMatchers.size(); i != e; ++i) {
- InnerMatchers.push_back(new Matcher<T>(*InputMatchers[i]));
+ InnerMatchers.push_back(*InputMatchers[i]);
}
}
- ~VariadicOperatorMatcherInterface() {
- llvm::DeleteContainerPointers(InnerMatchers);
- }
-
virtual bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder,
private:
const VariadicOperatorFunction Func;
- std::vector<const DynTypedMatcher *> InnerMatchers;
+ std::vector<DynTypedMatcher> InnerMatchers;
};
/// \brief "No argument" placeholder to use as template paratemers.
/// @}
/// \brief Matches nodes for which all provided matchers match.
-bool
-AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
- ArrayRef<const DynTypedMatcher *> InnerMatchers);
+bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
/// \brief Matches nodes for which at least one of the provided matchers
/// matches, but doesn't stop at the first match.
-bool
-EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
- ArrayRef<const DynTypedMatcher *> InnerMatchers);
+bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
/// \brief Matches nodes for which at least one of the provided matchers
/// matches.
-bool
-AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
- ArrayRef<const DynTypedMatcher *> InnerMatchers);
+bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
/// \brief Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
template<typename T, typename InnerT>
BindableMatcher<T> makeDynCastAllOfComposite(
ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return BindableMatcher<T>(
- Matcher<T>::constructFromUnsafe(makeAllOfComposite(InnerMatchers)));
+ return BindableMatcher<T>(DynTypedMatcher(makeAllOfComposite(InnerMatchers))
+ .unconditionalConvertTo<T>());
}
/// \brief Matches nodes of type T that have at least one descendant node of
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
///
/// \param MatcherCode The matcher expression to parse.
///
- /// \return The matcher object constructed, or NULL if an error occurred.
- // In that case, \c Error will contain a description of the error.
+ /// \return The matcher object constructed, or an empty Optional if an error
+ /// occurred.
+ /// In that case, \c Error will contain a description of the error.
/// The caller takes ownership of the DynTypedMatcher object returned.
- static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,
- Diagnostics *Error);
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error);
/// \brief Parse a matcher expression.
///
///
/// \param S The Sema instance that will help the parser
/// construct the matchers.
- /// \return The matcher object constructed by the processor, or NULL
- /// if an error occurred. In that case, \c Error will contain a
+ /// \return The matcher object constructed by the processor, or an empty
+ /// Optional if an error occurred. In that case, \c Error will contain a
/// description of the error.
/// The caller takes ownership of the DynTypedMatcher object returned.
- static DynTypedMatcher *parseMatcherExpression(StringRef MatcherCode,
- Sema *S,
- Diagnostics *Error);
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error);
/// \brief Parse an expression, creating matchers from the registry.
///
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/type_traits.h"
class Payload : public RefCountedBaseVPTR {
public:
virtual ~Payload();
- virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const = 0;
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
virtual std::string getTypeAsString() const = 0;
virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
};
/// \brief Clones the provided matchers.
///
/// They should be the result of a polymorphic matcher.
- static VariantMatcher
- PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers);
+ static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers);
/// \brief Creates a 'variadic' operator matcher.
///
/// \brief Return a single matcher, if there is no ambiguity.
///
- /// \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;
+ /// \returns the matcher, if there is only one matcher. An empty Optional, if
+ /// the underlying matcher is a polymorphic matcher with more than one
+ /// representation.
+ llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
/// \brief Determines if the contained matcher can be converted to
/// \c Matcher<T>.
typedef ast_matchers::internal::Matcher<T> MatcherT;
virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const {
- return MatcherT::canConstructFrom(Matcher);
+ return Matcher.canConvertTo<T>();
}
virtual void constructFrom(const DynTypedMatcher& Matcher) {
- Out.reset(new MatcherT(MatcherT::constructFrom(Matcher)));
+ Out.reset(new MatcherT(Matcher.convertTo<T>()));
}
virtual void constructVariadicOperator(
new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs))));
}
- std::for_each(InnerArgs, InnerArgs + NumArgs, llvm::deleter<MatcherT>);
+ for (size_t i = 0; i != NumArgs; ++i) {
+ delete InnerArgs[i];
+ }
delete[] InnerArgs;
}
class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
public ASTMatchFinder {
public:
- MatchASTVisitor(std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> > *MatcherCallbackPairs)
- : MatcherCallbackPairs(MatcherCallbackPairs),
- ActiveASTContext(NULL) {
- }
+ MatchASTVisitor(
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *
+ MatcherCallbackPairs)
+ : MatcherCallbackPairs(MatcherCallbackPairs), ActiveASTContext(NULL) {}
void onStartOfTranslationUnit() {
- for (std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> >::const_iterator
- I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
+ for (std::vector<std::pair<internal::DynTypedMatcher,
+ MatchCallback *> >::const_iterator
+ I = MatcherCallbackPairs->begin(),
+ E = MatcherCallbackPairs->end();
I != E; ++I) {
I->second->onStartOfTranslationUnit();
}
}
void onEndOfTranslationUnit() {
- for (std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> >::const_iterator
- I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
+ for (std::vector<std::pair<internal::DynTypedMatcher,
+ MatchCallback *> >::const_iterator
+ I = MatcherCallbackPairs->begin(),
+ E = MatcherCallbackPairs->end();
I != E; ++I) {
I->second->onEndOfTranslationUnit();
}
// Matches all registered matchers on the given node and calls the
// result callback for every node that matches.
void match(const ast_type_traits::DynTypedNode& Node) {
- for (std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> >::const_iterator
- I = MatcherCallbackPairs->begin(), E = MatcherCallbackPairs->end();
+ for (std::vector<std::pair<internal::DynTypedMatcher,
+ MatchCallback *> >::const_iterator
+ I = MatcherCallbackPairs->begin(),
+ E = MatcherCallbackPairs->end();
I != E; ++I) {
BoundNodesTreeBuilder Builder;
- if (I->first->matches(Node, this, &Builder)) {
+ if (I->first.matches(Node, this, &Builder)) {
MatchVisitor Visitor(ActiveASTContext, I->second);
Builder.visitMatches(&Visitor);
}
return false;
}
- std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> > *const MatcherCallbackPairs;
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *const
+ MatcherCallbackPairs;
ASTContext *ActiveASTContext;
// Maps a canonical type to its TypedefDecls.
class MatchASTConsumer : public ASTConsumer {
public:
MatchASTConsumer(
- std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> > *MatcherCallbackPairs,
- MatchFinder::ParsingDoneTestCallback *ParsingDone)
- : Visitor(MatcherCallbackPairs),
- ParsingDone(ParsingDone) {}
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > *
+ MatcherCallbackPairs,
+ MatchFinder::ParsingDoneTestCallback *ParsingDone)
+ : Visitor(MatcherCallbackPairs), ParsingDone(ParsingDone) {}
private:
virtual void HandleTranslationUnit(ASTContext &Context) {
MatchFinder::MatchFinder() : ParsingDone(NULL) {}
-MatchFinder::~MatchFinder() {
- for (std::vector<std::pair<const internal::DynTypedMatcher*,
- MatchCallback*> >::const_iterator
- It = MatcherCallbackPairs.begin(), End = MatcherCallbackPairs.end();
- It != End; ++It) {
- delete It->first;
- }
-}
+MatchFinder::~MatchFinder() {}
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new internal::Matcher<Decl>(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new internal::Matcher<QualType>(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new internal::Matcher<Stmt>(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new NestedNameSpecifierMatcher(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new NestedNameSpecifierLocMatcher(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action) {
- MatcherCallbackPairs.push_back(std::make_pair(
- new TypeLocMatcher(NodeMatch), Action));
+ MatcherCallbackPairs.push_back(std::make_pair(NodeMatch, Action));
}
ASTConsumer *MatchFinder::newASTConsumer() {
}
}
+DynTypedMatcher::MatcherStorage::~MatcherStorage() {}
+
void BoundNodesTreeBuilder::addMatch(const BoundNodesTreeBuilder &Other) {
for (unsigned i = 0, e = Other.Bindings.size(); i != e; ++i) {
Bindings.push_back(Other.Bindings[i]);
}
}
-DynTypedMatcher::~DynTypedMatcher() {}
-
-DynTypedMatcher *DynTypedMatcher::tryBind(StringRef ID) const { return NULL; }
-
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
- ArrayRef<const DynTypedMatcher *> InnerMatchers) {
+ ArrayRef<DynTypedMatcher> InnerMatchers) {
// allOf leads to one matcher for each alternative in the first
// matcher combined with each alternative in the second matcher.
// Thus, we can reuse the same Builder.
for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
- if (!InnerMatchers[i]->matches(DynNode, Finder, Builder))
+ if (!InnerMatchers[i].matches(DynNode, Finder, Builder))
return false;
}
return true;
bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
- ArrayRef<const DynTypedMatcher *> InnerMatchers) {
+ ArrayRef<DynTypedMatcher> InnerMatchers) {
BoundNodesTreeBuilder Result;
bool Matched = false;
for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
BoundNodesTreeBuilder BuilderInner(*Builder);
- if (InnerMatchers[i]->matches(DynNode, Finder, &BuilderInner)) {
+ if (InnerMatchers[i].matches(DynNode, Finder, &BuilderInner)) {
Matched = true;
Result.addMatch(BuilderInner);
}
bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder,
- ArrayRef<const DynTypedMatcher *> InnerMatchers) {
+ ArrayRef<DynTypedMatcher> InnerMatchers) {
for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
BoundNodesTreeBuilder Result = *Builder;
- if (InnerMatchers[i]->matches(DynNode, Finder, &Result)) {
+ if (InnerMatchers[i].matches(DynNode, Finder, &Result)) {
*Builder = Result;
return true;
}
/// out of the polymorphic object.
template <class PolyMatcher>
static void mergePolyMatchers(const PolyMatcher &Poly,
- std::vector<const DynTypedMatcher *> &Out,
+ std::vector<DynTypedMatcher> &Out,
ast_matchers::internal::EmptyTypeList) {}
template <class PolyMatcher, class TypeList>
static void mergePolyMatchers(const PolyMatcher &Poly,
- std::vector<const DynTypedMatcher *> &Out,
- TypeList) {
- Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly)
- .clone());
+ std::vector<DynTypedMatcher> &Out, TypeList) {
+ Out.push_back(ast_matchers::internal::Matcher<typename TypeList::head>(Poly));
mergePolyMatchers(Poly, Out, typename TypeList::tail());
}
static VariantMatcher outvalueToVariantMatcher(const T &PolyMatcher,
typename T::ReturnTypes * =
NULL) {
- std::vector<const DynTypedMatcher *> Matchers;
+ std::vector<DynTypedMatcher> Matchers;
mergePolyMatchers(PolyMatcher, Matchers, typename T::ReturnTypes());
VariantMatcher Out = VariantMatcher::PolymorphicMatcher(Matchers);
- llvm::DeleteContainerPointers(Matchers);
return Out;
}
return true;
}
-DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,
- Diagnostics *Error) {
+llvm::Optional<DynTypedMatcher>
+Parser::parseMatcherExpression(StringRef Code, Diagnostics *Error) {
RegistrySema S;
return parseMatcherExpression(Code, &S, Error);
}
-DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code,
- Parser::Sema *S,
- Diagnostics *Error) {
+llvm::Optional<DynTypedMatcher>
+Parser::parseMatcherExpression(StringRef Code, Parser::Sema *S,
+ Diagnostics *Error) {
VariantValue Value;
if (!parseExpression(Code, S, &Value, Error))
- return NULL;
+ return llvm::Optional<DynTypedMatcher>();
if (!Value.isMatcher()) {
Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
- return NULL;
+ return llvm::Optional<DynTypedMatcher>();
}
- const DynTypedMatcher *Result;
- if (!Value.getMatcher().getSingleMatcher(Result)) {
+ llvm::Optional<DynTypedMatcher> Result =
+ Value.getMatcher().getSingleMatcher();
+ if (!Result.hasValue()) {
Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
<< Value.getTypeAsString();
- return NULL;
}
- return Result->clone();
+ return Result;
}
} // namespace dynamic
VariantMatcher Out = constructMatcher(MatcherName, NameRange, Args, Error);
if (Out.isNull()) return Out;
- const DynTypedMatcher *Result;
- if (Out.getSingleMatcher(Result)) {
- OwningPtr<DynTypedMatcher> Bound(Result->tryBind(BindID));
- if (Bound) {
+ llvm::Optional<DynTypedMatcher> Result = Out.getSingleMatcher();
+ if (Result.hasValue()) {
+ llvm::Optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
+ if (Bound.hasValue()) {
return VariantMatcher::SingleMatcher(*Bound);
}
}
class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
public:
- SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher.clone()) {}
+ SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
- virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
- Out = Matcher.get();
- return true;
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
+ return Matcher;
}
virtual std::string getTypeAsString() const {
- return (Twine("Matcher<") + Matcher->getSupportedKind().asStringRef() + ">")
+ return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
.str();
}
virtual void makeTypedMatcher(MatcherOps &Ops) const {
- if (Ops.canConstructFrom(*Matcher))
- Ops.constructFrom(*Matcher);
+ if (Ops.canConstructFrom(Matcher))
+ Ops.constructFrom(Matcher);
}
private:
- OwningPtr<const DynTypedMatcher> Matcher;
+ const DynTypedMatcher Matcher;
};
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());
- }
- }
+ PolymorphicPayload(ArrayRef<DynTypedMatcher> MatchersIn)
+ : Matchers(MatchersIn) {}
- virtual ~PolymorphicPayload() {
- llvm::DeleteContainerPointers(Matchers);
- }
+ virtual ~PolymorphicPayload() {}
- virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
if (Matchers.size() != 1)
- return false;
- Out = Matchers[0];
- return true;
+ return llvm::Optional<DynTypedMatcher>();
+ return Matchers[0];
}
virtual std::string getTypeAsString() const {
for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
if (i != 0)
Inner += "|";
- Inner += Matchers[i]->getSupportedKind().asStringRef();
+ Inner += Matchers[i].getSupportedKind().asStringRef();
}
return (Twine("Matcher<") + Inner + ">").str();
}
virtual void makeTypedMatcher(MatcherOps &Ops) const {
const DynTypedMatcher *Found = NULL;
for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
- if (Ops.canConstructFrom(*Matchers[i])) {
+ if (Ops.canConstructFrom(Matchers[i])) {
if (Found)
return;
- Found = Matchers[i];
+ Found = &Matchers[i];
}
}
if (Found)
Ops.constructFrom(*Found);
}
- std::vector<const DynTypedMatcher *> Matchers;
+ const std::vector<DynTypedMatcher> Matchers;
};
class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
ArrayRef<VariantMatcher> Args)
: Func(Func), Args(Args) {}
- virtual bool getSingleMatcher(const DynTypedMatcher *&Out) const {
- return false;
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
+ return llvm::Optional<DynTypedMatcher>();
}
virtual std::string getTypeAsString() const {
}
VariantMatcher
-VariantMatcher::PolymorphicMatcher(ArrayRef<const DynTypedMatcher *> Matchers) {
+VariantMatcher::PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers) {
return VariantMatcher(new PolymorphicPayload(Matchers));
}
return VariantMatcher(new VariadicOpPayload(Func, Args));
}
-bool VariantMatcher::getSingleMatcher(const DynTypedMatcher *&Out) const {
- if (Value) return Value->getSingleMatcher(Out);
- return false;
+llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
+ return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
}
void VariantMatcher::reset() { Value.reset(); }
namespace dynamic {
namespace {
-class DummyDynTypedMatcher : public DynTypedMatcher {
-public:
- DummyDynTypedMatcher(uint64_t ID) : ID(ID) {}
- DummyDynTypedMatcher(uint64_t ID, StringRef BoundID)
- : ID(ID), BoundID(BoundID) {}
-
- typedef ast_matchers::internal::ASTMatchFinder ASTMatchFinder;
- typedef ast_matchers::internal::BoundNodesTreeBuilder BoundNodesTreeBuilder;
- virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return false;
- }
-
- /// \brief Makes a copy of this matcher object.
- virtual DynTypedMatcher *clone() const {
- return new DummyDynTypedMatcher(*this);
- }
-
- /// \brief Returns a unique ID for the matcher.
- virtual uint64_t getID() const { return ID; }
-
- virtual DynTypedMatcher* tryBind(StringRef BoundID) const {
- return new DummyDynTypedMatcher(ID, BoundID);
- }
-
- StringRef boundID() const { return BoundID; }
-
- virtual ast_type_traits::ASTNodeKind getSupportedKind() const {
- return ast_type_traits::ASTNodeKind();
- }
-
-private:
- uint64_t ID;
- std::string BoundID;
-};
-
class MockSema : public Parser::Sema {
public:
virtual ~MockSema() {}
uint64_t expectMatcher(StringRef MatcherName) {
- uint64_t ID = ExpectedMatchers.size() + 1;
- ExpectedMatchers[MatcherName] = ID;
- return ID;
+ ast_matchers::internal::Matcher<Stmt> M = stmt();
+ ExpectedMatchers.insert(std::make_pair(MatcherName, M));
+ return M.getID();
}
void parse(StringRef Code) {
Diagnostics *Error) {
MatcherInfo ToStore = { MatcherName, NameRange, Args, BindID };
Matchers.push_back(ToStore);
- DummyDynTypedMatcher Matcher(ExpectedMatchers[MatcherName]);
- OwningPtr<DynTypedMatcher> Out(Matcher.tryBind(BindID));
- return VariantMatcher::SingleMatcher(*Out);
+ return VariantMatcher::SingleMatcher(
+ ExpectedMatchers.find(MatcherName)->second);
}
struct MatcherInfo {
std::vector<std::string> Errors;
std::vector<VariantValue> Values;
std::vector<MatcherInfo> Matchers;
- llvm::StringMap<uint64_t> ExpectedMatchers;
+ std::map<std::string, ast_matchers::internal::Matcher<Stmt> >
+ ExpectedMatchers;
};
TEST(ParserTest, ParseUnsigned) {
Range.Start.Column == StartColumn && Range.End.Column == EndColumn;
}
-const DynTypedMatcher *getSingleMatcher(const VariantValue &Value) {
- const DynTypedMatcher *Out;
- EXPECT_TRUE(Value.getMatcher().getSingleMatcher(Out));
- return Out;
+llvm::Optional<DynTypedMatcher> getSingleMatcher(const VariantValue &Value) {
+ llvm::Optional<DynTypedMatcher> Result =
+ Value.getMatcher().getSingleMatcher();
+ EXPECT_TRUE(Result.hasValue());
+ return Result;
}
TEST(ParserTest, ParseMatcher) {
EXPECT_EQ(1ULL, Sema.Values.size());
EXPECT_EQ(ExpectedFoo, getSingleMatcher(Sema.Values[0])->getID());
- EXPECT_EQ("Yo!", static_cast<const DummyDynTypedMatcher *>(
- getSingleMatcher(Sema.Values[0]))->boundID());
EXPECT_EQ(3ULL, Sema.Matchers.size());
const MockSema::MatcherInfo Bar = Sema.Matchers[0];
TEST(ParserTest, FullParserTest) {
Diagnostics Error;
- OwningPtr<DynTypedMatcher> VarDecl(Parser::parseMatcherExpression(
+ llvm::Optional<DynTypedMatcher> VarDecl(Parser::parseMatcherExpression(
"varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral()),"
" hasOperatorName(\"+\"))))",
&Error));
EXPECT_EQ("", Error.toStringFull());
- Matcher<Decl> M = Matcher<Decl>::constructFrom(*VarDecl);
+ Matcher<Decl> M = VarDecl->unconditionalConvertTo<Decl>();
EXPECT_TRUE(matches("int x = 1 + false;", M));
EXPECT_FALSE(matches("int x = true + 1;", M));
EXPECT_FALSE(matches("int x = 1 - false;", M));
EXPECT_FALSE(matches("int x = true - 1;", M));
- OwningPtr<DynTypedMatcher> HasParameter(Parser::parseMatcherExpression(
+ llvm::Optional<DynTypedMatcher> HasParameter(Parser::parseMatcherExpression(
"functionDecl(hasParameter(1, hasName(\"x\")))", &Error));
EXPECT_EQ("", Error.toStringFull());
- M = Matcher<Decl>::constructFrom(*HasParameter);
+ M = HasParameter->unconditionalConvertTo<Decl>();
EXPECT_TRUE(matches("void f(int a, int x);", M));
EXPECT_FALSE(matches("void f(int x, int a);", M));
- EXPECT_TRUE(Parser::parseMatcherExpression(
- "hasInitializer(\n binaryOperator(hasLHS(\"A\")))", &Error) == NULL);
+ EXPECT_TRUE(!Parser::parseMatcherExpression(
+ "hasInitializer(\n binaryOperator(hasLHS(\"A\")))",
+ &Error).hasValue());
EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n"
"2:5: Error parsing argument 1 for matcher binaryOperator.\n"
"2:20: Error building matcher hasLHS.\n"