summaryrefslogtreecommitdiff
path: root/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include/clang/ASTMatchers/ASTMatchersInternal.h')
-rw-r--r--clang/include/clang/ASTMatchers/ASTMatchersInternal.h405
1 files changed, 243 insertions, 162 deletions
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index c4b449fa9434..3992850c992d 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -40,7 +40,6 @@
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/NestedNameSpecifier.h"
@@ -61,11 +60,13 @@
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Regex.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <map>
+#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
@@ -130,6 +131,9 @@ inline QualType getUnderlyingType(const FriendDecl &Node) {
return TSI->getType();
return QualType();
}
+inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) {
+ return Node.getType();
+}
/// Unifies obtaining the FunctionProtoType pointer from both
/// FunctionProtoType and FunctionDecl nodes..
@@ -142,14 +146,23 @@ inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) {
return Node.getType()->getAs<FunctionProtoType>();
}
+/// Unifies obtaining the access specifier from Decl and CXXBaseSpecifier nodes.
+inline clang::AccessSpecifier getAccessSpecifier(const Decl &Node) {
+ return Node.getAccess();
+}
+
+inline clang::AccessSpecifier getAccessSpecifier(const CXXBaseSpecifier &Node) {
+ return Node.getAccessSpecifier();
+}
+
/// Internal version of BoundNodes. Holds all the bound nodes.
class BoundNodesMap {
public:
/// Adds \c Node to the map with key \c ID.
///
/// The node's base type should be in NodeBaseType or it will be unaccessible.
- void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) {
- NodeMap[ID] = DynNode;
+ void addNode(StringRef ID, const DynTypedNode &DynNode) {
+ NodeMap[std::string(ID)] = DynNode;
}
/// Returns the AST node bound to \c ID.
@@ -165,10 +178,10 @@ public:
return It->second.get<T>();
}
- ast_type_traits::DynTypedNode getNode(StringRef ID) const {
+ DynTypedNode getNode(StringRef ID) const {
IDToNodeMap::const_iterator It = NodeMap.find(ID);
if (It == NodeMap.end()) {
- return ast_type_traits::DynTypedNode();
+ return DynTypedNode();
}
return It->second;
}
@@ -183,8 +196,7 @@ public:
/// Note that we're using std::map here, as for memoization:
/// - we need a comparison operator
/// - we need an assignment operator
- using IDToNodeMap =
- std::map<std::string, ast_type_traits::DynTypedNode, std::less<>>;
+ using IDToNodeMap = std::map<std::string, DynTypedNode, std::less<>>;
const IDToNodeMap &getMap() const {
return NodeMap;
@@ -223,7 +235,7 @@ public:
};
/// Add a binding from an id to a node.
- void setBinding(StringRef Id, const ast_type_traits::DynTypedNode &DynNode) {
+ void setBinding(StringRef Id, const DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.emplace_back();
for (BoundNodesMap &Binding : Bindings)
@@ -280,11 +292,10 @@ public:
///
/// May bind \p DynNode to an ID via \p Builder, or recurse into
/// the AST via \p Finder.
- virtual bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
- ASTMatchFinder *Finder,
+ virtual bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
- virtual llvm::Optional<ast_type_traits::TraversalKind> TraversalKind() const {
+ virtual llvm::Optional<clang::TraversalKind> TraversalKind() const {
return llvm::None;
}
};
@@ -307,8 +318,7 @@ public:
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const = 0;
- bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
- ASTMatchFinder *Finder,
+ bool dynMatches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return matches(DynNode.getUnchecked<T>(), Finder, Builder);
}
@@ -347,7 +357,7 @@ public:
/// Takes ownership of the provided implementation pointer.
template <typename T>
DynTypedMatcher(MatcherInterface<T> *Implementation)
- : SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()),
+ : SupportedKind(ASTNodeKind::getFromNodeKind<T>()),
RestrictKind(SupportedKind), Implementation(Implementation) {}
/// Construct from a variadic function.
@@ -375,40 +385,44 @@ public:
};
static DynTypedMatcher
- constructVariadic(VariadicOperator Op,
- ast_type_traits::ASTNodeKind SupportedKind,
+ constructVariadic(VariadicOperator Op, ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers);
static DynTypedMatcher
constructRestrictedWrapper(const DynTypedMatcher &InnerMatcher,
- ast_type_traits::ASTNodeKind RestrictKind);
+ ASTNodeKind RestrictKind);
/// Get a "true" matcher for \p NodeKind.
///
/// It only checks that the node is of the right kind.
- static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind);
+ static DynTypedMatcher trueMatcher(ASTNodeKind NodeKind);
void setAllowBind(bool AB) { AllowBind = AB; }
/// Check whether this matcher could ever match a node of kind \p Kind.
/// \return \c false if this matcher will never match such a node. Otherwise,
/// return \c true.
- bool canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const;
+ bool canMatchNodesOfKind(ASTNodeKind Kind) const;
/// Return a matcher that points to the same implementation, but
/// restricts the node types for \p Kind.
- DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const;
+ DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
+
+ /// Return a matcher that that points to the same implementation, but sets the
+ /// traversal kind.
+ ///
+ /// If the traversal kind is already set, then \c TK overrides it.
+ DynTypedMatcher withTraversalKind(TraversalKind TK);
/// Returns true if the matcher matches the given \c DynNode.
- bool matches(const ast_type_traits::DynTypedNode &DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const;
+ bool matches(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const;
/// Same as matches(), but skips the kind check.
///
/// It is faster, but the caller must ensure the node is valid for the
/// kind of this matcher.
- bool matchesNoKindCheck(const ast_type_traits::DynTypedNode &DynNode,
- ASTMatchFinder *Finder,
+ bool matchesNoKindCheck(const DynTypedNode &DynNode, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const;
/// Bind the specified \p ID to the matcher.
@@ -423,7 +437,7 @@ public:
/// include both in the ID to make it unique.
///
/// \c MatcherIDType supports operator< and provides strict weak ordering.
- using MatcherIDType = std::pair<ast_type_traits::ASTNodeKind, uint64_t>;
+ using MatcherIDType = std::pair<ASTNodeKind, uint64_t>;
MatcherIDType getID() const {
/// FIXME: Document the requirements this imposes on matcher
/// implementations (no new() implementation_ during a Matches()).
@@ -435,9 +449,7 @@ public:
///
/// \c matches() will always return false unless the node passed is of this
/// or a derived type.
- ast_type_traits::ASTNodeKind getSupportedKind() const {
- return SupportedKind;
- }
+ ASTNodeKind getSupportedKind() const { return SupportedKind; }
/// Returns \c true if the passed \c DynTypedMatcher can be converted
/// to a \c Matcher<T>.
@@ -445,9 +457,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 canConvertTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ return canConvertTo(ASTNodeKind::getFromNodeKind<T>());
}
- bool canConvertTo(ast_type_traits::ASTNodeKind To) const;
+ bool canConvertTo(ASTNodeKind To) const;
/// Construct a \c Matcher<T> interface around the dynamic matcher.
///
@@ -465,37 +477,31 @@ public:
/// If it is not compatible, then this matcher will never match anything.
template <typename T> Matcher<T> unconditionalConvertTo() const;
+ /// Returns the \c TraversalKind respected by calls to `match()`, if any.
+ ///
+ /// Most matchers will not have a traversal kind set, instead relying on the
+ /// surrounding context. For those, \c llvm::None is returned.
+ llvm::Optional<clang::TraversalKind> getTraversalKind() const {
+ return Implementation->TraversalKind();
+ }
+
private:
- DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind,
- ast_type_traits::ASTNodeKind RestrictKind,
- IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
- : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
- Implementation(std::move(Implementation)) {}
+ DynTypedMatcher(ASTNodeKind SupportedKind, ASTNodeKind RestrictKind,
+ IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
+ : SupportedKind(SupportedKind), RestrictKind(RestrictKind),
+ Implementation(std::move(Implementation)) {}
bool AllowBind = false;
- ast_type_traits::ASTNodeKind SupportedKind;
+ ASTNodeKind SupportedKind;
/// A potentially stricter node kind.
///
/// It allows to perform implicit and dynamic cast of matchers without
/// needing to change \c Implementation.
- ast_type_traits::ASTNodeKind RestrictKind;
+ ASTNodeKind RestrictKind;
IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
};
-/// 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;
-};
-
/// Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@@ -516,11 +522,11 @@ public:
/// Requires \c T to be derived from \c From.
template <typename From>
Matcher(const Matcher<From> &Other,
- typename std::enable_if<std::is_base_of<From, T>::value &&
- !std::is_same<From, T>::value>::type * = nullptr)
+ std::enable_if_t<std::is_base_of<From, T>::value &&
+ !std::is_same<From, T>::value> * = nullptr)
: Implementation(restrictMatcher(Other.Implementation)) {
assert(Implementation.getSupportedKind().isSame(
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ ASTNodeKind::getFromNodeKind<T>()));
}
/// Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
@@ -528,9 +534,8 @@ public:
/// The resulting matcher is not strict, i.e. ignores qualifiers.
template <typename TypeT>
Matcher(const Matcher<TypeT> &Other,
- typename std::enable_if<
- std::is_same<T, QualType>::value &&
- std::is_same<TypeT, Type>::value>::type* = nullptr)
+ std::enable_if_t<std::is_same<T, QualType>::value &&
+ std::is_same<TypeT, Type>::value> * = nullptr)
: Implementation(new TypeToQualType<TypeT>(Other)) {}
/// Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
@@ -546,8 +551,7 @@ public:
bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return Implementation.matches(ast_type_traits::DynTypedNode::create(Node),
- Finder, Builder);
+ return Implementation.matches(DynTypedNode::create(Node), Finder, Builder);
}
/// Returns an ID that uniquely identifies the matcher.
@@ -568,17 +572,19 @@ public:
/// does only matches in the absence of qualifiers, or not, i.e. simply
/// ignores any qualifiers.
template <typename TypeT>
- class TypeToQualType : public WrapperMatcherInterface<QualType> {
+ class TypeToQualType : public MatcherInterface<QualType> {
+ const DynTypedMatcher InnerMatcher;
+
public:
TypeToQualType(const Matcher<TypeT> &InnerMatcher)
- : TypeToQualType::WrapperMatcherInterface(InnerMatcher) {}
+ : InnerMatcher(InnerMatcher) {}
bool matches(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (Node.isNull())
return false;
- return this->InnerMatcher.matches(
- ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
+ return this->InnerMatcher.matches(DynTypedNode::create(*Node), Finder,
+ Builder);
}
};
@@ -590,13 +596,13 @@ private:
friend class DynTypedMatcher;
static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
- return Other.dynCastTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ return Other.dynCastTo(ASTNodeKind::getFromNodeKind<T>());
}
explicit Matcher(const DynTypedMatcher &Implementation)
: Implementation(restrictMatcher(Implementation)) {
- assert(this->Implementation.getSupportedKind()
- .isSame(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ assert(this->Implementation.getSupportedKind().isSame(
+ ASTNodeKind::getFromNodeKind<T>()));
}
DynTypedMatcher Implementation;
@@ -616,9 +622,8 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
template <>
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>())) {
+ const ASTNodeKind SourceKind = getSupportedKind();
+ if (SourceKind.isSame(ASTNodeKind::getFromNodeKind<Type>())) {
// We support implicit conversion from Matcher<Type> to Matcher<QualType>
return unconditionalConvertTo<Type>();
}
@@ -681,12 +686,12 @@ class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
std::is_base_of<FunctionDecl, T>::value,
"unsupported class for matcher");
- static_assert(std::is_same<ArgT, StringRef>::value,
- "argument type must be StringRef");
+ static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
+ "argument type must be std::vector<std::string>");
public:
- explicit HasOverloadedOperatorNameMatcher(const StringRef Name)
- : SingleNodeMatcherInterface<T>(), Name(Name) {}
+ explicit HasOverloadedOperatorNameMatcher(std::vector<std::string> Names)
+ : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
bool matchesNode(const T &Node) const override {
return matchesSpecialized(Node);
@@ -698,17 +703,18 @@ private:
/// so this function returns true if the call is to an operator of the given
/// name.
bool matchesSpecialized(const CXXOperatorCallExpr &Node) const {
- return getOperatorSpelling(Node.getOperator()) == Name;
+ return llvm::is_contained(Names, getOperatorSpelling(Node.getOperator()));
}
/// Returns true only if CXXMethodDecl represents an overloaded
/// operator and has the given operator name.
bool matchesSpecialized(const FunctionDecl &Node) const {
return Node.isOverloadedOperator() &&
- getOperatorSpelling(Node.getOverloadedOperator()) == Name;
+ llvm::is_contained(
+ Names, getOperatorSpelling(Node.getOverloadedOperator()));
}
- std::string Name;
+ const std::vector<std::string> Names;
};
/// Matches named declarations with a specific name.
@@ -760,13 +766,15 @@ Matcher<ObjCMessageExpr> hasAnySelectorFunc(
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
/// not actually used.
template <typename T, typename DeclMatcherT>
-class HasDeclarationMatcher : public WrapperMatcherInterface<T> {
+class HasDeclarationMatcher : public MatcherInterface<T> {
static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
"instantiated with wrong types");
+ const DynTypedMatcher InnerMatcher;
+
public:
explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
- : HasDeclarationMatcher::WrapperMatcherInterface(InnerMatcher) {}
+ : InnerMatcher(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
@@ -920,9 +928,8 @@ private:
/// is \c NULL.
bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return Node != nullptr &&
- this->InnerMatcher.matches(
- ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
+ return Node != nullptr && this->InnerMatcher.matches(
+ DynTypedNode::create(*Node), Finder, Builder);
}
};
@@ -1004,8 +1011,8 @@ public:
template <typename T>
bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- ast_type_traits::TraversalKind Traverse, BindKind Bind) {
+ BoundNodesTreeBuilder *Builder, TraversalKind Traverse,
+ BindKind Bind) {
static_assert(std::is_base_of<Decl, T>::value ||
std::is_base_of<Stmt, T>::value ||
std::is_base_of<NestedNameSpecifier, T>::value ||
@@ -1013,8 +1020,8 @@ public:
std::is_base_of<TypeLoc, T>::value ||
std::is_base_of<QualType, T>::value,
"unsupported type for recursive matching");
- return matchesChildOf(ast_type_traits::DynTypedNode::create(Node),
- getASTContext(), Matcher, Builder, Traverse, Bind);
+ return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
+ Builder, Traverse, Bind);
}
template <typename T>
@@ -1029,8 +1036,8 @@ public:
std::is_base_of<TypeLoc, T>::value ||
std::is_base_of<QualType, T>::value,
"unsupported type for recursive matching");
- return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node),
- getASTContext(), Matcher, Builder, Bind);
+ return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
+ Matcher, Builder, Bind);
}
// FIXME: Implement support for BindKind.
@@ -1044,27 +1051,24 @@ public:
std::is_base_of<Stmt, T>::value ||
std::is_base_of<TypeLoc, T>::value,
"type not allowed for recursive matching");
- return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
- getASTContext(), Matcher, Builder, MatchMode);
+ return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
+ Matcher, Builder, MatchMode);
}
virtual ASTContext &getASTContext() const = 0;
protected:
- virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
- ASTContext &Ctx, const DynTypedMatcher &Matcher,
+ virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
+ const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
- ast_type_traits::TraversalKind Traverse,
- BindKind Bind) = 0;
+ TraversalKind Traverse, BindKind Bind) = 0;
- virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
- ASTContext &Ctx,
+ virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
BindKind Bind) = 0;
- virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
- ASTContext &Ctx,
+ virtual bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) = 0;
@@ -1181,43 +1185,40 @@ struct ArgumentAdaptingMatcherFunc {
}
};
-template <typename T>
-class TraversalMatcher : public WrapperMatcherInterface<T> {
- ast_type_traits::TraversalKind Traversal;
+template <typename T> class TraversalMatcher : public MatcherInterface<T> {
+ const DynTypedMatcher InnerMatcher;
+ clang::TraversalKind Traversal;
public:
- explicit TraversalMatcher(ast_type_traits::TraversalKind TK,
- const Matcher<T> &ChildMatcher)
- : TraversalMatcher::WrapperMatcherInterface(ChildMatcher), Traversal(TK) {
- }
+ explicit TraversalMatcher(clang::TraversalKind TK,
+ const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher), Traversal(TK) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
- return this->InnerMatcher.matches(
- ast_type_traits::DynTypedNode::create(Node), Finder, Builder);
+ return this->InnerMatcher.matches(DynTypedNode::create(Node), Finder,
+ Builder);
}
- llvm::Optional<ast_type_traits::TraversalKind>
- TraversalKind() const override {
+ llvm::Optional<clang::TraversalKind> TraversalKind() const override {
return Traversal;
}
};
template <typename MatcherType> class TraversalWrapper {
public:
- TraversalWrapper(ast_type_traits::TraversalKind TK,
- const MatcherType &InnerMatcher)
+ TraversalWrapper(TraversalKind TK, const MatcherType &InnerMatcher)
: TK(TK), InnerMatcher(InnerMatcher) {}
template <typename T> operator Matcher<T>() const {
return internal::DynTypedMatcher::constructRestrictedWrapper(
new internal::TraversalMatcher<T>(TK, InnerMatcher),
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
+ ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
private:
- ast_type_traits::TraversalKind TK;
+ TraversalKind TK;
MatcherType InnerMatcher;
};
@@ -1300,8 +1301,7 @@ public:
template <typename T>
operator Matcher<T>() const {
- return DynTypedMatcher::trueMatcher(
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
+ return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
};
@@ -1341,15 +1341,17 @@ public:
///
/// ChildT must be an AST base type.
template <typename T, typename ChildT>
-class HasMatcher : public WrapperMatcherInterface<T> {
+class HasMatcher : public MatcherInterface<T> {
+ const DynTypedMatcher InnerMatcher;
+
public:
- explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
- : HasMatcher::WrapperMatcherInterface(ChildMatcher) {}
+ explicit HasMatcher(const Matcher<ChildT> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf(Node, this->InnerMatcher, Builder,
- ast_type_traits::TraversalKind::TK_AsIs,
+ TraversalKind::TK_AsIs,
ASTMatchFinder::BK_First);
}
};
@@ -1360,19 +1362,21 @@ 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 WrapperMatcherInterface<T> {
+class ForEachMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value,
"for each only accepts base type matcher");
- public:
- explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
- : ForEachMatcher::WrapperMatcherInterface(ChildMatcher) {}
+ const DynTypedMatcher InnerMatcher;
- bool matches(const T& Node, ASTMatchFinder* Finder,
- BoundNodesTreeBuilder* Builder) const override {
+public:
+ explicit ForEachMatcher(const Matcher<ChildT> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf(
Node, this->InnerMatcher, Builder,
- ast_type_traits::TraversalKind::TK_IgnoreImplicitCastsAndParentheses,
+ TraversalKind::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_All);
}
};
@@ -1393,7 +1397,7 @@ public:
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::constructVariadic(
- Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ Op, ASTNodeKind::getFromNodeKind<T>(),
getMatchers<T>(std::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
@@ -1449,10 +1453,9 @@ BindableMatcher<T> makeAllOfComposite(
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
- DynTypedMatcher::constructVariadic(
- DynTypedMatcher::VO_AllOf,
- ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
- std::move(DynMatchers))
+ DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
+ ASTNodeKind::getFromNodeKind<T>(),
+ std::move(DynMatchers))
.template unconditionalConvertTo<T>());
}
@@ -1474,17 +1477,19 @@ BindableMatcher<T> makeDynCastAllOfComposite(
///
/// DescendantT must be an AST base type.
template <typename T, typename DescendantT>
-class HasDescendantMatcher : public WrapperMatcherInterface<T> {
+class HasDescendantMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"has descendant only accepts base type matcher");
+ const DynTypedMatcher DescendantMatcher;
+
public:
explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
- : HasDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
+ : DescendantMatcher(DescendantMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
+ return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
ASTMatchFinder::BK_First);
}
};
@@ -1494,17 +1499,19 @@ public:
///
/// \c ParentT must be an AST base type.
template <typename T, typename ParentT>
-class HasParentMatcher : public WrapperMatcherInterface<T> {
+class HasParentMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<ParentT>::value,
"has parent only accepts base type matcher");
+ const DynTypedMatcher ParentMatcher;
+
public:
explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
- : HasParentMatcher::WrapperMatcherInterface(ParentMatcher) {}
+ : ParentMatcher(ParentMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
+ return Finder->matchesAncestorOf(Node, this->ParentMatcher, Builder,
ASTMatchFinder::AMM_ParentOnly);
}
};
@@ -1514,17 +1521,19 @@ public:
///
/// \c AncestorT must be an AST base type.
template <typename T, typename AncestorT>
-class HasAncestorMatcher : public WrapperMatcherInterface<T> {
+class HasAncestorMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<AncestorT>::value,
"has ancestor only accepts base type matcher");
+ const DynTypedMatcher AncestorMatcher;
+
public:
explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
- : HasAncestorMatcher::WrapperMatcherInterface(AncestorMatcher) {}
+ : AncestorMatcher(AncestorMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
+ return Finder->matchesAncestorOf(Node, this->AncestorMatcher, Builder,
ASTMatchFinder::AMM_All);
}
};
@@ -1536,18 +1545,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 WrapperMatcherInterface<T> {
+class ForEachDescendantMatcher : public MatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"for each descendant only accepts base type matcher");
+ const DynTypedMatcher DescendantMatcher;
+
public:
explicit ForEachDescendantMatcher(
const Matcher<DescendantT> &DescendantMatcher)
- : ForEachDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
+ : DescendantMatcher(DescendantMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
- return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
+ return Finder->matchesDescendantOf(Node, this->DescendantMatcher, Builder,
ASTMatchFinder::BK_All);
}
};
@@ -1640,10 +1651,12 @@ public:
/// Matches nodes of type \c TLoc for which the inner
/// \c Matcher<T> matches.
template <typename TLoc, typename T>
-class LocMatcher : public WrapperMatcherInterface<TLoc> {
+class LocMatcher : public MatcherInterface<TLoc> {
+ const DynTypedMatcher InnerMatcher;
+
public:
explicit LocMatcher(const Matcher<T> &InnerMatcher)
- : LocMatcher::WrapperMatcherInterface(InnerMatcher) {}
+ : InnerMatcher(InnerMatcher) {}
bool matches(const TLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
@@ -1653,9 +1666,8 @@ public:
}
private:
- static ast_type_traits::DynTypedNode
- extract(const NestedNameSpecifierLoc &Loc) {
- return ast_type_traits::DynTypedNode::create(*Loc.getNestedNameSpecifier());
+ static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) {
+ return DynTypedNode::create(*Loc.getNestedNameSpecifier());
}
};
@@ -1663,38 +1675,40 @@ private:
/// \c QualType.
///
/// Used to implement the \c loc() matcher.
-class TypeLocTypeMatcher : public WrapperMatcherInterface<TypeLoc> {
+class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> {
+ const DynTypedMatcher InnerMatcher;
+
public:
explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
- : TypeLocTypeMatcher::WrapperMatcherInterface(InnerMatcher) {}
+ : InnerMatcher(InnerMatcher) {}
bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (!Node)
return false;
- return this->InnerMatcher.matches(
- ast_type_traits::DynTypedNode::create(Node.getType()), Finder, Builder);
+ return this->InnerMatcher.matches(DynTypedNode::create(Node.getType()),
+ Finder, Builder);
}
};
/// 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 WrapperMatcherInterface<T> {
+template <typename T> class TypeTraverseMatcher : public MatcherInterface<T> {
+ const DynTypedMatcher InnerMatcher;
+
public:
explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
QualType (T::*TraverseFunction)() const)
- : TypeTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
- TraverseFunction(TraverseFunction) {}
+ : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
QualType NextNode = (Node.*TraverseFunction)();
if (NextNode.isNull())
return false;
- return this->InnerMatcher.matches(
- ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
+ return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
+ Builder);
}
private:
@@ -1705,20 +1719,21 @@ 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 WrapperMatcherInterface<T> {
+class TypeLocTraverseMatcher : public MatcherInterface<T> {
+ const DynTypedMatcher InnerMatcher;
+
public:
explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
TypeLoc (T::*TraverseFunction)() const)
- : TypeLocTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
- TraverseFunction(TraverseFunction) {}
+ : InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
TypeLoc NextNode = (Node.*TraverseFunction)();
if (!NextNode)
return false;
- return this->InnerMatcher.matches(
- ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
+ return this->InnerMatcher.matches(DynTypedNode::create(NextNode), Finder,
+ Builder);
}
private:
@@ -1818,7 +1833,7 @@ struct NotEqualsBoundNodePredicate {
}
std::string ID;
- ast_type_traits::DynTypedNode Node;
+ DynTypedNode Node;
};
template <typename Ty>
@@ -1872,6 +1887,72 @@ CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
return Node.getSubStmt();
}
+/// If \p Loc is (transitively) expanded from macro \p MacroName, returns the
+/// location (in the chain of expansions) at which \p MacroName was
+/// expanded. Since the macro may have been expanded inside a series of
+/// expansions, that location may itself be a MacroID.
+llvm::Optional<SourceLocation>
+getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
+ const ASTContext &Context);
+
+/// Matches overloaded operators with a specific name.
+///
+/// The type argument ArgT is not used by this matcher but is used by
+/// PolymorphicMatcherWithParam1 and should be std::vector<std::string>>.
+template <typename T, typename ArgT = std::vector<std::string>>
+class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
+ static_assert(std::is_same<T, BinaryOperator>::value ||
+ std::is_same<T, UnaryOperator>::value,
+ "Matcher only supports `BinaryOperator` and `UnaryOperator`");
+ static_assert(std::is_same<ArgT, std::vector<std::string>>::value,
+ "Matcher ArgT must be std::vector<std::string>");
+
+public:
+ explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names)
+ : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {}
+
+ bool matchesNode(const T &Node) const override {
+ StringRef OpName = getOpName(Node);
+ return llvm::any_of(
+ Names, [&](const std::string &Name) { return Name == OpName; });
+ }
+
+private:
+ static StringRef getOpName(const UnaryOperator &Node) {
+ return Node.getOpcodeStr(Node.getOpcode());
+ }
+ static StringRef getOpName(const BinaryOperator &Node) {
+ return Node.getOpcodeStr();
+ }
+
+ const std::vector<std::string> Names;
+};
+
+using HasOpNameMatcher =
+ PolymorphicMatcherWithParam1<HasAnyOperatorNameMatcher,
+ std::vector<std::string>,
+ void(TypeList<BinaryOperator, UnaryOperator>)>;
+
+HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
+
+using HasOverloadOpNameMatcher = PolymorphicMatcherWithParam1<
+ HasOverloadedOperatorNameMatcher, std::vector<std::string>,
+ void(TypeList<CXXOperatorCallExpr, FunctionDecl>)>;
+
+HasOverloadOpNameMatcher
+hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs);
+
+/// Returns true if \p Node has a base specifier matching \p BaseSpec.
+///
+/// A class is not considered to be derived from itself.
+bool matchesAnyBase(const CXXRecordDecl &Node,
+ const Matcher<CXXBaseSpecifier> &BaseSpecMatcher,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder);
+
+std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
+ llvm::Regex::RegexFlags Flags,
+ StringRef MatcherID);
+
} // namespace internal
} // namespace ast_matchers