summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/ASTMatchers')
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h21
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h718
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h786
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h189
-rw-r--r--include/clang/ASTMatchers/Dynamic/Diagnostics.h185
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h151
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h75
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h261
8 files changed, 1802 insertions, 584 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 870a39b..db0a83d 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -97,6 +97,11 @@ public:
///
/// Optionally override to do per translation unit tasks.
virtual void onStartOfTranslationUnit() {}
+
+ /// \brief Called at the end of each translation unit.
+ ///
+ /// Optionally override to do per translation unit tasks.
+ virtual void onEndOfTranslationUnit() {}
};
/// \brief Called when parsing is finished. Intended for testing only.
@@ -131,6 +136,17 @@ public:
MatchCallback *Action);
/// @}
+ /// \brief Adds a matcher to execute when running over the AST.
+ ///
+ /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
+ /// is more flexible, but the lost type information enables a caller to pass
+ /// a matcher that cannot match anything.
+ ///
+ /// \returns \c true if the matcher is a valid top-level matcher, \c false
+ /// otherwise.
+ bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
+ MatchCallback *Action);
+
/// \brief Creates a clang ASTConsumer that finds all matches.
clang::ASTConsumer *newASTConsumer();
@@ -147,6 +163,9 @@ public:
ASTContext &Context);
/// @}
+ /// \brief Finds all matches in the given AST.
+ void matchAST(ASTContext &Context);
+
/// \brief Registers a callback to notify the end of parsing.
///
/// The provided closure is called after parsing is done, before the AST is
@@ -157,7 +176,7 @@ public:
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.
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index ab62dd0..0a3157d 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -45,6 +45,7 @@
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
@@ -85,6 +86,16 @@ public:
}
/// @}
+ /// \brief Type of mapping from binding identifiers to bound nodes. This type
+ /// is an associative container with a key type of \c std::string and a value
+ /// type of \c clang::ast_type_traits::DynTypedNode
+ typedef internal::BoundNodesMap::IDToNodeMap IDToNodeMap;
+
+ /// \brief Retrieve mapping from binding identifiers to bound nodes.
+ const IDToNodeMap &getMap() const {
+ return MyBoundNodes.getMap();
+ }
+
private:
/// \brief Create BoundNodes from a pre-filled map of bindings.
BoundNodes(internal::BoundNodesMap &MyBoundNodes)
@@ -92,7 +103,7 @@ private:
internal::BoundNodesMap MyBoundNodes;
- friend class internal::BoundNodesTree;
+ friend class internal::BoundNodesTreeBuilder;
};
/// \brief If the provided matcher matches a node, binds the node to \c ID.
@@ -204,6 +215,28 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
ClassTemplateSpecializationDecl> classTemplateSpecializationDecl;
+/// \brief Matches declarator declarations (field, variable, function
+/// and non-type template parameter declarations).
+///
+/// Given
+/// \code
+/// class X { int y; };
+/// \endcode
+/// declaratorDecl()
+/// matches \c int y.
+const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
+ declaratorDecl;
+
+/// \brief Matches parameter variable declarations.
+///
+/// Given
+/// \code
+/// void f(int x);
+/// \endcode
+/// parmVarDecl()
+/// matches \c int x.
+const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
+
/// \brief Matches C++ access specifier declarations.
///
/// Given
@@ -219,6 +252,17 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
AccessSpecDecl> accessSpecDecl;
+/// \brief Matches constructor initializers.
+///
+/// Examples matches \c i(42).
+/// \code
+/// class C {
+/// C() : i(42) {}
+/// int i;
+/// };
+/// \endcode
+const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
+
/// \brief Matches public C++ declarations.
///
/// Given
@@ -281,12 +325,9 @@ AST_MATCHER(Decl, isPrivate) {
/// matches the specialization \c A<int>
AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
internal::Matcher<TemplateArgument>, InnerMatcher) {
- const TemplateArgumentList &List = Node.getTemplateArgs();
- for (unsigned i = 0; i < List.size(); ++i) {
- if (InnerMatcher.matches(List.get(i), Finder, Builder))
- return true;
- }
- return false;
+ llvm::ArrayRef<TemplateArgument> List = Node.getTemplateArgs().asArray();
+ return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder,
+ Builder);
}
/// \brief Matches expressions that match InnerMatcher after any implicit casts
@@ -520,6 +561,16 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
FunctionTemplateDecl> functionTemplateDecl;
+/// \brief Matches friend declarations.
+///
+/// Given
+/// \code
+/// class X { friend void foo(); };
+/// \endcode
+/// friendDecl()
+/// matches 'friend void foo()'.
+const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
+
/// \brief Matches statements.
///
/// Given
@@ -607,6 +658,21 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
/// matches \code using X::x \endcode
const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+/// \brief Matches unresolved using value declarations.
+///
+/// Given
+/// \code
+/// template<typename X>
+/// class C : private X {
+/// using X::x;
+/// };
+/// \endcode
+/// unresolvedUsingValueDecl()
+/// matches \code using X::x \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UnresolvedUsingValueDecl> unresolvedUsingValueDecl;
+
/// \brief Matches constructor call expressions (including implicit ones).
///
/// Example matches string(ptr, n) and ptr within arguments of f
@@ -621,6 +687,18 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CXXConstructExpr> constructExpr;
+/// \brief Matches unresolved constructor call expressions.
+///
+/// Example matches T(t) in return statement of f
+/// (matcher = unresolvedConstructExpr())
+/// \code
+/// template <typename T>
+/// void f(const T& t) { return T(t); }
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXUnresolvedConstructExpr> unresolvedConstructExpr;
+
/// \brief Matches implicit and explicit this expressions.
///
/// Example matches the implicit this expression in "return i".
@@ -894,6 +972,26 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
/// matches 'case 42: break;' and 'default: break;'.
const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
+/// \brief Matches case statements inside switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// caseStmt()
+/// matches 'case 42: break;'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
+
+/// \brief Matches default statements inside switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// defaultStmt()
+/// matches 'default: break;'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt;
+
/// \brief Matches compound statements.
///
/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
@@ -981,15 +1079,25 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CharacterLiteral> characterLiteral;
-/// \brief Matches integer literals of all sizes / encodings.
-///
-/// Not matching character-encoded integers such as L'a'.
+/// \brief Matches integer literals of all sizes / encodings, e.g.
+/// 1, 1L, 0x1 and 1U.
///
-/// Example matches 1, 1L, 0x1, 1U
+/// Does not match character-encoded integers such as L'a'.
const internal::VariadicDynCastAllOfMatcher<
Stmt,
IntegerLiteral> integerLiteral;
+/// \brief Matches float literals of all sizes / encodings, e.g.
+/// 1.0, 1.0f, 1.0L and 1e10.
+///
+/// Does not match implicit conversions such as
+/// \code
+/// float a = 10;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ FloatingLiteral> floatLiteral;
+
/// \brief Matches user defined literal operator call.
///
/// Example match: "foo"_suffix
@@ -1171,6 +1279,16 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CXXFunctionalCastExpr> functionalCastExpr;
+/// \brief Matches functional cast expressions having N != 1 arguments
+///
+/// Example: Matches Foo(bar, bar)
+/// \code
+/// Foo h = Foo(bar, bar);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXTemporaryObjectExpr> temporaryObjectExpr;
+
/// \brief Matches \c QualTypes in the clang AST.
const internal::VariadicAllOfMatcher<QualType> qualType;
@@ -1199,93 +1317,23 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// \c b.
///
/// Usable as: Any Matcher
-template <typename M1, typename M2>
-internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, M2>
-eachOf(const M1 &P1, const M2 &P2) {
- return internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1,
- M2>(P1, P2);
-}
-
-/// \brief Various overloads for the anyOf matcher.
-/// @{
+const internal::VariadicOperatorMatcherFunc eachOf = {
+ internal::EachOfVariadicOperator
+};
/// \brief Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
-template<typename M1, typename M2>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1, M2>
-anyOf(const M1 &P1, const M2 &P2) {
- return internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
- M1, M2 >(P1, P2);
-}
-template<typename M1, typename M2, typename M3>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2, M3> >
-anyOf(const M1 &P1, const M2 &P2, const M3 &P3) {
- return anyOf(P1, anyOf(P2, P3));
-}
-template<typename M1, typename M2, typename M3, typename M4>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
- M3, M4> > >
-anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) {
- return anyOf(P1, anyOf(P2, anyOf(P3, P4)));
-}
-template<typename M1, typename M2, typename M3, typename M4, typename M5>
-internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M2,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, M3,
- internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher,
- M4, M5> > > >
-anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) {
- return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5))));
-}
-
-/// @}
-
-/// \brief Various overloads for the allOf matcher.
-/// @{
+const internal::VariadicOperatorMatcherFunc anyOf = {
+ internal::AnyOfVariadicOperator
+};
/// \brief Matches if all given matchers match.
///
/// Usable as: Any Matcher
-template <typename M1, typename M2>
-internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2>
-allOf(const M1 &P1, const M2 &P2) {
- return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2>(
- P1, P2);
-}
-template <typename M1, typename M2, typename M3>
-internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M2, M3> >
-allOf(const M1 &P1, const M2 &P2, const M3 &P3) {
- return allOf(P1, allOf(P2, P3));
-}
-template <typename M1, typename M2, typename M3, typename M4>
-internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M2, internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M3, M4> > >
-allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) {
- return allOf(P1, allOf(P2, P3, P4));
-}
-template <typename M1, typename M2, typename M3, typename M4, typename M5>
-internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M1,
- internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M2,
- internal::PolymorphicMatcherWithParam2<
- internal::AllOfMatcher, M3,
- internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M4,
- M5> > > >
-allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) {
- return allOf(P1, allOf(P2, P3, P4, P5));
-}
-
-/// @}
+const internal::VariadicOperatorMatcherFunc allOf = {
+ internal::AllOfVariadicOperator
+};
/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
///
@@ -1412,10 +1460,13 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
///
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
inline internal::PolymorphicMatcherWithParam1<
- internal::HasOverloadedOperatorNameMatcher, StringRef>
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>
hasOverloadedOperatorName(const StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
- internal::HasOverloadedOperatorNameMatcher, StringRef>(Name);
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>(
+ Name);
}
/// \brief Matches C++ classes that are directly or indirectly derived from
@@ -1445,24 +1496,25 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
}
/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
-inline internal::Matcher<CXXRecordDecl> isDerivedFrom(StringRef BaseName) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, StringRef, BaseName, 1) {
assert(!BaseName.empty());
- return isDerivedFrom(hasName(BaseName));
+ return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly
/// match \c Base.
-inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom(
- internal::Matcher<NamedDecl> Base) {
- return anyOf(Base, isDerivedFrom(Base));
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
+ internal::Matcher<NamedDecl>, Base, 0) {
+ return Matcher<CXXRecordDecl>(anyOf(Base, isDerivedFrom(Base)))
+ .matches(Node, Finder, Builder);
}
/// \brief Overloaded method as shortcut for
/// \c isSameOrDerivedFrom(hasName(...)).
-inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom(
- StringRef BaseName) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, StringRef, BaseName,
+ 1) {
assert(!BaseName.empty());
- return isSameOrDerivedFrom(hasName(BaseName));
+ return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
}
/// \brief Matches the first method of a class or struct that satisfies \c
@@ -1478,12 +1530,8 @@ inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom(
/// but not \c B.
AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
InnerMatcher) {
- for (CXXRecordDecl::method_iterator I = Node.method_begin(),
- E = Node.method_end();
- I != E; ++I)
- if (InnerMatcher.matches(**I, Finder, Builder))
- return true;
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.method_begin(),
+ Node.method_end(), Finder, Builder);
}
/// \brief Matches AST nodes that have child AST nodes that match the
@@ -1499,12 +1547,8 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
/// ChildT must be an AST base type.
///
/// Usable as: Any Matcher
-template <typename ChildT>
-internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has(
- const internal::Matcher<ChildT> &ChildMatcher) {
- return internal::ArgumentAdaptingMatcher<internal::HasMatcher,
- ChildT>(ChildMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher>
+LLVM_ATTRIBUTE_UNUSED has = {};
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -1520,13 +1564,8 @@ internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has(
/// DescendantT must be an AST base type.
///
/// Usable as: Any Matcher
-template <typename DescendantT>
-internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher, DescendantT>
-hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasDescendantMatcher,
- DescendantT>(DescendantMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
+LLVM_ATTRIBUTE_UNUSED hasDescendant = {};
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
@@ -1544,13 +1583,8 @@ hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) {
/// matches instead of only on the first one.
///
/// Usable as: Any Matcher
-template <typename ChildT>
-internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach(
- const internal::Matcher<ChildT> &ChildMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::ForEachMatcher,
- ChildT>(ChildMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
+LLVM_ATTRIBUTE_UNUSED forEach = {};
/// \brief Matches AST nodes that have descendant AST nodes that match the
/// provided matcher.
@@ -1576,15 +1610,8 @@ internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach(
/// \endcode
///
/// Usable as: Any Matcher
-template <typename DescendantT>
-internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher,
- DescendantT>
-forEachDescendant(
- const internal::Matcher<DescendantT> &DescendantMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::ForEachDescendantMatcher,
- DescendantT>(DescendantMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher>
+LLVM_ATTRIBUTE_UNUSED forEachDescendant = {};
/// \brief Matches if the node or any descendant matches.
///
@@ -1602,10 +1629,7 @@ forEachDescendant(
///
/// Usable as: Any Matcher
template <typename T>
-internal::PolymorphicMatcherWithParam2<
- internal::EachOfMatcher, internal::Matcher<T>,
- internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, T> >
-findAll(const internal::Matcher<T> &Matcher) {
+internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
return eachOf(Matcher, forEachDescendant(Matcher));
}
@@ -1619,13 +1643,9 @@ findAll(const internal::Matcher<T> &Matcher) {
/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
///
/// Usable as: Any Matcher
-template <typename ParentT>
-internal::ArgumentAdaptingMatcher<internal::HasParentMatcher, ParentT>
-hasParent(const internal::Matcher<ParentT> &ParentMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasParentMatcher,
- ParentT>(ParentMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasParentMatcher, internal::TypeList<Decl, Stmt>,
+ internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasParent = {};
/// \brief Matches AST nodes that have an ancestor that matches the provided
/// matcher.
@@ -1638,13 +1658,9 @@ hasParent(const internal::Matcher<ParentT> &ParentMatcher) {
/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43.
///
/// Usable as: Any Matcher
-template <typename AncestorT>
-internal::ArgumentAdaptingMatcher<internal::HasAncestorMatcher, AncestorT>
-hasAncestor(const internal::Matcher<AncestorT> &AncestorMatcher) {
- return internal::ArgumentAdaptingMatcher<
- internal::HasAncestorMatcher,
- AncestorT>(AncestorMatcher);
-}
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasAncestorMatcher, internal::TypeList<Decl, Stmt>,
+ internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
/// \brief Matches if the provided matcher does not match.
///
@@ -1662,22 +1678,31 @@ unless(const M &InnerMatcher) {
internal::NotMatcher, M>(InnerMatcher);
}
-/// \brief Matches a type if the declaration of the type matches the given
-/// matcher.
+/// \brief Matches a node if the declaration associated with that node
+/// matches the given matcher.
+///
+/// The associated declaration is:
+/// - for type nodes, the declaration of the underlying type
+/// - for CallExpr, the declaration of the callee
+/// - for MemberExpr, the declaration of the referenced member
+/// - for CXXConstructExpr, the declaration of the constructor
///
-/// In addition to being usable as Matcher<TypedefType>, also usable as
-/// Matcher<T> for any T supporting the getDecl() member function. e.g. various
-/// subtypes of clang::Type.
+/// Also usable as Matcher<T> for any T supporting the getDecl() member
+/// function. e.g. various subtypes of clang::Type and various expressions.
///
-/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>,
-/// Matcher<MemberExpr>, Matcher<TypedefType>,
-/// Matcher<TemplateSpecializationType>
-inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher,
- internal::Matcher<Decl> >
- hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
+/// Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
+/// Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
+/// Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
+/// Matcher<RecordType>, Matcher<TagType>,
+/// Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
+/// Matcher<TypedefType>, Matcher<UnresolvedUsingType>
+inline internal::PolymorphicMatcherWithParam1<
+ internal::HasDeclarationMatcher, internal::Matcher<Decl>,
+ void(internal::HasDeclarationSupportedTypes)>
+hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
return internal::PolymorphicMatcherWithParam1<
- internal::HasDeclarationMatcher,
- internal::Matcher<Decl> >(InnerMatcher);
+ internal::HasDeclarationMatcher, internal::Matcher<Decl>,
+ void(internal::HasDeclarationSupportedTypes)>(InnerMatcher);
}
/// \brief Matches on the implicit object argument of a member call expression.
@@ -1728,9 +1753,9 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
/// class Y { public: void x(); };
/// void z() { Y y; y.x();
/// \endcode
-inline internal::Matcher<CallExpr> callee(
- const internal::Matcher<Decl> &InnerMatcher) {
- return callExpr(hasDeclaration(InnerMatcher));
+AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
+ 1) {
+ return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder);
}
/// \brief Matches if the expression's or declaration's type matches a type
@@ -1742,11 +1767,9 @@ inline internal::Matcher<CallExpr> callee(
/// class X {};
/// void y(X &x) { x; X z; }
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value ||
- llvm::is_base_of<ValueDecl, NodeType>::value),
- instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
+ internal::Matcher<QualType>, InnerMatcher, 0) {
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
@@ -1767,11 +1790,27 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
/// \endcode
///
/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
-inline internal::PolymorphicMatcherWithParam1<
- internal::matcher_hasType0Matcher,
- internal::Matcher<QualType> >
-hasType(const internal::Matcher<Decl> &InnerMatcher) {
- return hasType(qualType(hasDeclaration(InnerMatcher)));
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
+ internal::Matcher<Decl>, InnerMatcher, 1) {
+ return qualType(hasDeclaration(InnerMatcher))
+ .matches(Node.getType(), Finder, Builder);
+}
+
+/// \brief Matches if the type location of the declarator decl's type matches
+/// the inner matcher.
+///
+/// Given
+/// \code
+/// int x;
+/// \endcode
+/// declaratorDecl(hasTypeLoc(loc(asString("int"))))
+/// matches int x
+AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) {
+ if (!Node.getTypeSourceInfo())
+ // This happens for example for implicit destructors.
+ return false;
+ return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder);
}
/// \brief Matches if the matched type is represented by the given string.
@@ -1804,9 +1843,10 @@ AST_MATCHER_P(
}
/// \brief Overloaded to match the pointee type's declaration.
-inline internal::Matcher<QualType> pointsTo(
- const internal::Matcher<Decl> &InnerMatcher) {
- return pointsTo(qualType(hasDeclaration(InnerMatcher)));
+AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
+ InnerMatcher, 1) {
+ return pointsTo(qualType(hasDeclaration(InnerMatcher)))
+ .matches(Node, Finder, Builder);
}
/// \brief Matches if the matched type is a reference type and the referenced
@@ -1841,13 +1881,16 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does.
AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>,
InnerMatcher) {
+ if (Node.isNull())
+ return false;
return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder);
}
/// \brief Overloaded to match the referenced type's declaration.
-inline internal::Matcher<QualType> references(
- const internal::Matcher<Decl> &InnerMatcher) {
- return references(qualType(hasDeclaration(InnerMatcher)));
+AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
+ InnerMatcher, 1) {
+ return references(qualType(hasDeclaration(InnerMatcher)))
+ .matches(Node, Finder, Builder);
}
AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
@@ -1859,17 +1902,19 @@ AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
/// \brief Matches if the expression's type either matches the specified
/// matcher, or is a pointer to a type that matches the InnerMatcher.
-inline internal::Matcher<CXXMemberCallExpr> thisPointerType(
- const internal::Matcher<QualType> &InnerMatcher) {
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
+ internal::Matcher<QualType>, InnerMatcher, 0) {
return onImplicitObjectArgument(
- anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+ .matches(Node, Finder, Builder);
}
/// \brief Overloaded to match the type's declaration.
-inline internal::Matcher<CXXMemberCallExpr> thisPointerType(
- const internal::Matcher<Decl> &InnerMatcher) {
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
+ internal::Matcher<Decl>, InnerMatcher, 1) {
return onImplicitObjectArgument(
- anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+ .matches(Node, Finder, Builder);
}
/// \brief Matches a DeclRefExpr that refers to a declaration that matches the
@@ -1953,11 +1998,9 @@ AST_MATCHER_P(
/// void f(int x, int y);
/// f(0, 0);
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+AST_POLYMORPHIC_MATCHER_P(argumentCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ CallExpr, CXXConstructExpr),
+ unsigned, N) {
return Node.getNumArgs() == N;
}
@@ -1970,11 +2013,9 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
/// void x(int) { int y; x(y); }
/// \endcode
AST_POLYMORPHIC_MATCHER_P2(
- hasArgument, unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+ hasArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CallExpr, CXXConstructExpr),
+ unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
return (N < Node.getNumArgs() &&
InnerMatcher.matches(
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
@@ -2037,13 +2078,8 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
- for (CXXConstructorDecl::init_const_iterator I = Node.init_begin();
- I != Node.init_end(); ++I) {
- if (InnerMatcher.matches(**I, Finder, Builder)) {
- return true;
- }
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.init_begin(),
+ Node.init_end(), Finder, Builder);
}
/// \brief Matches the field declaration of a constructor initializer.
@@ -2086,7 +2122,7 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer,
InnerMatcher.matches(*NodeAsExpr, Finder, Builder));
}
-/// \brief Matches a contructor initializer if it is explicitly written in
+/// \brief Matches a constructor initializer if it is explicitly written in
/// code (as opposed to implicitly added by the compiler).
///
/// Given
@@ -2120,15 +2156,19 @@ AST_MATCHER(CXXConstructorDecl, isImplicit) {
/// matches x(1, y, 42)
/// with hasAnyArgument(...)
/// matching y
-AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<Expr>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
- llvm::is_base_of<CXXConstructExpr,
- NodeType>::value),
- instantiated_with_wrong_types);
+///
+/// FIXME: Currently this will ignore parentheses and implicit casts on
+/// the argument before applying the inner matcher. We'll want to remove
+/// this to allow for greater control by the user once \c ignoreImplicit()
+/// has been implemented.
+AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ CallExpr, CXXConstructExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
- if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(),
- Finder, Builder)) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder,
+ &Result)) {
+ *Builder = Result;
return true;
}
}
@@ -2167,12 +2207,8 @@ AST_MATCHER_P2(FunctionDecl, hasParameter,
/// matching int y
AST_MATCHER_P(FunctionDecl, hasAnyParameter,
internal::Matcher<ParmVarDecl>, InnerMatcher) {
- for (unsigned I = 0; I < Node.getNumParams(); ++I) {
- if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) {
- return true;
- }
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
+ Node.param_end(), Finder, Builder);
}
/// \brief Matches \c FunctionDecls that have a specific parameter count.
@@ -2222,27 +2258,68 @@ AST_MATCHER(FunctionDecl, isExternC) {
/// \code
/// if (true) {}
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<IfStmt, NodeType>::value) ||
- (llvm::is_base_of<ForStmt, NodeType>::value) ||
- (llvm::is_base_of<WhileStmt, NodeType>::value) ||
- (llvm::is_base_of<DoStmt, NodeType>::value) ||
- (llvm::is_base_of<ConditionalOperator, NodeType>::value),
- has_condition_requires_if_statement_conditional_operator_or_loop);
+AST_POLYMORPHIC_MATCHER_P(
+ hasCondition, AST_POLYMORPHIC_SUPPORTED_TYPES_5(
+ IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator),
+ internal::Matcher<Expr>, InnerMatcher) {
const Expr *const Condition = Node.getCond();
return (Condition != NULL &&
InnerMatcher.matches(*Condition, Finder, Builder));
}
+namespace internal {
+struct NotEqualsBoundNodePredicate {
+ bool operator()(const internal::BoundNodesMap &Nodes) const {
+ return Nodes.getNode(ID) != Node;
+ }
+ std::string ID;
+ ast_type_traits::DynTypedNode Node;
+};
+} // namespace internal
+
+/// \brief Matches if a node equals a previously bound node.
+///
+/// Matches a node if it equals the node previously bound to \p ID.
+///
+/// Given
+/// \code
+/// class X { int a; int b; };
+/// \endcode
+/// recordDecl(
+/// has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
+/// has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
+/// matches the class \c X, as \c a and \c b have the same type.
+///
+/// Note that when multiple matches are involved via \c forEach* matchers,
+/// \c equalsBoundNodes acts as a filter.
+/// For example:
+/// compoundStmt(
+/// forEachDescendant(varDecl().bind("d")),
+/// forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d"))))))
+/// will trigger a match for each combination of variable declaration
+/// and reference to that variable declaration within a compound statement.
+AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, AST_POLYMORPHIC_SUPPORTED_TYPES_4(
+ Stmt, Decl, Type, QualType),
+ std::string, ID) {
+ // FIXME: Figure out whether it makes sense to allow this
+ // on any other node types.
+ // For *Loc it probably does not make sense, as those seem
+ // unique. For NestedNameSepcifier it might make sense, as
+ // those also have pointer identity, but I'm not sure whether
+ // they're ever reused.
+ internal::NotEqualsBoundNodePredicate Predicate;
+ Predicate.ID = ID;
+ Predicate.Node = ast_type_traits::DynTypedNode::create(Node);
+ return Builder->removeBindings(Predicate);
+}
+
/// \brief Matches the condition variable statement in an if statement.
///
/// Given
/// \code
/// if (A* a = GetAPointer()) {}
/// \endcode
-/// hasConditionVariableStatment(...)
+/// hasConditionVariableStatement(...)
/// matches 'A* a = GetAPointer()'.
AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
internal::Matcher<DeclStmt>, InnerMatcher) {
@@ -2296,13 +2373,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
/// matches 'for (;;) {}'
/// with compoundStmt()
/// matching '{}'
-AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
- InnerMatcher) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<DoStmt, NodeType>::value) ||
- (llvm::is_base_of<ForStmt, NodeType>::value) ||
- (llvm::is_base_of<WhileStmt, NodeType>::value),
- has_body_requires_for_while_or_do_statement);
+AST_POLYMORPHIC_MATCHER_P(
+ hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES_3(DoStmt, ForStmt, WhileStmt),
+ internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Statement = Node.getBody();
return (Statement != NULL &&
InnerMatcher.matches(*Statement, Finder, Builder));
@@ -2321,12 +2394,8 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
/// matching '{}'
AST_MATCHER_P(CompoundStmt, hasAnySubstatement,
internal::Matcher<Stmt>, InnerMatcher) {
- for (CompoundStmt::const_body_iterator It = Node.body_begin();
- It != Node.body_end();
- ++It) {
- if (InnerMatcher.matches(**It, Finder, Builder)) return true;
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.body_begin(),
+ Node.body_end(), Finder, Builder);
}
/// \brief Checks that a compound statement contains a specific number of
@@ -2367,11 +2436,9 @@ equals(const ValueT &Value) {
/// \code
/// !(a || b)
/// \endcode
-AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<BinaryOperator, NodeType>::value) ||
- (llvm::is_base_of<UnaryOperator, NodeType>::value),
- has_condition_requires_if_statement_or_conditional_operator);
+AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
+ BinaryOperator, UnaryOperator),
+ std::string, Name) {
return Name == Node.getOpcodeStr(Node.getOpcode());
}
@@ -2493,12 +2560,8 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
/// \endcode
///
/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
-AST_POLYMORPHIC_MATCHER(isDefinition) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<TagDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<FunctionDecl, NodeType>::value),
- is_definition_requires_isThisDeclarationADefinition_method);
+AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3(
+ TagDecl, VarDecl, FunctionDecl)) {
return Node.isThisDeclarationADefinition();
}
@@ -2540,6 +2603,21 @@ AST_MATCHER(CXXMethodDecl, isVirtual) {
return Node.isVirtual();
}
+/// \brief Matches if the given method declaration is const.
+///
+/// Given
+/// \code
+/// struct A {
+/// void foo() const;
+/// void bar();
+/// };
+/// \endcode
+///
+/// methodDecl(isConst()) matches A::foo() but not A::bar()
+AST_MATCHER(CXXMethodDecl, isConst) {
+ return Node.isConst();
+}
+
/// \brief Matches if the given method declaration overrides another method.
///
/// Given
@@ -2672,12 +2750,8 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression,
/// matches \code using X::b \endcode
AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl,
internal::Matcher<UsingShadowDecl>, InnerMatcher) {
- for (UsingDecl::shadow_iterator II = Node.shadow_begin();
- II != Node.shadow_end(); ++II) {
- if (InnerMatcher.matches(**II, Finder, Builder))
- return true;
- }
- return false;
+ return matchesFirstInPointerRange(InnerMatcher, Node.shadow_begin(),
+ Node.shadow_end(), Finder, Builder);
}
/// \brief Matches a using shadow declaration where the target declaration is
@@ -2720,11 +2794,9 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// does not match, as X<A> is an explicit template specialization.
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
- requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+ isTemplateInstantiation,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
Node.getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition);
@@ -2742,11 +2814,9 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) {
/// matches the specialization A<int>().
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
-AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) ||
- (llvm::is_base_of<VarDecl, NodeType>::value) ||
- (llvm::is_base_of<CXXRecordDecl, NodeType>::value),
- requires_getTemplateSpecializationKind_method);
+AST_POLYMORPHIC_MATCHER(
+ isExplicitTemplateSpecialization,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
}
@@ -2807,7 +2877,9 @@ AST_TYPE_MATCHER(ComplexType, complexType);
/// matches "int b[7]"
///
/// Usable as: Matcher<ArrayType>, Matcher<ComplexType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement);
+AST_TYPELOC_TRAVERSE_MATCHER(
+ hasElementType, getElement,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(ArrayType, ComplexType));
/// \brief Matches C arrays with a specified constant size.
///
@@ -2914,7 +2986,8 @@ AST_TYPE_MATCHER(AtomicType, atomicType);
/// matches "_Atomic(int) i"
///
/// Usable as: Matcher<AtomicType>
-AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue);
+AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(AtomicType));
/// \brief Matches types nodes representing C++11 auto types.
///
@@ -2942,7 +3015,8 @@ AST_TYPE_MATCHER(AutoType, autoType);
/// matches "auto a"
///
/// Usable as: Matcher<AutoType>
-AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType);
+AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(AutoType));
/// \brief Matches \c FunctionType nodes.
///
@@ -2979,7 +3053,8 @@ AST_TYPE_MATCHER(ParenType, parenType);
/// \c ptr_to_func but not \c ptr_to_array.
///
/// Usable as: Matcher<ParenType>
-AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType);
+AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_1(ParenType));
/// \brief Matches block pointer types, i.e. types syntactically represented as
/// "void (^)(int)".
@@ -3073,7 +3148,10 @@ AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType);
///
/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>,
/// Matcher<PointerType>, Matcher<ReferenceType>
-AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee);
+AST_TYPELOC_TRAVERSE_MATCHER(
+ pointee, getPointee,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_4(BlockPointerType, MemberPointerType,
+ PointerType, ReferenceType));
/// \brief Matches typedef types.
///
@@ -3100,6 +3178,16 @@ AST_TYPE_MATCHER(TypedefType, typedefType);
/// instantiation in \c A and the type of the variable declaration in \c B.
AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType);
+/// \brief Matches types nodes representing unary type transformations.
+///
+/// Given:
+/// \code
+/// typedef __underlying_type(T) type;
+/// \endcode
+/// unaryTransformType()
+/// matches "__underlying_type(T)"
+AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType);
+
/// \brief Matches record types (e.g. structs, classes).
///
/// Given
@@ -3331,6 +3419,80 @@ AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, Stmt*, Other, 1) {
/// @}
+/// \brief Matches each case or default statement belonging to the given switch
+/// statement. This matcher may produce multiple matches.
+///
+/// Given
+/// \code
+/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } }
+/// \endcode
+/// switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s")
+/// matches four times, with "c" binding each of "case 1:", "case 2:",
+/// "case 3:" and "case 4:", and "s" respectively binding "switch (1)",
+/// "switch (1)", "switch (2)" and "switch (2)".
+AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
+ InnerMatcher) {
+ BoundNodesTreeBuilder Result;
+ // FIXME: getSwitchCaseList() does not necessarily guarantee a stable
+ // iteration order. We should use the more general iterating matchers once
+ // they are capable of expressing this matcher (for example, it should ignore
+ // case statements belonging to nested switch statements).
+ bool Matched = false;
+ for (const SwitchCase *SC = Node.getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ BoundNodesTreeBuilder CaseBuilder(*Builder);
+ bool CaseMatched = InnerMatcher.matches(*SC, Finder, &CaseBuilder);
+ if (CaseMatched) {
+ Matched = true;
+ Result.addMatch(CaseBuilder);
+ }
+ }
+ *Builder = Result;
+ return Matched;
+}
+
+/// \brief Matches each constructor initializer in a constructor definition.
+///
+/// Given
+/// \code
+/// class A { A() : i(42), j(42) {} int i; int j; };
+/// \endcode
+/// constructorDecl(forEachConstructorInitializer(forField(decl().bind("x"))))
+/// will trigger two matches, binding for 'i' and 'j' respectively.
+AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
+ internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
+ BoundNodesTreeBuilder Result;
+ bool Matched = false;
+ for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(),
+ E = Node.init_end();
+ I != E; ++I) {
+ BoundNodesTreeBuilder InitBuilder(*Builder);
+ if (InnerMatcher.matches(**I, Finder, &InitBuilder)) {
+ Matched = true;
+ Result.addMatch(InitBuilder);
+ }
+ }
+ *Builder = Result;
+ return Matched;
+}
+
+/// \brief If the given case statement does not use the GNU case range
+/// extension, matches the constant given in the statement.
+///
+/// Given
+/// \code
+/// switch (1) { case 1: case 1+1: case 3 ... 4: ; }
+/// \endcode
+/// caseStmt(hasCaseConstant(integerLiteral()))
+/// matches "case 1:"
+AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
+ InnerMatcher) {
+ if (Node.getRHS())
+ return false;
+
+ return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
+}
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 30691ad..69cee2e 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -36,12 +36,13 @@
#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>
@@ -60,7 +61,6 @@ class BoundNodes;
namespace internal {
-class BoundNodesTreeBuilder;
/// \brief Internal version of BoundNodes. Holds all the bound nodes.
class BoundNodesMap {
public:
@@ -71,9 +71,6 @@ public:
void addNode(StringRef ID, const T* Node) {
NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node);
}
- void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) {
- NodeMap[ID] = Node;
- }
/// \brief Returns the AST node bound to \c ID.
///
@@ -88,29 +85,39 @@ public:
return It->second.get<T>();
}
- /// \brief Copies all ID/Node pairs to BoundNodesTreeBuilder \c Builder.
- void copyTo(BoundNodesTreeBuilder *Builder) const;
+ ast_type_traits::DynTypedNode getNode(StringRef ID) const {
+ IDToNodeMap::const_iterator It = NodeMap.find(ID);
+ if (It == NodeMap.end()) {
+ return ast_type_traits::DynTypedNode();
+ }
+ return It->second;
+ }
- /// \brief Copies all ID/Node pairs to BoundNodesMap \c Other.
- void copyTo(BoundNodesMap *Other) const;
+ /// \brief Imposes an order on BoundNodesMaps.
+ bool operator<(const BoundNodesMap &Other) const {
+ return NodeMap < Other.NodeMap;
+ }
-private:
/// \brief A map from IDs to the bound nodes.
+ ///
+ /// Note that we're using std::map here, as for memoization:
+ /// - we need a comparison operator
+ /// - we need an assignment operator
typedef std::map<std::string, ast_type_traits::DynTypedNode> IDToNodeMap;
+ const IDToNodeMap &getMap() const {
+ return NodeMap;
+ }
+
+private:
IDToNodeMap NodeMap;
};
-/// \brief A tree of bound nodes in match results.
-///
-/// If a match can contain multiple matches on the same node with different
-/// matching subexpressions, BoundNodesTree contains a branch for each of
-/// those matching subexpressions.
+/// \brief Creates BoundNodesTree objects.
///
-/// BoundNodesTree's are created during the matching process; when a match
-/// is found, we iterate over the tree and create a BoundNodes object containing
-/// the union of all bound nodes on the path from the root to a each leaf.
-class BoundNodesTree {
+/// The tree builder is used during the matching process to insert the bound
+/// nodes from the Id matcher.
+class BoundNodesTreeBuilder {
public:
/// \brief A visitor interface to visit all BoundNodes results for a
/// BoundNodesTree.
@@ -124,63 +131,36 @@ public:
virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
};
- BoundNodesTree();
-
- /// \brief Create a BoundNodesTree from pre-filled maps of bindings.
- BoundNodesTree(const BoundNodesMap& Bindings,
- const std::vector<BoundNodesTree> RecursiveBindings);
+ /// \brief Add a binding from an id to a node.
+ template <typename T> void setBinding(const std::string &Id, const T *Node) {
+ if (Bindings.empty())
+ Bindings.push_back(BoundNodesMap());
+ for (unsigned i = 0, e = Bindings.size(); i != e; ++i)
+ Bindings[i].addNode(Id, Node);
+ }
- /// \brief Adds all bound nodes to \c Builder.
- void copyTo(BoundNodesTreeBuilder* Builder) const;
+ /// \brief Adds a branch in the tree.
+ void addMatch(const BoundNodesTreeBuilder &Bindings);
/// \brief Visits all matches that this BoundNodesTree represents.
///
/// The ownership of 'ResultVisitor' remains at the caller.
void visitMatches(Visitor* ResultVisitor);
-private:
- void visitMatchesRecursively(
- Visitor* ResultVistior,
- const BoundNodesMap& AggregatedBindings);
-
- // FIXME: Find out whether we want to use different data structures here -
- // first benchmarks indicate that it doesn't matter though.
-
- BoundNodesMap Bindings;
-
- std::vector<BoundNodesTree> RecursiveBindings;
-};
-
-/// \brief Creates BoundNodesTree objects.
-///
-/// The tree builder is used during the matching process to insert the bound
-/// nodes from the Id matcher.
-class BoundNodesTreeBuilder {
-public:
- BoundNodesTreeBuilder();
-
- /// \brief Add a binding from an id to a node.
- template <typename T>
- void setBinding(const std::string &Id, const T *Node) {
- Bindings.addNode(Id, Node);
- }
- void setBinding(const std::string &Id, ast_type_traits::DynTypedNode Node) {
- Bindings.addNode(Id, Node);
+ template <typename ExcludePredicate>
+ bool removeBindings(const ExcludePredicate &Predicate) {
+ Bindings.erase(std::remove_if(Bindings.begin(), Bindings.end(), Predicate),
+ Bindings.end());
+ return !Bindings.empty();
}
- /// \brief Adds a branch in the tree.
- void addMatch(const BoundNodesTree& Bindings);
-
- /// \brief Returns a BoundNodes object containing all current bindings.
- BoundNodesTree build() const;
+ /// \brief Imposes an order on BoundNodesTreeBuilders.
+ bool operator<(const BoundNodesTreeBuilder &Other) const {
+ return Bindings < Other.Bindings;
+ }
private:
- BoundNodesTreeBuilder(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION;
- void operator=(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION;
-
- BoundNodesMap Bindings;
-
- std::vector<BoundNodesTree> RecursiveBindings;
+ SmallVector<BoundNodesMap, 16> Bindings;
};
class ASTMatchFinder;
@@ -225,24 +205,6 @@ private:
}
};
-/// \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 Returns a unique ID for the matcher.
- virtual uint64_t getID() const = 0;
-};
-
/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@@ -252,7 +214,7 @@ public:
/// 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)
@@ -282,7 +244,13 @@ public:
bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return Implementation->matches(Node, Finder, Builder);
+ if (Implementation->matches(Node, Finder, Builder))
+ return true;
+ // Delete all bindings when a matcher does not match.
+ // This prevents unexpected exposure of bound nodes in unmatches
+ // branches of the match tree.
+ *Builder = BoundNodesTreeBuilder();
+ return false;
}
/// \brief Returns an ID that uniquely identifies the matcher.
@@ -292,15 +260,6 @@ public:
return reinterpret_cast<uint64_t>(Implementation.getPtr());
}
- /// \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 Allows the conversion of a \c Matcher<Type> to a \c
/// Matcher<QualType>.
///
@@ -353,6 +312,217 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
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 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>());
+ 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 unconditionalConvertTo<Type>();
+ }
+ return unconditionalConvertTo<QualType>();
+}
+
+/// \brief Finds the first node in a range that matches the given matcher.
+template <typename MatcherT, typename IteratorT>
+bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
+ IteratorT End, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) {
+ for (IteratorT I = Start; I != End; ++I) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(*I, Finder, &Result)) {
+ *Builder = Result;
+ return true;
+ }
+ }
+ return false;
+}
+
+/// \brief Finds the first node in a pointer range that matches the given
+/// matcher.
+template <typename MatcherT, typename IteratorT>
+bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
+ IteratorT End, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) {
+ for (IteratorT I = Start; I != End; ++I) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(**I, Finder, &Result)) {
+ *Builder = Result;
+ return true;
+ }
+ }
+ return false;
+}
+
/// \brief Metafunction to determine if type T has a member called getDecl.
template <typename T> struct has_getDecl {
struct Default { int getDecl; };
@@ -632,6 +802,94 @@ protected:
AncestorMatchMode MatchMode) = 0;
};
+/// \brief A type-list implementation.
+///
+/// A list is declared as a tree of type list nodes, where the leafs are the
+/// types.
+/// However, it is used as a "linked list" of types, by using the ::head and
+/// ::tail typedefs.
+/// Each node supports up to 4 children (instead of just 2) to reduce the
+/// nesting required by large lists.
+template <typename T1 = void, typename T2 = void, typename T3 = void,
+ typename T4 = void>
+struct TypeList {
+ /// \brief Implementation detail. Combined with the specializations below,
+ /// this typedef allows for flattening of nested structures.
+ typedef TypeList<T1, T2, T3, T4> self;
+
+ /// \brief The first type on the list.
+ typedef T1 head;
+
+ /// \brief A sub list with the tail. ie everything but the head.
+ ///
+ /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
+ /// end of the list.
+ typedef typename TypeList<T2, T3, T4>::self tail;
+};
+
+/// \brief Template specialization to allow nested lists.
+///
+/// First element is a typelist. Pop its first element.
+template <typename Sub1, typename Sub2, typename Sub3, typename Sub4,
+ typename T2, typename T3, typename T4>
+struct TypeList<TypeList<Sub1, Sub2, Sub3, Sub4>, T2, T3,
+ T4> : public TypeList<Sub1,
+ typename TypeList<Sub2, Sub3, Sub4>::self,
+ typename TypeList<T2, T3, T4>::self> {};
+
+/// \brief Template specialization to allow nested lists.
+///
+/// First element is an empty typelist. Skip it.
+template <typename T2, typename T3, typename T4>
+struct TypeList<TypeList<>, T2, T3, T4> : public TypeList<T2, T3, T4> {
+};
+
+/// \brief The empty type list.
+typedef TypeList<> EmptyTypeList;
+
+/// \brief Helper meta-function to determine if some type \c T is present or
+/// a parent type in the list.
+template <typename AnyTypeList, typename T>
+struct TypeListContainsSuperOf {
+ static const bool value =
+ llvm::is_base_of<typename AnyTypeList::head, T>::value ||
+ TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
+};
+template <typename T>
+struct TypeListContainsSuperOf<EmptyTypeList, T> {
+ static const bool value = false;
+};
+
+/// \brief A "type list" that contains all types.
+///
+/// Useful for matchers like \c anything and \c unless.
+typedef TypeList<
+ TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc>,
+ TypeList<QualType, Type, TypeLoc, CXXCtorInitializer> > AllNodeBaseTypes;
+
+/// \brief Helper meta-function to extract the argument out of a function of
+/// type void(Arg).
+///
+/// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details.
+template <class T> struct ExtractFunctionArgMeta;
+template <class T> struct ExtractFunctionArgMeta<void(T)> {
+ typedef T type;
+};
+
+/// \brief Default type lists for ArgumentAdaptingMatcher matchers.
+typedef AllNodeBaseTypes AdaptativeDefaultFromTypes;
+typedef TypeList<TypeList<Decl, Stmt, NestedNameSpecifier>,
+ TypeList<NestedNameSpecifierLoc, TypeLoc, QualType> >
+AdaptativeDefaultToTypes;
+
+/// \brief All types that are supported by HasDeclarationMatcher above.
+typedef TypeList<TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType>,
+ TypeList<InjectedClassNameType, LabelStmt, MemberExpr>,
+ TypeList<QualType, RecordType, TagType>,
+ TypeList<TemplateSpecializationType, TemplateTypeParmType,
+ TypedefType, UnresolvedUsingType> >
+HasDeclarationSupportedTypes;
+
/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
/// "adapting" a \c To into a \c T.
///
@@ -646,19 +904,33 @@ protected:
/// If a matcher does not need knowledge about the inner type, prefer to use
/// PolymorphicMatcherWithParam1.
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
- typename T>
-class ArgumentAdaptingMatcher {
-public:
- explicit ArgumentAdaptingMatcher(const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
+ typename FromTypes = AdaptativeDefaultFromTypes,
+ typename ToTypes = AdaptativeDefaultToTypes>
+struct ArgumentAdaptingMatcherFunc {
+ template <typename T> class Adaptor {
+ public:
+ explicit Adaptor(const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
- template <typename To>
- operator Matcher<To>() const {
- return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ typedef ToTypes ReturnTypes;
+
+ template <typename To> operator Matcher<To>() const {
+ return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ }
+
+ private:
+ const Matcher<T> InnerMatcher;
+ };
+
+ template <typename T>
+ static Adaptor<T> create(const Matcher<T> &InnerMatcher) {
+ return Adaptor<T>(InnerMatcher);
}
-private:
- const Matcher<T> InnerMatcher;
+ template <typename T>
+ Adaptor<T> operator()(const Matcher<T> &InnerMatcher) const {
+ return create(InnerMatcher);
+ }
};
/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
@@ -673,24 +945,33 @@ private:
/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42)
/// creates an object that can be used as a Matcher<T> for any type T
/// where a ValueEqualsMatcher<T, int>(42) can be constructed.
-template <template <typename T> class MatcherT>
+template <template <typename T> class MatcherT,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam0 {
public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T>());
}
};
template <template <typename T, typename P1> class MatcherT,
- typename P1>
+ typename P1,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam1 {
public:
explicit PolymorphicMatcherWithParam1(const P1 &Param1)
: Param1(Param1) {}
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T, P1>(Param1));
}
@@ -699,14 +980,19 @@ private:
};
template <template <typename T, typename P1, typename P2> class MatcherT,
- typename P1, typename P2>
+ typename P1, typename P2,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
class PolymorphicMatcherWithParam2 {
public:
PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
: Param1(Param1), Param2(Param2) {}
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
template <typename T>
operator Matcher<T>() const {
+ TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
+ right_polymorphic_conversion);
return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
}
@@ -737,27 +1023,6 @@ public:
}
};
-/// \brief Provides a MatcherInterface<T> for a Matcher<To> that matches if T is
-/// dyn_cast'able into To and the given Matcher<To> matches on the dyn_cast'ed
-/// node.
-template <typename T, typename To>
-class DynCastMatcher : public MatcherInterface<T> {
-public:
- explicit DynCastMatcher(const Matcher<To> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
-
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- const To *InnerMatchValue = dyn_cast<To>(&Node);
- return InnerMatchValue != NULL &&
- InnerMatcher.matches(*InnerMatchValue, Finder, Builder);
- }
-
-private:
- const Matcher<To> InnerMatcher;
-};
-
/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the matched node
/// to an ID if the inner matcher matches on the node.
template <typename T>
@@ -790,7 +1055,8 @@ private:
template <typename T>
class BindableMatcher : public Matcher<T> {
public:
- BindableMatcher(MatcherInterface<T> *Implementation)
+ explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
+ explicit BindableMatcher(MatcherInterface<T> *Implementation)
: Matcher<T>(Implementation) {}
/// \brief Returns a matcher that will bind the matched node on a match.
@@ -867,108 +1133,172 @@ public:
virtual bool matches(const T &Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return !InnerMatcher.matches(Node, Finder, Builder);
+ // The 'unless' matcher will always discard the result:
+ // If the inner matcher doesn't match, unless returns true,
+ // but the inner matcher cannot have bound anything.
+ // If the inner matcher matches, the result is false, and
+ // any possible binding will be discarded.
+ // We still need to hand in all the bound nodes up to this
+ // point so the inner matcher can depend on bound nodes,
+ // and we need to actively discard the bound nodes, otherwise
+ // the inner matcher will reset the bound nodes if it doesn't
+ // match, but this would be inversed by 'unless'.
+ BoundNodesTreeBuilder Discard(*Builder);
+ return !InnerMatcher.matches(Node, Finder, &Discard);
}
private:
const Matcher<T> InnerMatcher;
};
-/// \brief Matches nodes of type T for which both provided matchers match.
-///
-/// Type arguments MatcherT1 and MatcherT2 are required by
-/// PolymorphicMatcherWithParam2 but not actually used. They will
-/// always be instantiated with types convertible to Matcher<T>.
-template <typename T, typename MatcherT1, typename MatcherT2>
-class AllOfMatcher : public MatcherInterface<T> {
+/// \brief VariadicOperatorMatcher related types.
+/// @{
+
+/// \brief Function signature for any variadic operator. It takes the inner
+/// matchers as an array of DynTypedMatcher.
+typedef bool (*VariadicOperatorFunction)(
+ const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers);
+
+/// \brief \c MatcherInterface<T> implementation for an variadic operator.
+template <typename T>
+class VariadicOperatorMatcherInterface : public MatcherInterface<T> {
public:
- AllOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2)
- : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
+ VariadicOperatorMatcherInterface(VariadicOperatorFunction Func,
+ ArrayRef<const Matcher<T> *> InputMatchers)
+ : Func(Func) {
+ for (size_t i = 0, e = InputMatchers.size(); i != e; ++i) {
+ InnerMatchers.push_back(*InputMatchers[i]);
+ }
+ }
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
+ virtual bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return InnerMatcher1.matches(Node, Finder, Builder) &&
- InnerMatcher2.matches(Node, Finder, Builder);
+ return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder,
+ InnerMatchers);
}
private:
- const Matcher<T> InnerMatcher1;
- const Matcher<T> InnerMatcher2;
+ const VariadicOperatorFunction Func;
+ std::vector<DynTypedMatcher> InnerMatchers;
};
-/// \brief Matches nodes of type T for which at least one of the two provided
-/// matchers matches.
+/// \brief "No argument" placeholder to use as template paratemers.
+struct VariadicOperatorNoArg {};
+
+/// \brief Polymorphic matcher object that uses a \c VariadicOperatorFunction
+/// operator.
///
-/// Type arguments MatcherT1 and MatcherT2 are
-/// required by PolymorphicMatcherWithParam2 but not actually
-/// used. They will always be instantiated with types convertible to
-/// Matcher<T>.
-template <typename T, typename MatcherT1, typename MatcherT2>
-class EachOfMatcher : public MatcherInterface<T> {
+/// Input matchers can have any type (including other polymorphic matcher
+/// types), and the actual Matcher<T> is generated on demand with an implicit
+/// coversion operator.
+template <typename P1, typename P2,
+ typename P3 = VariadicOperatorNoArg,
+ typename P4 = VariadicOperatorNoArg,
+ typename P5 = VariadicOperatorNoArg>
+class VariadicOperatorMatcher {
public:
- EachOfMatcher(const Matcher<T> &InnerMatcher1,
- const Matcher<T> &InnerMatcher2)
- : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {
+ VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1,
+ const P2 &Param2,
+ const P3 &Param3 = VariadicOperatorNoArg(),
+ const P4 &Param4 = VariadicOperatorNoArg(),
+ const P5 &Param5 = VariadicOperatorNoArg())
+ : Func(Func), Param1(Param1), Param2(Param2), Param3(Param3),
+ Param4(Param4), Param5(Param5) {}
+
+ template <typename T> operator Matcher<T>() const {
+ Matcher<T> *Array[5];
+ size_t Size = 0;
+
+ addMatcher<T>(Param1, Array, Size);
+ addMatcher<T>(Param2, Array, Size);
+ addMatcher<T>(Param3, Array, Size);
+ addMatcher<T>(Param4, Array, Size);
+ addMatcher<T>(Param5, Array, Size);
+ Matcher<T> Result(new VariadicOperatorMatcherInterface<T>(
+ Func, ArrayRef<const Matcher<T> *>(Array, Size)));
+ for (size_t i = 0, e = Size; i != e; ++i) delete Array[i];
+ return Result;
}
- virtual bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- BoundNodesTreeBuilder Builder1;
- bool Matched1 = InnerMatcher1.matches(Node, Finder, &Builder1);
- if (Matched1)
- Builder->addMatch(Builder1.build());
-
- BoundNodesTreeBuilder Builder2;
- bool Matched2 = InnerMatcher2.matches(Node, Finder, &Builder2);
- if (Matched2)
- Builder->addMatch(Builder2.build());
-
- return Matched1 || Matched2;
+private:
+ template <typename T>
+ static void addMatcher(const Matcher<T> &M, Matcher<T> **Array,
+ size_t &Size) {
+ Array[Size++] = new Matcher<T>(M);
}
-private:
- const Matcher<T> InnerMatcher1;
- const Matcher<T> InnerMatcher2;
+ /// \brief Overload to ignore \c VariadicOperatorNoArg arguments.
+ template <typename T>
+ static void addMatcher(VariadicOperatorNoArg, Matcher<T> **Array,
+ size_t &Size) {}
+
+ const VariadicOperatorFunction Func;
+ const P1 Param1;
+ const P2 Param2;
+ const P3 Param3;
+ const P4 Param4;
+ const P5 Param5;
};
-/// \brief Matches nodes of type T for which at least one of the two provided
-/// matchers matches.
+/// \brief Overloaded function object to generate VariadicOperatorMatcher
+/// objects from arbitrary matchers.
///
-/// Type arguments MatcherT1 and MatcherT2 are
-/// required by PolymorphicMatcherWithParam2 but not actually
-/// used. They will always be instantiated with types convertible to
-/// Matcher<T>.
-template <typename T, typename MatcherT1, typename MatcherT2>
-class AnyOfMatcher : public MatcherInterface<T> {
-public:
- AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2)
- : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
+/// It supports 2-5 argument overloaded operator(). More can be added if needed.
+struct VariadicOperatorMatcherFunc {
+ VariadicOperatorFunction Func;
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return InnerMatcher1.matches(Node, Finder, Builder) ||
- InnerMatcher2.matches(Node, Finder, Builder);
+ template <typename M1, typename M2>
+ VariadicOperatorMatcher<M1, M2> operator()(const M1 &P1, const M2 &P2) const {
+ return VariadicOperatorMatcher<M1, M2>(Func, P1, P2);
+ }
+ template <typename M1, typename M2, typename M3>
+ VariadicOperatorMatcher<M1, M2, M3> operator()(const M1 &P1, const M2 &P2,
+ const M3 &P3) const {
+ return VariadicOperatorMatcher<M1, M2, M3>(Func, P1, P2, P3);
+ }
+ template <typename M1, typename M2, typename M3, typename M4>
+ VariadicOperatorMatcher<M1, M2, M3, M4>
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4>(Func, P1, P2, P3, P4);
+ }
+ template <typename M1, typename M2, typename M3, typename M4, typename M5>
+ VariadicOperatorMatcher<M1, M2, M3, M4, M5>
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
+ const M5 &P5) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Func, P1, P2, P3, P4,
+ P5);
}
-
-private:
- const Matcher<T> InnerMatcher1;
- const Matcher<T> InnerMatcher2;
};
+/// @}
+
+/// \brief Matches nodes for which all provided matchers match.
+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<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<DynTypedMatcher> InnerMatchers);
+
/// \brief Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
- if (InnerMatchers.empty())
- return BindableMatcher<T>(new TrueMatcher<T>);
- MatcherInterface<T> *InnerMatcher = new TrueMatcher<T>;
- for (int i = InnerMatchers.size() - 1; i >= 0; --i) {
- InnerMatcher = new AllOfMatcher<T, Matcher<T>, Matcher<T> >(
- *InnerMatchers[i], makeMatcher(InnerMatcher));
- }
- return BindableMatcher<T>(InnerMatcher);
+ return BindableMatcher<T>(new VariadicOperatorMatcherInterface<T>(
+ AllOfVariadicOperator, InnerMatchers));
}
/// \brief Creates a Matcher<T> that matches if
@@ -980,8 +1310,8 @@ BindableMatcher<T> makeAllOfComposite(
template<typename T, typename InnerT>
BindableMatcher<T> makeDynCastAllOfComposite(
ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(
- makeAllOfComposite(InnerMatchers)));
+ return BindableMatcher<T>(DynTypedMatcher(makeAllOfComposite(InnerMatchers))
+ .unconditionalConvertTo<T>());
}
/// \brief Matches nodes of type T that have at least one descendant node of
@@ -1233,9 +1563,53 @@ private:
TypeLoc (T::*TraverseFunction)() const;
};
-template <typename T, typename InnerT>
-T makeTypeAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
- return T(makeAllOfComposite<InnerT>(InnerMatchers));
+/// \brief Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where
+/// \c OuterT is any type that is supported by \c Getter.
+///
+/// \code Getter<OuterT>::value() \endcode returns a
+/// \code InnerTBase (OuterT::*)() \endcode, which is used to adapt a \c OuterT
+/// object into a \c InnerT
+template <typename InnerTBase,
+ template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl,
+ typename ReturnTypesF>
+class TypeTraversePolymorphicMatcher {
+private:
+ typedef TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF> Self;
+ static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers);
+
+public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
+ explicit TypeTraversePolymorphicMatcher(
+ ArrayRef<const Matcher<InnerTBase> *> InnerMatchers)
+ : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
+
+ template <typename OuterT> operator Matcher<OuterT>() const {
+ return Matcher<OuterT>(
+ new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
+ }
+
+ struct Func : public llvm::VariadicFunction<Self, Matcher<InnerTBase>,
+ &Self::create> {
+ Func() {}
+ };
+
+private:
+ const Matcher<InnerTBase> InnerMatcher;
+};
+
+// Define the create() method out of line to silence a GCC warning about
+// the struct "Func" having greater visibility than its base, which comes from
+// using the flag -fvisibility-inlines-hidden.
+template <typename InnerTBase, template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl, typename ReturnTypesF>
+TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
+TypeTraversePolymorphicMatcher<
+ InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF>::create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) {
+ return Self(InnerMatchers);
}
} // end namespace internal
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index f5ca26b..b5d5303 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -49,23 +49,19 @@
///
/// The code should return true if 'Node' matches.
#define AST_MATCHER(Type, DefineMatcher) \
- AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0)
-
-#define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId) \
namespace internal { \
- class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<Type> { \
+ class matcher_##DefineMatcher##Matcher : public MatcherInterface<Type> { \
public: \
- explicit matcher_##DefineMatcher##OverloadId##Matcher() {} \
+ explicit matcher_##DefineMatcher##Matcher() {} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher() { \
return internal::makeMatcher( \
- new internal::matcher_##DefineMatcher##OverloadId##Matcher()); \
+ new internal::matcher_##DefineMatcher##Matcher()); \
} \
- inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
+ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
@@ -93,10 +89,10 @@
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
const ParamType &A##Param) \
- : Param(A##Param) { \
- } \
+ : Param(A##Param) {} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType Param; \
}; \
@@ -105,6 +101,8 @@
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
} \
+ typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType &Param); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
@@ -136,53 +134,70 @@
public: \
matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
const ParamType2 &A##Param2) \
- : Param1(A##Param1), Param2(A##Param2) { \
- } \
+ : Param1(A##Param1), Param2(A##Param2) {} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
}; \
} \
- inline internal::Matcher<Type> \
- DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
+ inline internal::Matcher<Type> DefineMatcher(const ParamType1 &Param1, \
+ const ParamType2 &Param2) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
Param2)); \
} \
+ typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType1 &Param1, const ParamType2 &Param2); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
+/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
+/// macros.
+///
+/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
+/// will look at that as two arguments. However, you can pass
+/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
+/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
+/// extract the TypeList object.
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_1(t1) void(internal::TypeList<t1>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2) \
+ void(internal::TypeList<t1, t2>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3) \
+ void(internal::TypeList<t1, t2, t3>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_4(t1, t2, t3, t4) \
+ void(internal::TypeList<t1, t2, t3, t4>)
+#define AST_POLYMORPHIC_SUPPORTED_TYPES_5(t1, t2, t3, t4, t5) \
+ void(internal::TypeList<t1, t2, t3, internal::TypeList<t4, t5> >)
+
/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
/// from the calling context.
-#define AST_POLYMORPHIC_MATCHER(DefineMatcher) \
- AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0)
-
-#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId) \
+#define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \
namespace internal { \
template <typename NodeType> \
- class matcher_##DefineMatcher##OverloadId##Matcher \
- : public MatcherInterface<NodeType> { \
+ class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \
public: \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
}; \
} \
inline internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \
+ DefineMatcher() { \
return internal::PolymorphicMatcherWithParam0< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher>(); \
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \
} \
template <typename NodeType> \
- bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
- NodeType>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const
+ bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \
+ const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const
/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that is
@@ -193,11 +208,13 @@
/// of the matcher Matcher<NodeType> returned by the function matcher().
///
/// FIXME: Pull out common code with above macro?
-#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \
- AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0)
+#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \
+ Param) \
+ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \
+ Param, 0)
-#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, \
- OverloadId) \
+#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType, Param, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT> \
class matcher_##DefineMatcher##OverloadId##Matcher \
@@ -205,21 +222,25 @@
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
const ParamType &A##Param) \
- : Param(A##Param) { \
- } \
+ : Param(A##Param) {} \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType Param; \
}; \
} \
inline internal::PolymorphicMatcherWithParam1< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType> \
- DefineMatcher(const ParamType &Param) { \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF> DefineMatcher(const ParamType &Param) { \
return internal::PolymorphicMatcherWithParam1< \
- internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>( \
- Param); \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF>(Param); \
} \
+ typedef internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType &Param); \
template <typename NodeType, typename ParamT> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
@@ -233,13 +254,14 @@
/// The variables are the same as for AST_MATCHER_P2, with the
/// addition of NodeType, which specifies the node type of the matcher
/// Matcher<NodeType> returned by the function DefineMatcher().
-#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2) \
- AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2, 0)
+#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2) \
+ AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2, 0)
-#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
- ParamType2, Param2, OverloadId) \
+#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType1, Param1, ParamType2, \
+ Param2, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT1, typename ParamT2> \
class matcher_##DefineMatcher##OverloadId##Matcher \
@@ -247,10 +269,10 @@
public: \
matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
const ParamType2 &A##Param2) \
- : Param1(A##Param1), Param2(A##Param2) { \
- } \
+ : Param1(A##Param1), Param2(A##Param2) {} \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
+ \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
@@ -258,12 +280,16 @@
} \
inline internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2> \
- DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
+ ParamType2, ReturnTypesF> DefineMatcher(const ParamType1 &Param1, \
+ const ParamType2 &Param2) { \
return internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2>(Param1, Param2); \
+ ParamType2, ReturnTypesF>(Param1, Param2); \
} \
+ typedef internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+ ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
+ const ParamType1 &Param1, const ParamType2 &Param2); \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT1, ParamT2>::matches( \
@@ -282,64 +308,29 @@
/// to another.
///
/// For a specific \c SpecificType, the traversal is done using
-/// \c SpecificType::FunctionName. The existance of such a function determines
+/// \c SpecificType::FunctionName. The existence of such a function determines
/// whether a corresponding matcher can be used on \c SpecificType.
-#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \
- class Polymorphic##MatcherName##TypeMatcher { \
- public: \
- Polymorphic##MatcherName##TypeMatcher( \
- const internal::Matcher<QualType> &InnerMatcher) \
- : InnerMatcher(InnerMatcher) { \
- } \
- template <typename T> operator internal:: Matcher< T>() { \
- return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \
- InnerMatcher, &T::FunctionName)); \
- } \
- private: \
- const internal::Matcher<QualType> InnerMatcher; \
- } \
- ; \
- class Variadic##MatcherName##TypeTraverseMatcher \
- : public llvm::VariadicFunction< \
- Polymorphic##MatcherName##TypeMatcher, internal::Matcher<QualType>, \
- internal::makeTypeAllOfComposite< \
- Polymorphic##MatcherName##TypeMatcher, QualType> > { \
- public: \
- Variadic##MatcherName##TypeTraverseMatcher() { \
- } \
+#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeMatcher##MatcherName##Getter { \
+ static QualType (T::*value())() const { return &T::FunctionName; } \
+ }; \
} \
- ; \
- const Variadic##MatcherName##TypeTraverseMatcher MatcherName
+ const internal::TypeTraversePolymorphicMatcher< \
+ QualType, internal::TypeMatcher##MatcherName##Getter, \
+ internal::TypeTraverseMatcher, ReturnTypesF>::Func MatcherName
/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
-#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \
- class Polymorphic##MatcherName##TypeLocMatcher { \
- public: \
- Polymorphic##MatcherName##TypeLocMatcher( \
- const internal::Matcher<TypeLoc> &InnerMatcher) \
- : InnerMatcher(InnerMatcher) { \
- } \
- template <typename T> operator internal:: Matcher< T>() { \
- return internal::Matcher<T>( \
- new internal::TypeLocTraverseMatcher<T>(InnerMatcher, \
- &T::FunctionName##Loc)); \
- } \
- private: \
- const internal::Matcher<TypeLoc> InnerMatcher; \
- } \
- ; \
- class Variadic##MatcherName##TypeLocTraverseMatcher \
- : public llvm::VariadicFunction< \
- Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher<TypeLoc>,\
- internal::makeTypeAllOfComposite< \
- Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \
- public: \
- Variadic##MatcherName##TypeLocTraverseMatcher() { \
- } \
+#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
+ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
+ }; \
} \
- ; \
- const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \
- AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type)
+ const internal::TypeTraversePolymorphicMatcher< \
+ TypeLoc, internal::TypeLocMatcher##MatcherName##Getter, \
+ internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \
+ AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
new file mode 100644
index 0000000..aec0c0e
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -0,0 +1,185 @@
+//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Diagnostics class to manage error messages.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+
+#include <string>
+#include <vector>
+
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+struct SourceLocation {
+ SourceLocation() : Line(), Column() {}
+ unsigned Line;
+ unsigned Column;
+};
+
+struct SourceRange {
+ SourceLocation Start;
+ SourceLocation End;
+};
+
+/// \brief A VariantValue instance annotated with its parser context.
+struct ParserValue {
+ ParserValue() : Text(), Range(), Value() {}
+ StringRef Text;
+ SourceRange Range;
+ VariantValue Value;
+};
+
+/// \brief Helper class to manage error messages.
+class Diagnostics {
+public:
+ /// \brief Parser context types.
+ enum ContextType {
+ CT_MatcherArg = 0,
+ CT_MatcherConstruct = 1
+ };
+
+ /// \brief All errors from the system.
+ enum ErrorType {
+ ET_None = 0,
+
+ ET_RegistryNotFound = 1,
+ ET_RegistryWrongArgCount = 2,
+ ET_RegistryWrongArgType = 3,
+ ET_RegistryNotBindable = 4,
+ ET_RegistryAmbiguousOverload = 5,
+
+ ET_ParserStringError = 100,
+ ET_ParserNoOpenParen = 101,
+ ET_ParserNoCloseParen = 102,
+ ET_ParserNoComma = 103,
+ ET_ParserNoCode = 104,
+ ET_ParserNotAMatcher = 105,
+ ET_ParserInvalidToken = 106,
+ ET_ParserMalformedBindExpr = 107,
+ ET_ParserTrailingCode = 108,
+ ET_ParserUnsignedError = 109,
+ ET_ParserOverloadedType = 110
+ };
+
+ /// \brief Helper stream class.
+ class ArgStream {
+ public:
+ ArgStream(std::vector<std::string> *Out) : Out(Out) {}
+ template <class T> ArgStream &operator<<(const T &Arg) {
+ return operator<<(Twine(Arg));
+ }
+ ArgStream &operator<<(const Twine &Arg);
+
+ private:
+ std::vector<std::string> *Out;
+ };
+
+ /// \brief Class defining a parser context.
+ ///
+ /// Used by the parser to specify (possibly recursive) contexts where the
+ /// parsing/construction can fail. Any error triggered within a context will
+ /// keep information about the context chain.
+ /// This class should be used as a RAII instance in the stack.
+ struct Context {
+ public:
+ /// \brief About to call the constructor for a matcher.
+ enum ConstructMatcherEnum { ConstructMatcher };
+ Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
+ const SourceRange &MatcherRange);
+ /// \brief About to recurse into parsing one argument for a matcher.
+ enum MatcherArgEnum { MatcherArg };
+ Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
+ const SourceRange &MatcherRange, unsigned ArgNumber);
+ ~Context();
+
+ private:
+ Diagnostics *const Error;
+ };
+
+ /// \brief Context for overloaded matcher construction.
+ ///
+ /// This context will take care of merging all errors that happen within it
+ /// as "candidate" overloads for the same matcher.
+ struct OverloadContext {
+ public:
+ OverloadContext(Diagnostics* Error);
+ ~OverloadContext();
+
+ /// \brief Revert all errors that happened within this context.
+ void revertErrors();
+
+ private:
+ Diagnostics *const Error;
+ unsigned BeginIndex;
+ };
+
+ /// \brief Add an error to the diagnostics.
+ ///
+ /// All the context information will be kept on the error message.
+ /// \return a helper class to allow the caller to pass the arguments for the
+ /// error message, using the << operator.
+ ArgStream addError(const SourceRange &Range, ErrorType Error);
+
+ /// \brief Information stored for one frame of the context.
+ struct ContextFrame {
+ ContextType Type;
+ SourceRange Range;
+ std::vector<std::string> Args;
+ };
+
+ /// \brief Information stored for each error found.
+ struct ErrorContent {
+ std::vector<ContextFrame> ContextStack;
+ struct Message {
+ SourceRange Range;
+ ErrorType Type;
+ std::vector<std::string> Args;
+ };
+ std::vector<Message> Messages;
+ };
+ ArrayRef<ErrorContent> errors() const { return Errors; }
+
+ /// \brief Returns a simple string representation of each error.
+ ///
+ /// Each error only shows the error message without any context.
+ void printToStream(llvm::raw_ostream &OS) const;
+ std::string toString() const;
+
+ /// \brief Returns the full string representation of each error.
+ ///
+ /// Each error message contains the full context.
+ void printToStreamFull(llvm::raw_ostream &OS) const;
+ std::string toStringFull() const;
+
+private:
+ /// \brief Helper function used by the constructors of ContextFrame.
+ ArgStream pushContextFrame(ContextType Type, SourceRange Range);
+
+ std::vector<ContextFrame> ContextStack;
+ std::vector<ErrorContent> Errors;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
new file mode 100644
index 0000000..bb6ac76
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -0,0 +1,151 @@
+//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Simple matcher expression parser.
+///
+/// The parser understands matcher expressions of the form:
+/// MatcherName(Arg0, Arg1, ..., ArgN)
+/// as well as simple types like strings.
+/// The parser does not know how to process the matchers. It delegates this task
+/// to a Sema object received as an argument.
+///
+/// \code
+/// Grammar for the expressions supported:
+/// <Expression> := <Literal> | <MatcherExpression>
+/// <Literal> := <StringLiteral> | <Unsigned>
+/// <StringLiteral> := "quoted string"
+/// <Unsigned> := [0-9]+
+/// <MatcherExpression> := <MatcherName>(<ArgumentList>) |
+/// <MatcherName>(<ArgumentList>).bind(<StringLiteral>)
+/// <MatcherName> := [a-zA-Z]+
+/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
+/// \endcode
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#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 {
+namespace ast_matchers {
+namespace dynamic {
+
+/// \brief Matcher expression parser.
+class Parser {
+public:
+ /// \brief Interface to connect the parser with the registry and more.
+ ///
+ /// The parser uses the Sema instance passed into
+ /// parseMatcherExpression() to handle all matcher tokens. The simplest
+ /// processor implementation would simply call into the registry to create
+ /// the matchers.
+ /// However, a more complex processor might decide to intercept the matcher
+ /// creation and do some extra work. For example, it could apply some
+ /// transformation to the matcher by adding some id() nodes, or could detect
+ /// specific matcher nodes for more efficient lookup.
+ class Sema {
+ public:
+ virtual ~Sema();
+
+ /// \brief Process a matcher expression.
+ ///
+ /// All the arguments passed here have already been processed.
+ ///
+ /// \param MatcherName The matcher name found by the parser.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param BindID The ID to use to bind the matcher, or a null \c StringRef
+ /// if no ID is specified.
+ ///
+ /// \param Args The argument list for the matcher.
+ ///
+ /// \return The matcher objects constructed by the processor, or a null
+ /// matcher if an error occurred. In that case, \c Error will contain a
+ /// description of the error.
+ virtual VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) = 0;
+ };
+
+ /// \brief Parse a matcher expression, creating matchers from the registry.
+ ///
+ /// This overload creates matchers calling directly into the registry. If the
+ /// caller needs more control over how the matchers are created, then it can
+ /// use the overload below that takes a Sema.
+ ///
+ /// \param MatcherCode The matcher expression to parse.
+ ///
+ /// \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 llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error);
+
+ /// \brief Parse a matcher expression.
+ ///
+ /// \param MatcherCode The matcher expression to parse.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers.
+ /// \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 llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error);
+
+ /// \brief Parse an expression, creating matchers from the registry.
+ ///
+ /// Parses any expression supported by this parser. In general, the
+ /// \c parseMatcherExpression function is a better approach to get a matcher
+ /// object.
+ static bool parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error);
+
+ /// \brief Parse an expression.
+ ///
+ /// Parses any expression supported by this parser. In general, the
+ /// \c parseMatcherExpression function is a better approach to get a matcher
+ /// object.
+ static bool parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error);
+
+private:
+ class CodeTokenizer;
+ struct TokenInfo;
+
+ Parser(CodeTokenizer *Tokenizer, Sema *S,
+ Diagnostics *Error);
+
+ bool parseExpressionImpl(VariantValue *Value);
+ bool parseMatcherExpressionImpl(VariantValue *Value);
+
+ CodeTokenizer *const Tokenizer;
+ Sema *const S;
+ Diagnostics *const Error;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
new file mode 100644
index 0000000..c113c14
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -0,0 +1,75 @@
+//===--- Registry.h - Matcher registry -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Registry of all known matchers.
+///
+/// The registry provides a generic interface to construct any matcher by name.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+class Registry {
+public:
+ /// \brief Construct a matcher from the registry by name.
+ ///
+ /// Consult the registry of known matchers and construct the appropriate
+ /// matcher by name.
+ ///
+ /// \param MatcherName The name of the matcher to instantiate.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param Args The argument list for the matcher. The number and types of the
+ /// values must be valid for the matcher requested. Otherwise, the function
+ /// will return an error.
+ ///
+ /// \return The matcher object constructed if no error was found.
+ /// A null matcher if the matcher is not found, or if the number of
+ /// arguments or argument types do not match the signature.
+ /// In that case \c Error will contain the description of the error.
+ static VariantMatcher constructMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+ /// \brief Construct a matcher from the registry and bind it.
+ ///
+ /// Similar the \c constructMatcher() above, but it then tries to bind the
+ /// matcher to the specified \c BindID.
+ /// If the matcher is not bindable, it sets an error in \c Error and returns
+ /// a null matcher.
+ static VariantMatcher constructBoundMatcher(StringRef MatcherName,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+private:
+ Registry() LLVM_DELETED_FUNCTION;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
new file mode 100644
index 0000000..b9bc017
--- /dev/null
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -0,0 +1,261 @@
+//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Polymorphic value type.
+///
+/// Supports all the types required for dynamic Matcher construction.
+/// Used by the registry to construct matchers in a generic way.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+
+#include <vector>
+
+#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"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+using ast_matchers::internal::DynTypedMatcher;
+
+/// \brief A variant matcher object.
+///
+/// The purpose of this object is to abstract simple and polymorphic matchers
+/// into a single object type.
+/// Polymorphic matchers might be implemented as a list of all the possible
+/// overloads of the matcher. \c VariantMatcher knows how to select the
+/// appropriate overload when needed.
+/// To get a real matcher object out of a \c VariantMatcher you can do:
+/// - getSingleMatcher() which returns a matcher, only if it is not ambiguous
+/// to decide which matcher to return. Eg. it contains only a single
+/// matcher, or a polymorphic one with only one overload.
+/// - 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;
+ virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
+ virtual void constructVariadicOperator(
+ ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> InnerMatchers) = 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 llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
+ virtual std::string getTypeAsString() const = 0;
+ virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
+ };
+
+public:
+ /// \brief A null matcher.
+ VariantMatcher();
+
+ /// \brief Clones the provided matcher.
+ static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
+
+ /// \brief Clones the provided matchers.
+ ///
+ /// They should be the result of a polymorphic matcher.
+ static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers);
+
+ /// \brief Creates a 'variadic' operator matcher.
+ ///
+ /// It will bind to the appropriate type on getTypedMatcher<T>().
+ static VariantMatcher VariadicOperatorMatcher(
+ ast_matchers::internal::VariadicOperatorFunction Func,
+ ArrayRef<VariantMatcher> Args);
+
+ /// \brief Makes the matcher the "null" matcher.
+ void reset();
+
+ /// \brief Whether the matcher is null.
+ bool isNull() const { return !Value; }
+
+ /// \brief Return a single matcher, if there is no ambiguity.
+ ///
+ /// \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>.
+ ///
+ /// 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 {
+ TypedMatcherOps<T> Ops;
+ if (Value) Value->makeTypedMatcher(Ops);
+ return Ops.hasMatcher();
+ }
+
+ /// \brief Return this matcher 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 {
+ TypedMatcherOps<T> Ops;
+ Value->makeTypedMatcher(Ops);
+ assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false");
+ return Ops.matcher();
+ }
+
+ /// \brief String representation of the type of the value.
+ ///
+ /// If the underlying matcher is a polymorphic one, the string will show all
+ /// the types.
+ std::string getTypeAsString() const;
+
+private:
+ explicit VariantMatcher(Payload *Value) : Value(Value) {}
+
+ 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) const {
+ 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) {
+ const size_t NumArgs = InnerMatchers.size();
+ MatcherT **InnerArgs = new MatcherT *[NumArgs]();
+ bool HasError = false;
+ for (size_t i = 0; i != NumArgs; ++i) {
+ // Abort if any of the inner matchers can't be converted to
+ // Matcher<T>.
+ if (!InnerMatchers[i].hasTypedMatcher<T>()) {
+ HasError = true;
+ break;
+ }
+ InnerArgs[i] = new MatcherT(InnerMatchers[i].getTypedMatcher<T>());
+ }
+ if (!HasError) {
+ Out.reset(new MatcherT(
+ new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
+ Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs))));
+ }
+ for (size_t i = 0; i != NumArgs; ++i) {
+ delete InnerArgs[i];
+ }
+ delete[] InnerArgs;
+ }
+
+ bool hasMatcher() const { return Out.get() != NULL; }
+ const MatcherT &matcher() const { return *Out; }
+
+ private:
+ OwningPtr<MatcherT> Out;
+ };
+
+ IntrusiveRefCntPtr<const Payload> Value;
+};
+
+/// \brief Variant value class.
+///
+/// Basically, a tagged union with value type semantics.
+/// It is used by the registry as the return value and argument type for the
+/// matcher factory methods.
+/// It can be constructed from any of the supported types. It supports
+/// copy/assignment.
+///
+/// Supported types:
+/// - \c unsigned
+/// - \c std::string
+/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
+class VariantValue {
+public:
+ VariantValue() : Type(VT_Nothing) {}
+
+ VariantValue(const VariantValue &Other);
+ ~VariantValue();
+ VariantValue &operator=(const VariantValue &Other);
+
+ /// \brief Specific constructors for each supported type.
+ VariantValue(unsigned Unsigned);
+ VariantValue(const std::string &String);
+ VariantValue(const VariantMatcher &Matchers);
+
+ /// \brief Unsigned value functions.
+ bool isUnsigned() const;
+ unsigned getUnsigned() const;
+ void setUnsigned(unsigned Unsigned);
+
+ /// \brief String value functions.
+ bool isString() const;
+ const std::string &getString() const;
+ void setString(const std::string &String);
+
+ /// \brief Matcher value functions.
+ bool isMatcher() const;
+ const VariantMatcher &getMatcher() const;
+ void setMatcher(const VariantMatcher &Matcher);
+
+ /// \brief String representation of the type of the value.
+ std::string getTypeAsString() const;
+
+private:
+ void reset();
+
+ /// \brief All supported value types.
+ enum ValueType {
+ VT_Nothing,
+ VT_Unsigned,
+ VT_String,
+ VT_Matcher
+ };
+
+ /// \brief All supported value types.
+ union AllValues {
+ unsigned Unsigned;
+ std::string *String;
+ VariantMatcher *Matcher;
+ };
+
+ ValueType Type;
+ AllValues Value;
+};
+
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
OpenPOWER on IntegriCloud