aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h724
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h120
-rw-r--r--lib/ASTMatchers/ASTMatchFinder.cpp120
-rw-r--r--lib/ASTMatchers/ASTMatchersInternal.cpp26
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp252
5 files changed, 884 insertions, 358 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 69e9c4b53d..ac3ff732e9 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -45,9 +45,11 @@
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Regex.h"
namespace clang {
namespace ast_matchers {
@@ -78,8 +80,8 @@ public:
private:
/// \brief Create BoundNodes from a pre-filled map of bindings.
- BoundNodes(const std::map<std::string, const clang::Decl*> &DeclBindings,
- const std::map<std::string, const clang::Stmt*> &StmtBindings)
+ BoundNodes(const std::map<std::string, const Decl*> &DeclBindings,
+ const std::map<std::string, const Stmt*> &StmtBindings)
: DeclBindings(DeclBindings), StmtBindings(StmtBindings) {}
template <typename T, typename MapT>
@@ -91,8 +93,8 @@ private:
return llvm::dyn_cast<T>(It->second);
}
- std::map<std::string, const clang::Decl*> DeclBindings;
- std::map<std::string, const clang::Stmt*> StmtBindings;
+ std::map<std::string, const Decl*> DeclBindings;
+ std::map<std::string, const Stmt*> StmtBindings;
friend class internal::BoundNodesTree;
};
@@ -109,9 +111,9 @@ internal::Matcher<T> id(const std::string &ID,
/// \brief Types of matchers for the top-level classes in the AST class
/// hierarchy.
/// @{
-typedef internal::Matcher<clang::Decl> DeclarationMatcher;
-typedef internal::Matcher<clang::QualType> TypeMatcher;
-typedef internal::Matcher<clang::Stmt> StatementMatcher;
+typedef internal::Matcher<Decl> DeclarationMatcher;
+typedef internal::Matcher<QualType> TypeMatcher;
+typedef internal::Matcher<Stmt> StatementMatcher;
/// @}
/// \brief Matches any node.
@@ -138,8 +140,8 @@ inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> anything()
/// } U;
/// };
const internal::VariadicDynCastAllOfMatcher<
- clang::Decl,
- clang::NamedDecl> nameableDeclaration;
+ Decl,
+ NamedDecl> nameableDeclaration;
/// \brief Matches C++ class declarations.
///
@@ -147,8 +149,91 @@ const internal::VariadicDynCastAllOfMatcher<
/// class X;
/// template<class T> class Z {};
const internal::VariadicDynCastAllOfMatcher<
- clang::Decl,
- clang::CXXRecordDecl> record;
+ Decl,
+ CXXRecordDecl> record;
+
+/// \brief Matches C++ class template specializations.
+///
+/// Given
+/// template<typename T> class A {};
+/// template<> class A<double> {};
+/// A<int> a;
+/// classTemplateSpecialization()
+/// matches the specializations \c A<int> and \c A<double>
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ClassTemplateSpecializationDecl> classTemplateSpecialization;
+
+/// \brief Matches classTemplateSpecializations that have at least one
+/// TemplateArgument matching the given Matcher.
+///
+/// Given
+/// template<typename T> class A {};
+/// template<> class A<double> {};
+/// A<int> a;
+/// classTemplateSpecialization(hasAnyTemplateArgument(
+/// refersToType(asString("int"))))
+/// matches the specialization \c A<int>
+AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
+ internal::Matcher<TemplateArgument>, Matcher) {
+ const TemplateArgumentList &List = Node.getTemplateArgs();
+ for (unsigned i = 0; i < List.size(); ++i) {
+ if (Matcher.matches(List.get(i), Finder, Builder))
+ return true;
+ }
+ return false;
+}
+
+/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
+/// matches the given Matcher.
+///
+/// Given
+/// template<typename T, typename U> class A {};
+/// A<bool, int> b;
+/// A<int, bool> c;
+/// classTemplateSpecialization(hasTemplateArgument(
+/// 1, refersToType(asString("int"))))
+/// matches the specialization \c A<bool, int>
+AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument,
+ unsigned, N, internal::Matcher<TemplateArgument>, Matcher) {
+ const TemplateArgumentList &List = Node.getTemplateArgs();
+ if (List.size() <= N)
+ return false;
+ return Matcher.matches(List.get(N), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument that refers to a certain type.
+///
+/// Given
+/// struct X {};
+/// template<typename T> struct A {};
+/// A<X> a;
+/// classTemplateSpecialization(hasAnyTemplateArgument(
+/// refersToType(class(hasName("X")))))
+/// matches the specialization \c A<X>
+AST_MATCHER_P(TemplateArgument, refersToType,
+ internal::Matcher<QualType>, Matcher) {
+ if (Node.getKind() != TemplateArgument::Type)
+ return false;
+ return Matcher.matches(Node.getAsType(), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument that refers to a certain declaration.
+///
+/// Given
+/// template<typename T> struct A {};
+/// struct B { B* next; };
+/// A<&B::next> a;
+/// classTemplateSpecialization(hasAnyTemplateArgument(
+/// refersToDeclaration(field(hasName("next"))))
+/// matches the specialization \c A<&B::next> with \c field(...) matching
+/// \c B::next
+AST_MATCHER_P(TemplateArgument, refersToDeclaration,
+ internal::Matcher<Decl>, Matcher) {
+ if (const Decl *Declaration = Node.getAsDecl())
+ return Matcher.matches(*Declaration, Finder, Builder);
+ return false;
+}
/// \brief Matches C++ constructor declarations.
///
@@ -160,16 +245,41 @@ const internal::VariadicDynCastAllOfMatcher<
/// int DoSomething();
/// };
const internal::VariadicDynCastAllOfMatcher<
- clang::Decl,
- clang::CXXConstructorDecl> constructor;
+ Decl,
+ CXXConstructorDecl> constructor;
+
+/// \brief Matches explicit C++ destructor declarations.
+///
+/// Example matches Foo::~Foo()
+/// class Foo {
+/// public:
+/// virtual ~Foo();
+/// };
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> destructor;
+
+/// \brief Matches enum declarations.
+///
+/// Example matches X
+/// enum X {
+/// A, B, C
+/// };
+const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
+
+/// \brief Matches enum constants.
+///
+/// Example matches A, B, C
+/// enum X {
+/// A, B, C
+/// };
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ EnumConstantDecl> enumConstant;
/// \brief Matches method declarations.
///
/// Example matches y
/// class X { void y() };
-const internal::VariadicDynCastAllOfMatcher<
- clang::Decl,
- clang::CXXMethodDecl> method;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> method;
/// \brief Matches variable declarations.
///
@@ -178,9 +288,7 @@ const internal::VariadicDynCastAllOfMatcher<
///
/// Example matches a
/// int a;
-const internal::VariadicDynCastAllOfMatcher<
- clang::Decl,
- clang::VarDecl> variable;
+const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> variable;
/// \brief Matches field declarations.
///
@@ -188,17 +296,13 @@ const internal::VariadicDynCastAllOfMatcher<
/// class X { int m; };
/// field()
/// matches 'm'.
-const internal::VariadicDynCastAllOfMatcher<
- clang::Decl,
- clang::FieldDecl> field;
+const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> field;
/// \brief Matches function declarations.
///
/// Example matches f
/// void f();
-const internal::VariadicDynCastAllOfMatcher<
- clang::Decl,
- clang::FunctionDecl> function;
+const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> function;
/// \brief Matches statements.
@@ -207,7 +311,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// { ++a; }
/// statement()
/// matches both the compound statement '{ ++a; }' and '++a'.
-const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::Stmt> statement;
+const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> statement;
/// \brief Matches declaration statements.
///
@@ -216,8 +320,8 @@ const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::Stmt> statement;
/// declarationStatement()
/// matches 'int a'.
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::DeclStmt> declarationStatement;
+ Stmt,
+ DeclStmt> declarationStatement;
/// \brief Matches member expressions.
///
@@ -229,15 +333,34 @@ const internal::VariadicDynCastAllOfMatcher<
/// memberExpression()
/// matches this->x, x, y.x, a, this->b
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::MemberExpr> memberExpression;
+ Stmt,
+ MemberExpr> memberExpression;
/// \brief Matches call expressions.
///
/// Example matches x.y()
/// X x;
/// x.y();
-const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::CallExpr> call;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> call;
+
+/// \brief Matches init list expressions.
+///
+/// Given
+/// int a[] = { 1, 2 };
+/// struct B { int x, y; };
+/// B b = { 5, 6 };
+/// initList()
+/// matches "{ 1, 2 }" and "{ 5, 6 }"
+const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
+
+/// \brief Matches using declarations.
+///
+/// Given
+/// namespace X { int x; }
+/// using X::x;
+/// usingDecl()
+/// matches \code using X::x \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
/// \brief Matches constructor call expressions (including implicit ones).
///
@@ -248,18 +371,18 @@ const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::CallExpr> call;
/// int n;
/// f(string(ptr, n), ptr);
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::CXXConstructExpr> constructorCall;
+ Stmt,
+ CXXConstructExpr> constructorCall;
/// \brief Matches nodes where temporaries are created.
///
/// Example matches FunctionTakesString(GetStringByValue())
-/// (matcher = bindTemporaryExpr())
+/// (matcher = bindTemporaryExpression())
/// FunctionTakesString(GetStringByValue());
/// FunctionTakesStringByPointer(GetStringPointer());
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::CXXBindTemporaryExpr> bindTemporaryExpression;
+ Stmt,
+ CXXBindTemporaryExpr> bindTemporaryExpression;
/// \brief Matches new expressions.
///
@@ -268,8 +391,28 @@ const internal::VariadicDynCastAllOfMatcher<
/// newExpression()
/// matches 'new X'.
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::CXXNewExpr> newExpression;
+ Stmt,
+ CXXNewExpr> newExpression;
+
+/// \brief Matches delete expressions.
+///
+/// Given
+/// delete X;
+/// deleteExpression()
+/// matches 'delete X'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXDeleteExpr> deleteExpression;
+
+/// \brief Matches array subscript expressions.
+///
+/// Given
+/// int i = a[1];
+/// arraySubscriptExpr()
+/// matches "a[1]"
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ArraySubscriptExpr> arraySubscriptExpr;
/// \brief Matches the value of a default argument at the call site.
///
@@ -279,8 +422,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// void f(int x, int y = 0);
/// f(42);
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::CXXDefaultArgExpr> defaultArgument;
+ Stmt,
+ CXXDefaultArgExpr> defaultArgument;
/// \brief Matches overloaded operator calls.
///
@@ -295,16 +438,16 @@ const internal::VariadicDynCastAllOfMatcher<
/// ostream &o; int b = 1, c = 1;
/// o << b << c;
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::CXXOperatorCallExpr> overloadedOperatorCall;
+ Stmt,
+ CXXOperatorCallExpr> overloadedOperatorCall;
/// \brief Matches expressions.
///
/// Example matches x()
/// void f() { x(); }
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::Expr> expression;
+ Stmt,
+ Expr> expression;
/// \brief Matches expressions that refer to declarations.
///
@@ -312,21 +455,21 @@ const internal::VariadicDynCastAllOfMatcher<
/// bool x;
/// if (x) {}
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::DeclRefExpr> declarationReference;
+ Stmt,
+ DeclRefExpr> declarationReference;
/// \brief Matches if statements.
///
/// Example matches 'if (x) {}'
/// if (x) {}
-const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::IfStmt> ifStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
/// \brief Matches for statements.
///
/// Example matches 'for (;;) {}'
/// for (;;) {}
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt, clang::ForStmt> forStmt;
+ Stmt, ForStmt> forStmt;
/// \brief Matches while statements.
///
@@ -335,8 +478,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// whileStmt()
/// matches 'while (true) {}'.
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::WhileStmt> whileStmt;
+ Stmt,
+ WhileStmt> whileStmt;
/// \brief Matches do statements.
///
@@ -344,7 +487,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// do {} while (true);
/// doStmt()
/// matches 'do {} while(true)'
-const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::DoStmt> doStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
/// \brief Matches case and default statements inside switch statements.
///
@@ -353,32 +496,32 @@ const internal::VariadicDynCastAllOfMatcher<clang::Stmt, clang::DoStmt> doStmt;
/// switchCase()
/// matches 'case 42: break;' and 'default: break;'.
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::SwitchCase> switchCase;
+ Stmt,
+ SwitchCase> switchCase;
/// \brief Matches compound statements.
///
/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
/// for (;;) {{}}
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::CompoundStmt> compoundStatement;
+ Stmt,
+ CompoundStmt> compoundStatement;
/// \brief Matches bool literals.
///
/// Example matches true
/// true
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::CXXBoolLiteralExpr> boolLiteral;
+ Expr,
+ CXXBoolLiteralExpr> boolLiteral;
/// \brief Matches string literals (also matches wide string literals).
///
/// Example matches "abcd", L"abcd"
/// char *s = "abcd"; wchar_t *ws = L"abcd"
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::StringLiteral> stringLiteral;
+ Expr,
+ StringLiteral> stringLiteral;
/// \brief Matches character literals (also matches wchar_t).
///
@@ -388,8 +531,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// Example matches 'a', L'a'
/// char ch = 'a'; wchar_t chw = L'a';
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::CharacterLiteral> characterLiteral;
+ Expr,
+ CharacterLiteral> characterLiteral;
/// \brief Matches integer literals of all sizes / encodings.
///
@@ -397,32 +540,32 @@ const internal::VariadicDynCastAllOfMatcher<
///
/// Example matches 1, 1L, 0x1, 1U
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::IntegerLiteral> integerLiteral;
+ Expr,
+ IntegerLiteral> integerLiteral;
/// \brief Matches binary operator expressions.
///
/// Example matches a || b
/// !(a || b)
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::BinaryOperator> binaryOperator;
+ Stmt,
+ BinaryOperator> binaryOperator;
/// \brief Matches unary operator expressions.
///
/// Example matches !a
/// !a || b
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::UnaryOperator> unaryOperator;
+ Stmt,
+ UnaryOperator> unaryOperator;
/// \brief Matches conditional operator expressions.
///
/// Example matches a ? b : c
/// (a ? b : c) + 42
const internal::VariadicDynCastAllOfMatcher<
- clang::Stmt,
- clang::ConditionalOperator> conditionalOperator;
+ Stmt,
+ ConditionalOperator> conditionalOperator;
/// \brief Matches a reinterpret_cast expression.
///
@@ -433,8 +576,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// Example matches reinterpret_cast<char*>(&p) in
/// void* p = reinterpret_cast<char*>(&p);
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::CXXReinterpretCastExpr> reinterpretCast;
+ Expr,
+ CXXReinterpretCastExpr> reinterpretCast;
/// \brief Matches a C++ static_cast expression.
///
@@ -448,8 +591,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// in
/// long eight(static_cast<long>(8));
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::CXXStaticCastExpr> staticCast;
+ Expr,
+ CXXStaticCastExpr> staticCast;
/// \brief Matches a dynamic_cast expression.
///
@@ -462,8 +605,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// B b;
/// D* p = dynamic_cast<D*>(&b);
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::CXXDynamicCastExpr> dynamicCast;
+ Expr,
+ CXXDynamicCastExpr> dynamicCast;
/// \brief Matches a const_cast expression.
///
@@ -472,8 +615,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// const int& r(n);
/// int* p = const_cast<int*>(&r);
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::CXXConstCastExpr> constCast;
+ Expr,
+ CXXConstCastExpr> constCast;
/// \brief Matches explicit cast expressions.
///
@@ -493,16 +636,16 @@ const internal::VariadicDynCastAllOfMatcher<
/// but does not match the implicit conversion in
/// long ell = 42;
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::ExplicitCastExpr> explicitCast;
+ Expr,
+ ExplicitCastExpr> explicitCast;
/// \brief Matches the implicit cast nodes of Clang's AST.
///
/// This matches many different places, including function call return value
/// eliding, as well as any type conversions.
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::ImplicitCastExpr> implicitCast;
+ Expr,
+ ImplicitCastExpr> implicitCast;
/// \brief Matches functional cast expressions
///
@@ -511,8 +654,8 @@ const internal::VariadicDynCastAllOfMatcher<
/// Foo g = (Foo) bar;
/// Foo h = Foo(bar);
const internal::VariadicDynCastAllOfMatcher<
- clang::Expr,
- clang::CXXFunctionalCastExpr> functionalCast;
+ Expr,
+ CXXFunctionalCastExpr> functionalCast;
/// \brief Various overloads for the anyOf matcher.
/// @{
@@ -563,6 +706,56 @@ allOf(const C1& P1, const C2& P2, const C3& P3) {
}
/// @}
+/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
+///
+/// Given
+/// Foo x = bar;
+/// int y = sizeof(x) + alignof(x);
+/// unaryExprOrTypeTraitExpr()
+/// matches \c sizeof(x) and \c alignof(x)
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr;
+
+/// \brief Matches unary expressions that have a specific type of argument.
+///
+/// Given
+/// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c);
+/// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int"))
+/// matches \c sizeof(a) and \c alignof(c)
+AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType,
+ internal::Matcher<QualType>, Matcher) {
+ const QualType ArgumentType = Node.getTypeOfArgument();
+ return Matcher.matches(ArgumentType, Finder, Builder);
+}
+
+/// \brief Matches unary expressions of a certain kind.
+///
+/// Given
+/// int x;
+/// int s = sizeof(x) + alignof(x)
+/// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))
+/// matches \c sizeof(x)
+AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
+ return Node.getKind() == Kind;
+}
+
+/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// alignof.
+inline internal::Matcher<Stmt> alignOfExpr(
+ const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) {
+ return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf(
+ ofKind(UETT_AlignOf), Matcher)));
+}
+
+/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// sizeof.
+inline internal::Matcher<Stmt> sizeOfExpr(
+ const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) {
+ return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf(
+ ofKind(UETT_SizeOf), Matcher)));
+}
+
/// \brief Matches NamedDecl nodes that have the specified name.
///
/// Supports specifying enclosing namespaces or classes by prefixing the name
@@ -574,7 +767,7 @@ allOf(const C1& P1, const C2& P2, const C3& P3) {
///
/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X")
/// namespace a { namespace b { class X; } }
-AST_MATCHER_P(clang::NamedDecl, hasName, std::string, Name) {
+AST_MATCHER_P(NamedDecl, hasName, std::string, Name) {
assert(!Name.empty());
const std::string FullNameString = "::" + Node.getQualifiedNameAsString();
const llvm::StringRef FullName = FullNameString;
@@ -586,6 +779,25 @@ AST_MATCHER_P(clang::NamedDecl, hasName, std::string, Name) {
}
}
+/// \brief Matches NamedDecl nodes whose full names partially match the
+/// given RegExp.
+///
+/// Supports specifying enclosing namespaces or classes by
+/// prefixing the name with '<enclosing>::'. Does not match typedefs
+/// of an underlying type with the given name.
+///
+/// Example matches X (regexp == "::X")
+/// class X;
+///
+/// Example matches X (regexp is one of "::X", "^foo::.*X", among others)
+/// namespace foo { namespace bar { class X; } }
+AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
+ assert(!RegExp.empty());
+ std::string FullNameString = "::" + Node.getQualifiedNameAsString();
+ llvm::Regex RE(RegExp);
+ return RE.match(FullNameString);
+}
+
/// \brief Matches overloaded operator names.
///
/// Matches overloaded operator names specified in strings without the
@@ -596,9 +808,9 @@ AST_MATCHER_P(clang::NamedDecl, hasName, std::string, Name) {
/// a << b;
/// c && d; // assuming both operator<<
/// // and operator&& are overloaded somewhere.
-AST_MATCHER_P(clang::CXXOperatorCallExpr,
+AST_MATCHER_P(CXXOperatorCallExpr,
hasOverloadedOperatorName, std::string, Name) {
- return clang::getOperatorSpelling(Node.getOperator()) == Name;
+ return getOperatorSpelling(Node.getOperator()) == Name;
}
/// \brief Matches C++ classes that are directly or indirectly derived from
@@ -621,7 +833,7 @@ AST_MATCHER_P(clang::CXXOperatorCallExpr,
/// class Foo;
/// typedef Foo X;
/// class Bar : public Foo {}; // derived from a type that X is a typedef of
-AST_MATCHER_P(clang::CXXRecordDecl, isDerivedFrom, std::string, Base) {
+AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, std::string, Base) {
assert(!Base.empty());
return Finder->classIsDerivedFrom(&Node, Base);
}
@@ -722,11 +934,11 @@ internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> unless(const M &
/// \brief Matches a type if the declaration of the type matches the given
/// matcher.
inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher,
- internal::Matcher<clang::Decl> >
- hasDeclaration(const internal::Matcher<clang::Decl> &InnerMatcher) {
+ internal::Matcher<Decl> >
+ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
return internal::PolymorphicMatcherWithParam1<
internal::HasDeclarationMatcher,
- internal::Matcher<clang::Decl> >(InnerMatcher);
+ internal::Matcher<Decl> >(InnerMatcher);
}
/// \brief Matches on the implicit object argument of a member call expression.
@@ -736,9 +948,9 @@ inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher,
/// void z() { Y y; y.x(); }",
///
/// FIXME: Overload to allow directly matching types?
-AST_MATCHER_P(clang::CXXMemberCallExpr, on, internal::Matcher<clang::Expr>,
+AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
InnerMatcher) {
- const clang::Expr *ExprNode = const_cast<clang::CXXMemberCallExpr&>(Node)
+ const Expr *ExprNode = const_cast<CXXMemberCallExpr&>(Node)
.getImplicitObjectArgument()
->IgnoreParenImpCasts();
return (ExprNode != NULL &&
@@ -755,13 +967,13 @@ AST_MATCHER_P(clang::CXXMemberCallExpr, on, internal::Matcher<clang::Expr>,
/// with callee(...)
/// matching this->x, x, y.x, f respectively
///
-/// Note: Callee cannot take the more general internal::Matcher<clang::Expr>
+/// Note: Callee cannot take the more general internal::Matcher<Expr>
/// because this introduces ambiguous overloads with calls to Callee taking a
-/// internal::Matcher<clang::Decl>, as the matcher hierarchy is purely
+/// internal::Matcher<Decl>, as the matcher hierarchy is purely
/// implemented in terms of implicit casts.
-AST_MATCHER_P(clang::CallExpr, callee, internal::Matcher<clang::Stmt>,
+AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
InnerMatcher) {
- const clang::Expr *ExprNode = Node.getCallee();
+ const Expr *ExprNode = Node.getCallee();
return (ExprNode != NULL &&
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
@@ -772,9 +984,9 @@ AST_MATCHER_P(clang::CallExpr, callee, internal::Matcher<clang::Stmt>,
/// Example matches y.x() (matcher = call(callee(method(hasName("x")))))
/// class Y { public: void x(); };
/// void z() { Y y; y.x();
-inline internal::Matcher<clang::CallExpr> callee(
- const internal::Matcher<clang::Decl> &InnerMatcher) {
- return internal::Matcher<clang::CallExpr>(hasDeclaration(InnerMatcher));
+inline internal::Matcher<CallExpr> callee(
+ const internal::Matcher<Decl> &InnerMatcher) {
+ return internal::Matcher<CallExpr>(hasDeclaration(InnerMatcher));
}
/// \brief Matches if the expression's or declaration's type matches a type
@@ -786,10 +998,10 @@ inline internal::Matcher<clang::CallExpr> callee(
/// hasDeclaration(record(hasName("X"))))))
/// class X {};
/// void y(X &x) { x; X z; }
-AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<clang::QualType>,
+AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>,
InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::Expr, NodeType>::value ||
- llvm::is_base_of<clang::ValueDecl, NodeType>::value),
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value ||
+ llvm::is_base_of<ValueDecl, NodeType>::value),
instantiated_with_wrong_types);
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
@@ -809,12 +1021,23 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<clang::QualType>,
/// void y(X &x) { x; X z; }
inline internal::PolymorphicMatcherWithParam1<
internal::matcher_hasTypeMatcher,
- internal::Matcher<clang::QualType> >
-hasType(const internal::Matcher<clang::Decl> &InnerMatcher) {
- return hasType(internal::Matcher<clang::QualType>(
+ internal::Matcher<QualType> >
+hasType(const internal::Matcher<Decl> &InnerMatcher) {
+ return hasType(internal::Matcher<QualType>(
hasDeclaration(InnerMatcher)));
}
+/// \brief Matches if the matched type is represented by the given string.
+///
+/// Given
+/// class Y { public: void x(); };
+/// void z() { Y* y; y->x(); }
+/// call(on(hasType(asString("class Y *"))))
+/// matches y->x()
+AST_MATCHER_P(QualType, asString, std::string, Name) {
+ return Name == Node.getAsString();
+}
+
/// \brief Matches if the matched type is a pointer type and the pointee type
/// matches the specified matcher.
///
@@ -823,16 +1046,16 @@ hasType(const internal::Matcher<clang::Decl> &InnerMatcher) {
/// class Y { public: void x(); };
/// void z() { Y *y; y->x(); }
AST_MATCHER_P(
- clang::QualType, pointsTo, internal::Matcher<clang::QualType>,
+ QualType, pointsTo, internal::Matcher<QualType>,
InnerMatcher) {
- return (Node->isPointerType() &&
+ return (!Node.isNull() && Node->isPointerType() &&
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
/// \brief Overloaded to match the pointee type's declaration.
-inline internal::Matcher<clang::QualType> pointsTo(
- const internal::Matcher<clang::Decl> &InnerMatcher) {
- return pointsTo(internal::Matcher<clang::QualType>(
+inline internal::Matcher<QualType> pointsTo(
+ const internal::Matcher<Decl> &InnerMatcher) {
+ return pointsTo(internal::Matcher<QualType>(
hasDeclaration(InnerMatcher)));
}
@@ -846,38 +1069,38 @@ inline internal::Matcher<clang::QualType> pointsTo(
/// X &x = b;
/// const X &y = b;
/// };
-AST_MATCHER_P(clang::QualType, references, internal::Matcher<clang::QualType>,
+AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
InnerMatcher) {
- return (Node->isReferenceType() &&
+ return (!Node.isNull() && Node->isReferenceType() &&
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
/// \brief Overloaded to match the referenced type's declaration.
-inline internal::Matcher<clang::QualType> references(
- const internal::Matcher<clang::Decl> &InnerMatcher) {
- return references(internal::Matcher<clang::QualType>(
+inline internal::Matcher<QualType> references(
+ const internal::Matcher<Decl> &InnerMatcher) {
+ return references(internal::Matcher<QualType>(
hasDeclaration(InnerMatcher)));
}
-AST_MATCHER_P(clang::CXXMemberCallExpr, onImplicitObjectArgument,
- internal::Matcher<clang::Expr>, InnerMatcher) {
- const clang::Expr *ExprNode =
- const_cast<clang::CXXMemberCallExpr&>(Node).getImplicitObjectArgument();
+AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *ExprNode =
+ const_cast<CXXMemberCallExpr&>(Node).getImplicitObjectArgument();
return (ExprNode != NULL &&
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
/// \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<clang::CallExpr> thisPointerType(
- const internal::Matcher<clang::QualType> &InnerMatcher) {
+inline internal::Matcher<CallExpr> thisPointerType(
+ const internal::Matcher<QualType> &InnerMatcher) {
return onImplicitObjectArgument(
anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
}
/// \brief Overloaded to match the type's declaration.
-inline internal::Matcher<clang::CallExpr> thisPointerType(
- const internal::Matcher<clang::Decl> &InnerMatcher) {
+inline internal::Matcher<CallExpr> thisPointerType(
+ const internal::Matcher<Decl> &InnerMatcher) {
return onImplicitObjectArgument(
anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))));
}
@@ -889,13 +1112,36 @@ inline internal::Matcher<clang::CallExpr> thisPointerType(
/// (matcher = declarationReference(to(variable(hasName("x")))))
/// bool x;
/// if (x) {}
-AST_MATCHER_P(clang::DeclRefExpr, to, internal::Matcher<clang::Decl>,
+AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
InnerMatcher) {
- const clang::Decl *DeclNode = Node.getDecl();
+ const Decl *DeclNode = Node.getDecl();
return (DeclNode != NULL &&
InnerMatcher.matches(*DeclNode, Finder, Builder));
}
+/// \brief Matches a \c DeclRefExpr that refers to a declaration through a
+/// specific using shadow declaration.
+///
+/// FIXME: This currently only works for functions. Fix.
+///
+/// Given
+/// namespace a { void f() {} }
+/// using a::f;
+/// void g() {
+/// f(); // Matches this ..
+/// a::f(); // .. but not this.
+/// }
+/// declarationReference(throughUsingDeclaration(anything()))
+/// matches \c f()
+AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
+ internal::Matcher<UsingShadowDecl>, Matcher) {
+ const NamedDecl *FoundDecl = Node.getFoundDecl();
+ if (const UsingShadowDecl *UsingDecl =
+ llvm::dyn_cast<UsingShadowDecl>(FoundDecl))
+ return Matcher.matches(*UsingDecl, Finder, Builder);
+ return false;
+}
+
/// \brief Matches a variable declaration that has an initializer expression
/// that matches the given matcher.
///
@@ -903,9 +1149,9 @@ AST_MATCHER_P(clang::DeclRefExpr, to, internal::Matcher<clang::Decl>,
/// bool y() { return true; }
/// bool x = y();
AST_MATCHER_P(
- clang::VarDecl, hasInitializer, internal::Matcher<clang::Expr>,
+ VarDecl, hasInitializer, internal::Matcher<Expr>,
InnerMatcher) {
- const clang::Expr *Initializer = Node.getAnyInitializer();
+ const Expr *Initializer = Node.getAnyInitializer();
return (Initializer != NULL &&
InnerMatcher.matches(*Initializer, Finder, Builder));
}
@@ -917,8 +1163,8 @@ AST_MATCHER_P(
/// void f(int x, int y);
/// f(0, 0);
AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr, NodeType>::value ||
- llvm::is_base_of<clang::CXXConstructExpr,
+ TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value ||
+ llvm::is_base_of<CXXConstructExpr,
NodeType>::value),
instantiated_with_wrong_types);
return Node.getNumArgs() == N;
@@ -931,9 +1177,9 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) {
/// (matcher = call(hasArgument(0, declarationReference())))
/// void x(int) { int y; x(y); }
AST_POLYMORPHIC_MATCHER_P2(
- hasArgument, unsigned, N, internal::Matcher<clang::Expr>, InnerMatcher) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<clang::CallExpr, NodeType>::value ||
- llvm::is_base_of<clang::CXXConstructExpr,
+ 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);
return (N < Node.getNumArgs() &&
@@ -948,11 +1194,11 @@ AST_POLYMORPHIC_MATCHER_P2(
/// Foo() : foo_(1) { }
/// int foo_;
/// };
-/// record(Has(Constructor(hasAnyConstructorInitializer(anything()))))
-/// Class matches Foo, hasAnyConstructorInitializer matches foo_(1)
-AST_MATCHER_P(clang::CXXConstructorDecl, hasAnyConstructorInitializer,
- internal::Matcher<clang::CXXCtorInitializer>, InnerMatcher) {
- for (clang::CXXConstructorDecl::init_const_iterator I = Node.init_begin();
+/// record(has(constructor(hasAnyConstructorInitializer(anything()))))
+/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
+AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
+ internal::Matcher<CXXCtorInit