summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers/ASTMatchers.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchers.h')
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h831
1 files changed, 692 insertions, 139 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 281d637..e6ba877 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -14,7 +14,7 @@
// a functional in-language DSL to express queries over the C++ AST.
//
// For example, to match a class with a certain name, one would call:
-// recordDecl(hasName("MyClass"))
+// cxxRecordDecl(hasName("MyClass"))
// which returns a matcher that can be used to find all AST nodes that declare
// a class named 'MyClass'.
//
@@ -25,13 +25,13 @@
//
// For example, when we're interested in child classes of a certain class, we
// would write:
-// recordDecl(hasName("MyClass"), hasChild(id("child", recordDecl())))
+// cxxRecordDecl(hasName("MyClass"), hasChild(id("child", recordDecl())))
// When the match is found via the MatchFinder, a user provided callback will
// be called with a BoundNodes instance that contains a mapping from the
// strings that we provided for the id(...) calls to the nodes that were
// matched.
// In the given example, each time our matcher finds a match we get a callback
-// where "child" is bound to the CXXRecordDecl node of the matching child
+// where "child" is bound to the RecordDecl node of the matching child
// class declaration.
//
// See ASTMatchersInternal.h for a more in-depth explanation of the
@@ -170,7 +170,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
/// \brief Matches AST nodes that were expanded within the main-file.
///
-/// Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+/// Example matches X but not Y
+/// (matcher = cxxRecordDecl(isExpansionInMainFile())
/// \code
/// #include <Y.h>
/// class X {};
@@ -191,7 +192,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
/// \brief Matches AST nodes that were expanded within system-header-files.
///
/// Example matches Y but not X
-/// (matcher = recordDecl(isExpansionInSystemHeader())
+/// (matcher = cxxRecordDecl(isExpansionInSystemHeader())
/// \code
/// #include <SystemHeader.h>
/// class X {};
@@ -216,7 +217,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
/// partially matching a given regex.
///
/// Example matches Y but not X
-/// (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+/// (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*"))
/// \code
/// #include "ASTMatcher.h"
/// class X {};
@@ -292,6 +293,31 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
/// matches "namespace {}" and "namespace test {}"
const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
+/// \brief Matches a declaration of a namespace alias.
+///
+/// Given
+/// \code
+/// namespace test {}
+/// namespace alias = ::test;
+/// \endcode
+/// namespaceAliasDecl()
+/// matches "namespace alias" but not "namespace test"
+const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
+ namespaceAliasDecl;
+
+/// \brief Matches class, struct, and union declarations.
+///
+/// Example matches \c X, \c Z, \c U, and \c S
+/// \code
+/// class X;
+/// template<class T> class Z {};
+/// struct S {};
+/// union U {};
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ RecordDecl> recordDecl;
+
/// \brief Matches C++ class declarations.
///
/// Example matches \c X, \c Z
@@ -301,7 +327,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Decl,
- CXXRecordDecl> recordDecl;
+ CXXRecordDecl> cxxRecordDecl;
/// \brief Matches C++ class template declarations.
///
@@ -373,7 +399,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// int i;
/// };
/// \endcode
-const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
+const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
/// \brief Matches template arguments.
///
@@ -386,6 +412,30 @@ const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
/// matches 'int' in C<int>.
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+/// \brief Matches non-type template parameter declarations.
+///
+/// Given
+/// \code
+/// template <typename T, int N> struct C {};
+/// \endcode
+/// nonTypeTemplateParmDecl()
+/// matches 'N', but not 'T'.
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ NonTypeTemplateParmDecl> nonTypeTemplateParmDecl;
+
+/// \brief Matches template type parameter declarations.
+///
+/// Given
+/// \code
+/// template <typename T, int N> struct C {};
+/// \endcode
+/// templateTypeParmDecl()
+/// matches 'T', but not 'N'.
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ TemplateTypeParmDecl> templateTypeParmDecl;
+
/// \brief Matches public C++ declarations.
///
/// Given
@@ -712,7 +762,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Decl,
- CXXConstructorDecl> constructorDecl;
+ CXXConstructorDecl> cxxConstructorDecl;
/// \brief Matches explicit C++ destructor declarations.
///
@@ -725,7 +775,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Decl,
- CXXDestructorDecl> destructorDecl;
+ CXXDestructorDecl> cxxDestructorDecl;
/// \brief Matches enum declarations.
///
@@ -755,7 +805,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// class X { void y(); };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl;
/// \brief Matches conversion operator declarations.
///
@@ -764,7 +814,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl;
/// class X { operator int() const; };
/// \endcode
const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
- conversionDecl;
+ cxxConversionDecl;
/// \brief Matches variable declarations.
///
@@ -877,7 +927,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXMemberCallExpr> memberCallExpr;
+ CXXMemberCallExpr> cxxMemberCallExpr;
/// \brief Matches ObjectiveC Message invocation expressions.
///
@@ -892,6 +942,16 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
ObjCMessageExpr> objcMessageExpr;
+/// \brief Matches Objective-C interface declarations.
+///
+/// Example matches Foo
+/// \code
+/// @interface Foo
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCInterfaceDecl> objcInterfaceDecl;
/// \brief Matches expressions that introduce cleanups to be run at the end
/// of the sub-expression's evaluation.
@@ -900,8 +960,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// const std::string str = std::string();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
-exprWithCleanups;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ExprWithCleanups> exprWithCleanups;
/// \brief Matches init list expressions.
///
@@ -925,8 +986,9 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
/// \endcode
/// substNonTypeTemplateParmExpr()
/// matches "N" in the right-hand side of "static const int n = N;"
-const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr>
-substNonTypeTemplateParmExpr;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ SubstNonTypeTemplateParmExpr> substNonTypeTemplateParmExpr;
/// \brief Matches using declarations.
///
@@ -948,8 +1010,9 @@ const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
/// \endcode
/// usingDirectiveDecl()
/// matches \code using namespace X \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
- usingDirectiveDecl;
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UsingDirectiveDecl> usingDirectiveDecl;
/// \brief Matches unresolved using value declarations.
///
@@ -966,10 +1029,29 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
UnresolvedUsingValueDecl> unresolvedUsingValueDecl;
+/// \brief Matches unresolved using value declarations that involve the
+/// typename.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// struct Base { typedef T Foo; };
+///
+/// template<typename T>
+/// struct S : private Base<T> {
+/// using typename Base<T>::Foo;
+/// };
+/// \endcode
+/// unresolvedUsingTypenameDecl()
+/// matches \code using Base<T>::Foo \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UnresolvedUsingTypenameDecl> unresolvedUsingTypenameDecl;
+
/// \brief Matches constructor call expressions (including implicit ones).
///
/// Example matches string(ptr, n) and ptr within arguments of f
-/// (matcher = constructExpr())
+/// (matcher = cxxConstructExpr())
/// \code
/// void f(const string &a, const string &b);
/// char *ptr;
@@ -978,43 +1060,43 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXConstructExpr> constructExpr;
+ CXXConstructExpr> cxxConstructExpr;
/// \brief Matches unresolved constructor call expressions.
///
/// Example matches T(t) in return statement of f
-/// (matcher = unresolvedConstructExpr())
+/// (matcher = cxxUnresolvedConstructExpr())
/// \code
/// template <typename T>
/// void f(const T& t) { return T(t); }
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXUnresolvedConstructExpr> unresolvedConstructExpr;
+ CXXUnresolvedConstructExpr> cxxUnresolvedConstructExpr;
/// \brief Matches implicit and explicit this expressions.
///
/// Example matches the implicit this expression in "return i".
-/// (matcher = thisExpr())
+/// (matcher = cxxThisExpr())
/// \code
/// struct foo {
/// int i;
/// int f() { return i; }
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> thisExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr;
/// \brief Matches nodes where temporaries are created.
///
/// Example matches FunctionTakesString(GetStringByValue())
-/// (matcher = bindTemporaryExpr())
+/// (matcher = cxxBindTemporaryExpr())
/// \code
/// FunctionTakesString(GetStringByValue());
/// FunctionTakesStringByPointer(GetStringPointer());
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXBindTemporaryExpr> bindTemporaryExpr;
+ CXXBindTemporaryExpr> cxxBindTemporaryExpr;
/// \brief Matches nodes where temporaries are materialized.
///
@@ -1044,9 +1126,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// new X;
/// \endcode
-/// newExpr()
+/// cxxNewExpr()
/// matches 'new X'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> newExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
/// \brief Matches delete expressions.
///
@@ -1054,9 +1136,9 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> newExpr;
/// \code
/// delete X;
/// \endcode
-/// deleteExpr()
+/// cxxDeleteExpr()
/// matches 'delete X'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> deleteExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr;
/// \brief Matches array subscript expressions.
///
@@ -1074,14 +1156,14 @@ const internal::VariadicDynCastAllOfMatcher<
///
/// Example matches the CXXDefaultArgExpr placeholder inserted for the
/// default value of the second parameter in the call expression f(42)
-/// (matcher = defaultArgExpr())
+/// (matcher = cxxDefaultArgExpr())
/// \code
/// void f(int x, int y = 0);
/// f(42);
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXDefaultArgExpr> defaultArgExpr;
+ CXXDefaultArgExpr> cxxDefaultArgExpr;
/// \brief Matches overloaded operator calls.
///
@@ -1091,7 +1173,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// FIXME: figure out why these do not match?
///
/// Example matches both operator<<((o << b), c) and operator<<(o, b)
-/// (matcher = operatorCallExpr())
+/// (matcher = cxxOperatorCallExpr())
/// \code
/// ostream &operator<< (ostream &out, int i) { };
/// ostream &o; int b = 1, c = 1;
@@ -1099,7 +1181,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXOperatorCallExpr> operatorCallExpr;
+ CXXOperatorCallExpr> cxxOperatorCallExpr;
/// \brief Matches expressions.
///
@@ -1166,12 +1248,14 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
/// \brief Matches range-based for statements.
///
-/// forRangeStmt() matches 'for (auto a : i)'
+/// cxxForRangeStmt() matches 'for (auto a : i)'
/// \code
/// int i[] = {1, 2, 3}; for (auto a : i);
/// for(int j = 0; j < 5; ++j);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> forRangeStmt;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXForRangeStmt> cxxForRangeStmt;
/// \brief Matches the initialization statement of a for loop.
///
@@ -1326,27 +1410,27 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt;
/// \code
/// try {} catch(int i) {}
/// \endcode
-/// catchStmt()
+/// cxxCatchStmt()
/// matches 'catch(int i)'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> catchStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt;
/// \brief Matches try statements.
///
/// \code
/// try {} catch(int i) {}
/// \endcode
-/// tryStmt()
+/// cxxTryStmt()
/// matches 'try {}'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> tryStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
/// \brief Matches throw expressions.
///
/// \code
/// try { throw 5; } catch(int i) {}
/// \endcode
-/// throwExpr()
+/// cxxThrowExpr()
/// matches 'throw 5'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> throwExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr;
/// \brief Matches null statements.
///
@@ -1375,7 +1459,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXBoolLiteralExpr> boolLiteral;
+ CXXBoolLiteralExpr> cxxBoolLiteral;
/// \brief Matches string literals (also matches wide string literals).
///
@@ -1439,7 +1523,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \brief Matches nullptr literal.
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXNullPtrLiteralExpr> nullPtrLiteralExpr;
+ CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr;
/// \brief Matches GNU __null expression.
const internal::VariadicDynCastAllOfMatcher<
@@ -1505,7 +1589,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXReinterpretCastExpr> reinterpretCastExpr;
+ CXXReinterpretCastExpr> cxxReinterpretCastExpr;
/// \brief Matches a C++ static_cast expression.
///
@@ -1513,7 +1597,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \see reinterpretCast
///
/// Example:
-/// staticCastExpr()
+/// cxxStaticCastExpr()
/// matches
/// static_cast<long>(8)
/// in
@@ -1522,12 +1606,12 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXStaticCastExpr> staticCastExpr;
+ CXXStaticCastExpr> cxxStaticCastExpr;
/// \brief Matches a dynamic_cast expression.
///
/// Example:
-/// dynamicCastExpr()
+/// cxxDynamicCastExpr()
/// matches
/// dynamic_cast<D*>(&b);
/// in
@@ -1538,7 +1622,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXDynamicCastExpr> dynamicCastExpr;
+ CXXDynamicCastExpr> cxxDynamicCastExpr;
/// \brief Matches a const_cast expression.
///
@@ -1550,7 +1634,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXConstCastExpr> constCastExpr;
+ CXXConstCastExpr> cxxConstCastExpr;
/// \brief Matches a C-style cast expression.
///
@@ -1620,7 +1704,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXFunctionalCastExpr> functionalCastExpr;
+ CXXFunctionalCastExpr> cxxFunctionalCastExpr;
/// \brief Matches functional cast expressions having N != 1 arguments
///
@@ -1630,7 +1714,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXTemporaryObjectExpr> temporaryObjectExpr;
+ CXXTemporaryObjectExpr> cxxTemporaryObjectExpr;
/// \brief Matches \c QualTypes in the clang AST.
const internal::VariadicAllOfMatcher<QualType> qualType;
@@ -1652,8 +1736,8 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// \endcode
/// The matcher:
/// \code
-/// recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
-/// has(fieldDecl(hasName("b")).bind("v"))))
+/// cxxRecordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+/// has(fieldDecl(hasName("b")).bind("v"))))
/// \endcode
/// will generate two results binding "v", the first of which binds
/// the field declaration of \c a, the second the field declaration of
@@ -1789,9 +1873,10 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
/// a << a; // <-- This matches
/// \endcode
///
-/// \c operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified
-/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
-/// the declaration of \c A.
+/// \c cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))) matches the
+/// specified line and
+/// \c cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
+/// matches the declaration of \c A.
///
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
inline internal::PolymorphicMatcherWithParam1<
@@ -1858,10 +1943,10 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
/// \code
/// class A { void func(); };
/// class B { void member(); };
-/// \code
+/// \endcode
///
-/// \c recordDecl(hasMethod(hasName("func"))) matches the declaration of \c A
-/// but not \c B.
+/// \c cxxRecordDecl(hasMethod(hasName("func"))) matches the declaration of
+/// \c A but not \c B.
AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.method_begin(),
@@ -1871,7 +1956,8 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
-/// Example matches X, Y (matcher = recordDecl(has(recordDecl(hasName("X")))
+/// Example matches X, Y
+/// (matcher = cxxRecordDecl(has(cxxRecordDecl(hasName("X")))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
@@ -1888,7 +1974,7 @@ LLVM_ATTRIBUTE_UNUSED has = {};
/// provided matcher.
///
/// Example matches X, Y, Z
-/// (matcher = recordDecl(hasDescendant(recordDecl(hasName("X")))))
+/// (matcher = cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
@@ -1904,7 +1990,8 @@ LLVM_ATTRIBUTE_UNUSED hasDescendant = {};
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
-/// Example matches X, Y (matcher = recordDecl(forEach(recordDecl(hasName("X")))
+/// Example matches X, Y
+/// (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
@@ -1924,7 +2011,7 @@ LLVM_ATTRIBUTE_UNUSED forEach = {};
/// provided matcher.
///
/// Example matches X, A, B, C
-/// (matcher = recordDecl(forEachDescendant(recordDecl(hasName("X")))))
+/// (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class A { class X {}; };
@@ -1937,7 +2024,9 @@ LLVM_ATTRIBUTE_UNUSED forEach = {};
/// each result that matches instead of only on the first one.
///
/// Note: Recursively combined ForEachDescendant can cause many matches:
-/// recordDecl(forEachDescendant(recordDecl(forEachDescendant(recordDecl()))))
+/// cxxRecordDecl(forEachDescendant(cxxRecordDecl(
+/// forEachDescendant(cxxRecordDecl())
+/// )))
/// will match 10 times (plus injected class name matches) on:
/// \code
/// class A { class B { class C { class D { class E {}; }; }; }; };
@@ -1957,7 +2046,8 @@ LLVM_ATTRIBUTE_UNUSED forEachDescendant = {};
/// \endcode
/// The matcher:
/// \code
-/// recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m")))
+/// cxxRecordDecl(hasName("::A"),
+/// findAll(cxxRecordDecl(isDefinition()).bind("m")))
/// \endcode
/// will generate results for \c A, \c B and \c C.
///
@@ -1978,8 +2068,10 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
///
/// Usable as: Any Matcher
const internal::ArgumentAdaptingMatcherFunc<
- internal::HasParentMatcher, internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasParent = {};
+ internal::HasParentMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ LLVM_ATTRIBUTE_UNUSED hasParent = {};
/// \brief Matches AST nodes that have an ancestor that matches the provided
/// matcher.
@@ -1993,12 +2085,14 @@ const internal::ArgumentAdaptingMatcherFunc<
///
/// Usable as: Any Matcher
const internal::ArgumentAdaptingMatcherFunc<
- internal::HasAncestorMatcher, internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
+ internal::HasAncestorMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
/// \brief Matches if the provided matcher does not match.
///
-/// Example matches Y (matcher = recordDecl(unless(hasName("X"))))
+/// Example matches Y (matcher = cxxRecordDecl(unless(hasName("X"))))
/// \code
/// class X {};
/// class Y {};
@@ -2038,7 +2132,8 @@ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
/// \brief Matches on the implicit object argument of a member call expression.
///
-/// Example matches y.x() (matcher = callExpr(on(hasType(recordDecl(hasName("Y"))))))
+/// Example matches y.x()
+/// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y y; y.x(); }",
@@ -2078,7 +2173,7 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
- AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
+AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
Selector Sel = Node.getSelector();
return BaseName.compare(Sel.getAsString()) == 0;
}
@@ -2131,14 +2226,13 @@ AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
/// webView.frame = bodyFrame;
/// // ^---- matches here
/// \endcode
-
AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
return Node.getSelector().isKeywordSelector();
}
/// \brief Matches when the selector has the specified number of arguments
///
-/// matcher = objCMessageExpr(numSelectorArgs(1));
+/// matcher = objCMessageExpr(numSelectorArgs(0));
/// matches self.bodyView in the code below
///
/// matcher = objCMessageExpr(numSelectorArgs(2));
@@ -2177,7 +2271,8 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
/// \brief Matches if the call expression's callee's declaration matches the
/// given matcher.
///
-/// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x")))))
+/// Example matches y.x() (matcher = callExpr(callee(
+/// cxxMethodDecl(hasName("x")))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y y; y.x(); }
@@ -2190,8 +2285,8 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
/// \brief Matches if the expression's or declaration's type matches a type
/// matcher.
///
-/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X")))))
-/// and z (matcher = varDecl(hasType(recordDecl(hasName("X")))))
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
@@ -2207,12 +2302,12 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
///
/// In case of a value declaration (for example a variable declaration),
/// this resolves one layer of indirection. For example, in the value
-/// declaration "X x;", recordDecl(hasName("X")) matches the declaration of X,
-/// while varDecl(hasType(recordDecl(hasName("X")))) matches the declaration
-/// of x."
+/// declaration "X x;", cxxRecordDecl(hasName("X")) matches the declaration of
+/// X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
+/// declaration of x.
///
-/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X")))))
-/// and z (matcher = varDecl(hasType(recordDecl(hasName("X")))))
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
@@ -2250,7 +2345,7 @@ AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) {
/// class Y { public: void x(); };
/// void z() { Y* y; y->x(); }
/// \endcode
-/// callExpr(on(hasType(asString("class Y *"))))
+/// cxxMemberCallExpr(on(hasType(asString("class Y *"))))
/// matches y->x()
AST_MATCHER_P(QualType, asString, std::string, Name) {
return Name == Node.getAsString();
@@ -2260,7 +2355,8 @@ AST_MATCHER_P(QualType, asString, std::string, Name) {
/// matches the specified matcher.
///
/// Example matches y->x()
-/// (matcher = callExpr(on(hasType(pointsTo(recordDecl(hasName("Y")))))))
+/// (matcher = cxxMemberCallExpr(on(hasType(pointsTo
+/// cxxRecordDecl(hasName("Y")))))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y *y; y->x(); }
@@ -2268,7 +2364,7 @@ AST_MATCHER_P(QualType, asString, std::string, Name) {
AST_MATCHER_P(
QualType, pointsTo, internal::Matcher<QualType>,
InnerMatcher) {
- return (!Node.isNull() && Node->isPointerType() &&
+ return (!Node.isNull() && Node->isAnyPointerType() &&
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
@@ -2283,7 +2379,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
/// type matches the specified matcher.
///
/// Example matches X &x and const X &y
-/// (matcher = varDecl(hasType(references(recordDecl(hasName("X"))))))
+/// (matcher = varDecl(hasType(references(cxxRecordDecl(hasName("X"))))))
/// \code
/// class X {
/// void a(X b) {
@@ -2305,7 +2401,7 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
/// typedef int &int_ref;
/// int a;
/// int_ref b = a;
-/// \code
+/// \endcode
///
/// \c varDecl(hasType(qualType(referenceType()))))) will not match the
/// declaration of b but \c
@@ -2367,8 +2463,6 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
/// \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
/// \code
/// namespace a { void f() {} }
@@ -2378,7 +2472,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
/// a::f(); // .. but not this.
/// }
/// \endcode
-/// declRefExpr(throughUsingDeclaration(anything()))
+/// declRefExpr(throughUsingDecl(anything()))
/// matches \c f()
AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
internal::Matcher<UsingShadowDecl>, InnerMatcher) {
@@ -2450,6 +2544,69 @@ AST_MATCHER(VarDecl, hasGlobalStorage) {
return Node.hasGlobalStorage();
}
+/// \brief Matches a variable declaration that has automatic storage duration.
+///
+/// Example matches x, but not y, z, or a.
+/// (matcher = varDecl(hasAutomaticStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
+ return Node.getStorageDuration() == SD_Automatic;
+}
+
+/// \brief Matches a variable declaration that has static storage duration.
+///
+/// Example matches y and a, but not x or z.
+/// (matcher = varDecl(hasStaticStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasStaticStorageDuration) {
+ return Node.getStorageDuration() == SD_Static;
+}
+
+/// \brief Matches a variable declaration that has thread storage duration.
+///
+/// Example matches z, but not x, z, or a.
+/// (matcher = varDecl(hasThreadStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasThreadStorageDuration) {
+ return Node.getStorageDuration() == SD_Thread;
+}
+
+/// \brief Matches a variable declaration that is an exception variable from
+/// a C++ catch block, or an Objective-C \@catch statement.
+///
+/// Example matches x (matcher = varDecl(isExceptionVariable())
+/// \code
+/// void f(int y) {
+/// try {
+/// } catch (int x) {
+/// }
+/// }
+/// \endcode
+AST_MATCHER(VarDecl, isExceptionVariable) {
+ return Node.isExceptionVariable();
+}
+
/// \brief Checks that a call expression or a constructor call expression has
/// a specific number of arguments (including absent default arguments).
///
@@ -2540,7 +2697,7 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
/// // ...
/// }
/// /endcode
-/// catchStmt(isCatchAll()) matches catch(...) but not catch(int).
+/// cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int).
AST_MATCHER(CXXCatchStmt, isCatchAll) {
return Node.getExceptionDecl() == nullptr;
}
@@ -2554,7 +2711,9 @@ AST_MATCHER(CXXCatchStmt, isCatchAll) {
/// int foo_;
/// };
/// \endcode
-/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(anything()))))
+/// cxxRecordDecl(has(cxxConstructorDecl(
+/// hasAnyConstructorInitializer(anything())
+/// )))
/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
@@ -2571,7 +2730,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
/// int foo_;
/// };
/// \endcode
-/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
/// forField(hasName("foo_"))))))
/// matches Foo
/// with forField matching foo_
@@ -2591,7 +2750,7 @@ AST_MATCHER_P(CXXCtorInitializer, forField,
/// int foo_;
/// };
/// \endcode
-/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
/// withInitializer(integerLiteral(equals(1)))))))
/// matches Foo
/// with withInitializer matching (1)
@@ -2613,12 +2772,52 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer,
/// string foo_;
/// };
/// \endcode
-/// constructorDecl(hasAnyConstructorInitializer(isWritten()))
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isWritten()))
/// will match Foo(int), but not Foo()
AST_MATCHER(CXXCtorInitializer, isWritten) {
return Node.isWritten();
}
+/// \brief Matches a constructor initializer if it is initializing a base, as
+/// opposed to a member.
+///
+/// Given
+/// \code
+/// struct B {};
+/// struct D : B {
+/// int I;
+/// D(int i) : I(i) {}
+/// };
+/// struct E : B {
+/// E() : B() {}
+/// };
+/// \endcode
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
+/// will match E(), but not match D(int).
+AST_MATCHER(CXXCtorInitializer, isBaseInitializer) {
+ return Node.isBaseInitializer();
+}
+
+/// \brief Matches a constructor initializer if it is initializing a member, as
+/// opposed to a base.
+///
+/// Given
+/// \code
+/// struct B {};
+/// struct D : B {
+/// int I;
+/// D(int i) : I(i) {}
+/// };
+/// struct E : B {
+/// E() : B() {}
+/// };
+/// \endcode
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isMemberInitializer()))
+/// will match D(int), but not match E().
+AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
+ return Node.isMemberInitializer();
+}
+
/// \brief Matches any argument of a call expression or a constructor call
/// expression.
///
@@ -2660,7 +2859,7 @@ AST_MATCHER(CXXConstructExpr, isListInitialization) {
/// \code
/// class X { void f(int x) {} };
/// \endcode
-/// methodDecl(hasParameter(0, hasType(varDecl())))
+/// cxxMethodDecl(hasParameter(0, hasType(varDecl())))
/// matches f(int x) {}
/// with hasParameter(...)
/// matching int x
@@ -2680,7 +2879,7 @@ AST_MATCHER_P2(FunctionDecl, hasParameter,
/// \code
/// class X { void f(int x, int y, int z) {} };
/// \endcode
-/// methodDecl(hasAnyParameter(hasName("y")))
+/// cxxMethodDecl(hasAnyParameter(hasName("y")))
/// matches f(int x, int y, int z) {}
/// with hasAnyParameter(...)
/// matching int y
@@ -2709,7 +2908,7 @@ AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) {
/// \code
/// class X { int f() { return 1; } };
/// \endcode
-/// methodDecl(returns(asString("int")))
+/// cxxMethodDecl(returns(asString("int")))
/// matches int f() { return 1; }
AST_MATCHER_P(FunctionDecl, returns,
internal::Matcher<QualType>, InnerMatcher) {
@@ -2743,6 +2942,34 @@ AST_MATCHER(FunctionDecl, isDeleted) {
return Node.isDeleted();
}
+/// \brief Matches functions that have a non-throwing exception specification.
+///
+/// Given:
+/// \code
+/// void f();
+/// void g() noexcept;
+/// void h() throw();
+/// void i() throw(int);
+/// void j() noexcept(false);
+/// \endcode
+/// functionDecl(isNoThrow())
+/// matches the declarations of g, and h, but not f, i or j.
+AST_MATCHER(FunctionDecl, isNoThrow) {
+ const auto *FnTy = Node.getType()->getAs<FunctionProtoType>();
+
+ // If the function does not have a prototype, then it is assumed to be a
+ // throwing function (as it would if the function did not have any exception
+ // specification).
+ if (!FnTy)
+ return false;
+
+ // Assume the best for any unresolved exception specification.
+ if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType()))
+ return true;
+
+ return FnTy->isNothrow(Node.getASTContext());
+}
+
/// \brief Matches constexpr variable and function declarations.
///
/// Given:
@@ -2763,7 +2990,7 @@ AST_POLYMORPHIC_MATCHER(isConstexpr,
/// \brief Matches the condition expression of an if statement, for loop,
/// or conditional operator.
///
-/// Example matches true (matcher = hasCondition(boolLiteral(equals(true))))
+/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
/// \code
/// if (true) {}
/// \endcode
@@ -2780,7 +3007,7 @@ AST_POLYMORPHIC_MATCHER_P(hasCondition,
/// \brief Matches the then-statement of an if statement.
///
/// Examples matches the if statement
-/// (matcher = ifStmt(hasThen(boolLiteral(equals(true)))))
+/// (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true)))))
/// \code
/// if (false) true; else false;
/// \endcode
@@ -2792,7 +3019,7 @@ AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) {
/// \brief Matches the else-statement of an if statement.
///
/// Examples matches the if statement
-/// (matcher = ifStmt(hasElse(boolLiteral(equals(true)))))
+/// (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true)))))
/// \code
/// if (false) false; else true;
/// \endcode
@@ -2809,7 +3036,7 @@ AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
/// \code
/// class X { int a; int b; };
/// \endcode
-/// recordDecl(
+/// cxxRecordDecl(
/// 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.
@@ -2941,7 +3168,7 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
/// \brief Matches literals that are equal to the given value.
///
-/// Example matches true (matcher = boolLiteral(equals(true)))
+/// Example matches true (matcher = cxxBoolLiteral(equals(true)))
/// \code
/// true
/// \endcode
@@ -2976,9 +3203,11 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
/// \code
/// a || b
/// \endcode
-AST_MATCHER_P(BinaryOperator, hasLHS,
- internal::Matcher<Expr>, InnerMatcher) {
- Expr *LeftHandSide = Node.getLHS();
+AST_POLYMORPHIC_MATCHER_P(hasLHS,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ ArraySubscriptExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *LeftHandSide = Node.getLHS();
return (LeftHandSide != nullptr &&
InnerMatcher.matches(*LeftHandSide, Finder, Builder));
}
@@ -2989,9 +3218,11 @@ AST_MATCHER_P(BinaryOperator, hasLHS,
/// \code
/// a || b
/// \endcode
-AST_MATCHER_P(BinaryOperator, hasRHS,
- internal::Matcher<Expr>, InnerMatcher) {
- Expr *RightHandSide = Node.getRHS();
+AST_POLYMORPHIC_MATCHER_P(hasRHS,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ ArraySubscriptExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *RightHandSide = Node.getRHS();
return (RightHandSide != nullptr &&
InnerMatcher.matches(*RightHandSide, Finder, Builder));
}
@@ -3005,7 +3236,8 @@ inline internal::Matcher<BinaryOperator> hasEitherOperand(
/// \brief Matches if the operand of a unary operator matches.
///
-/// Example matches true (matcher = hasUnaryOperand(boolLiteral(equals(true))))
+/// Example matches true (matcher = hasUnaryOperand(
+/// cxxBoolLiteral(equals(true))))
/// \code
/// !true
/// \endcode
@@ -3019,10 +3251,11 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
/// \brief Matches if the cast's source expression matches the given matcher.
///
/// Example: matches "a string" (matcher =
-/// hasSourceExpression(constructExpr()))
+/// hasSourceExpression(cxxConstructExpr()))
/// \code
/// class URL { URL(string); };
/// URL url = "a string";
+/// \endcode
AST_MATCHER_P(CastExpr, hasSourceExpression,
internal::Matcher<Expr>, InnerMatcher) {
const Expr* const SubExpression = Node.getSubExpr();
@@ -3049,6 +3282,42 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
+/// \brief Matches RecordDecl object that are spelled with "struct."
+///
+/// Example matches S, but not C or U.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isStruct) {
+ return Node.isStruct();
+}
+
+/// \brief Matches RecordDecl object that are spelled with "union."
+///
+/// Example matches U, but not C or S.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isUnion) {
+ return Node.isUnion();
+}
+
+/// \brief Matches RecordDecl object that are spelled with "class."
+///
+/// Example matches C, but not S or U.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isClass) {
+ return Node.isClass();
+}
+
/// \brief Matches the true branch expression of a conditional operator.
///
/// Example matches a
@@ -3057,7 +3326,7 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
/// \endcode
AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
internal::Matcher<Expr>, InnerMatcher) {
- Expr *Expression = Node.getTrueExpr();
+ const Expr *Expression = Node.getTrueExpr();
return (Expression != nullptr &&
InnerMatcher.matches(*Expression, Finder, Builder));
}
@@ -3070,7 +3339,7 @@ AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
/// \endcode
AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
internal::Matcher<Expr>, InnerMatcher) {
- Expr *Expression = Node.getFalseExpr();
+ const Expr *Expression = Node.getFalseExpr();
return (Expression != nullptr &&
InnerMatcher.matches(*Expression, Finder, Builder));
}
@@ -3094,6 +3363,20 @@ AST_POLYMORPHIC_MATCHER(isDefinition,
return Node.isThisDeclarationADefinition();
}
+/// \brief Matches if a function declaration is variadic.
+///
+/// Example matches f, but not g or h. The function i will not match, even when
+/// compiled in C mode.
+/// \code
+/// void f(...);
+/// void g(int);
+/// template <typename... Ts> void h(Ts...);
+/// void i();
+/// \endcode
+AST_MATCHER(FunctionDecl, isVariadic) {
+ return Node.isVariadic();
+}
+
/// \brief Matches the class declaration that the given method declaration
/// belongs to.
///
@@ -3102,7 +3385,7 @@ AST_POLYMORPHIC_MATCHER(isDefinition,
/// this to?
///
/// Example matches A() in the last line
-/// (matcher = constructExpr(hasDeclaration(methodDecl(
+/// (matcher = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
/// ofClass(hasName("A"))))))
/// \code
/// class A {
@@ -3132,6 +3415,27 @@ AST_MATCHER(CXXMethodDecl, isVirtual) {
return Node.isVirtual();
}
+/// \brief Matches if the given method or class declaration is final.
+///
+/// Given:
+/// \code
+/// class A final {};
+///
+/// struct B {
+/// virtual void f();
+/// };
+///
+/// struct C : B {
+/// void f() final;
+/// };
+/// \endcode
+/// matches A and C::f, but not B, C, or B::f
+AST_POLYMORPHIC_MATCHER(isFinal,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl,
+ CXXMethodDecl)) {
+ return Node.template hasAttr<FinalAttr>();
+}
+
/// \brief Matches if the given method declaration is pure.
///
/// Given
@@ -3156,11 +3460,28 @@ AST_MATCHER(CXXMethodDecl, isPure) {
/// };
/// \endcode
///
-/// methodDecl(isConst()) matches A::foo() but not A::bar()
+/// cxxMethodDecl(isConst()) matches A::foo() but not A::bar()
AST_MATCHER(CXXMethodDecl, isConst) {
return Node.isConst();
}
+/// \brief Matches if the given method declaration declares a copy assignment
+/// operator.
+///
+/// Given
+/// \code
+/// struct A {
+/// A &operator=(const A &);
+/// A &operator=(A &&);
+/// };
+/// \endcode
+///
+/// cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not
+/// the second one.
+AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) {
+ return Node.isCopyAssignmentOperator();
+}
+
/// \brief Matches if the given method declaration overrides another method.
///
/// Given
@@ -3212,6 +3533,20 @@ AST_MATCHER(QualType, isInteger) {
return Node->isIntegerType();
}
+/// \brief Matches QualType nodes that are of character type.
+///
+/// Given
+/// \code
+/// void a(char);
+/// void b(wchar_t);
+/// void c(double);
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isAnyCharacter())))
+/// matches "a(char)", "b(wchar_t)", but not "c(double)".
+AST_MATCHER(QualType, isAnyCharacter) {
+ return Node->isAnyCharacterType();
+}
+
/// \brief Matches QualType nodes that are const-qualified, i.e., that
/// include "top-level" const.
///
@@ -3231,6 +3566,25 @@ AST_MATCHER(QualType, isConstQualified) {
return Node.isConstQualified();
}
+/// \brief Matches QualType nodes that are volatile-qualified, i.e., that
+/// include "top-level" volatile.
+///
+/// Given
+/// \code
+/// void a(int);
+/// void b(int volatile);
+/// void c(volatile int);
+/// void d(volatile int*);
+/// void e(int volatile) {};
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isVolatileQualified())))
+/// matches "void b(int volatile)", "void c(volatile int)" and
+/// "void e(int volatile) {}". It does not match d as there
+/// is no top-level volatile on the parameter type "volatile int *".
+AST_MATCHER(QualType, isVolatileQualified) {
+ return Node.isVolatileQualified();
+}
+
/// \brief Matches QualType nodes that have local CV-qualifiers attached to
/// the node, not hidden within a typedef.
///
@@ -3273,7 +3627,7 @@ AST_MATCHER_P(MemberExpr, member,
/// struct X { int m; };
/// void f(X x) { x.m; m; }
/// \endcode
-/// memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))))
+/// memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
/// matches "x.m" and "m"
/// with hasObjectExpression(...)
/// matching "x" and the implicit object expression of "m" which has type X*.
@@ -3325,7 +3679,7 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// \code
/// template <typename T> class X {}; class A {}; template class X<A>;
/// \endcode
-/// recordDecl(hasName("::X"), isTemplateInstantiation())
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
/// matches the template instantiation of X<A>.
///
/// But given
@@ -3333,7 +3687,7 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// template <typename T> class X {}; class A {};
/// template <> class X<A> {}; X<A> x;
/// \endcode
-/// recordDecl(hasName("::X"), isTemplateInstantiation())
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
/// does not match, as X<A> is an explicit template specialization.
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
@@ -3357,7 +3711,7 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
/// functionDecl(isInstantiated())
/// matches 'A(int) {...};' and 'A(unsigned) {...}'.
AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
- auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()),
+ auto IsInstantiation = decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation())));
return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
}
@@ -3378,7 +3732,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
/// instantiation.
AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
return stmt(
- hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
+ hasAncestor(decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation())))));
}
@@ -3408,6 +3762,18 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
new internal::TypeLocTypeMatcher(InnerMatcher));
}
+/// \brief Matches type \c bool.
+///
+/// Given
+/// \code
+/// struct S { bool func(); };
+/// \endcode
+/// functionDecl(returns(booleanType()))
+/// matches "bool func();"
+AST_MATCHER(Type, booleanType) {
+ return Node.isBooleanType();
+}
+
/// \brief Matches type \c void.
///
/// Given
@@ -3665,18 +4031,38 @@ AST_TYPE_MATCHER(BlockPointerType, blockPointerType);
/// matches "A::* ptr"
AST_TYPE_MATCHER(MemberPointerType, memberPointerType);
-/// \brief Matches pointer types.
+/// \brief Matches pointer types, but does not match Objective-C object pointer
+/// types.
///
/// Given
/// \code
/// int *a;
/// int &b = *a;
/// int c = 5;
+///
+/// @interface Foo
+/// @end
+/// Foo *f;
/// \endcode
/// pointerType()
-/// matches "int *a"
+/// matches "int *a", but does not match "Foo *f".
AST_TYPE_MATCHER(PointerType, pointerType);
+/// \brief Matches an Objective-C object pointer type, which is different from
+/// a pointer type, despite being syntactically similar.
+///
+/// Given
+/// \code
+/// int *a;
+///
+/// @interface Foo
+/// @end
+/// Foo *f;
+/// \endcode
+/// pointerType()
+/// matches "Foo *f", but does not match "int *a".
+AST_TYPE_MATCHER(ObjCObjectPointerType, objcObjectPointerType);
+
/// \brief Matches both lvalue and rvalue reference types.
///
/// Given
@@ -3766,7 +4152,7 @@ AST_TYPE_MATCHER(TypedefType, typedefType);
///
/// template class C<int>; // A
/// C<char> var; // B
-/// \code
+/// \endcode
///
/// \c templateSpecializationType() matches the type of the explicit
/// instantiation in \c A and the type of the variable declaration in \c B.
@@ -3791,7 +4177,7 @@ AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType);
///
/// C c;
/// S s;
-/// \code
+/// \endcode
///
/// \c recordType() matches the type of the variable declarations of both \c c
/// and \c s.
@@ -3811,7 +4197,7 @@ AST_TYPE_MATCHER(RecordType, recordType);
///
/// class C c;
/// N::M::D d;
-/// \code
+/// \endcode
///
/// \c elaboratedType() matches the type of the variable declarations of both
/// \c c and \c d.
@@ -3828,7 +4214,7 @@ AST_TYPE_MATCHER(ElaboratedType, elaboratedType);
/// }
/// }
/// N::M::D d;
-/// \code
+/// \endcode
///
/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
/// matches the type of the variable declaration of \c d.
@@ -3850,7 +4236,7 @@ AST_MATCHER_P(ElaboratedType, hasQualifier,
/// }
/// }
/// N::M::D d;
-/// \code
+/// \endcode
///
/// \c elaboratedType(namesType(recordType(
/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
@@ -3860,6 +4246,59 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
}
+/// \brief Matches types that represent the result of substituting a type for a
+/// template type parameter.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// void F(T t) {
+/// int i = 1 + t;
+/// }
+/// \endcode
+///
+/// \c substTemplateTypeParmType() matches the type of 't' but not '1'
+AST_TYPE_MATCHER(SubstTemplateTypeParmType, substTemplateTypeParmType);
+
+/// \brief Matches template type parameter types.
+///
+/// Example matches T, but not int.
+/// (matcher = templateTypeParmType())
+/// \code
+/// template <typename T> void f(int i);
+/// \endcode
+AST_TYPE_MATCHER(TemplateTypeParmType, templateTypeParmType);
+
+/// \brief Matches injected class name types.
+///
+/// Example matches S s, but not S<T> s.
+/// (matcher = parmVarDecl(hasType(injectedClassNameType())))
+/// \code
+/// template <typename T> struct S {
+/// void f(S s);
+/// void g(S<T> s);
+/// };
+/// \endcode
+AST_TYPE_MATCHER(InjectedClassNameType, injectedClassNameType);
+
+/// \brief Matches decayed type
+/// Example matches i[] in declaration of f.
+/// (matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))
+/// Example matches i[1].
+/// (matcher = expr(hasType(decayedType(hasDecayedType(pointerType())))))
+/// \code
+/// void f(int i[]) {
+/// i[1] = 0;
+/// }
+/// \endcode
+AST_TYPE_MATCHER(DecayedType, decayedType);
+
+/// \brief Matches the decayed type, whos decayed type matches \c InnerMatcher
+AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>,
+ InnerType) {
+ return InnerType.matches(Node.getDecayedType(), Finder, Builder);
+}
+
/// \brief Matches declarations whose declaration context, interpreted as a
/// Decl, matches \c InnerMatcher.
///
@@ -3870,9 +4309,9 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
/// class D {};
/// }
/// }
-/// \code
+/// \endcode
///
-/// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
+/// \c cxxRcordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
/// declaration of \c class \c D.
AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
const DeclContext *DC = Node.getDeclContext();
@@ -3917,7 +4356,9 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(
/// struct A { struct B { struct C {}; }; };
/// A::B::C c;
/// \endcode
-/// nestedNameSpecifier(specifiesType(hasDeclaration(recordDecl(hasName("A")))))
+/// nestedNameSpecifier(specifiesType(
+/// hasDeclaration(cxxRecordDecl(hasName("A")))
+/// ))
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifier, specifiesType,
internal::Matcher<QualType>, InnerMatcher) {
@@ -3935,7 +4376,7 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// A::B::C c;
/// \endcode
/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type(
-/// hasDeclaration(recordDecl(hasName("A")))))))
+/// hasDeclaration(cxxRecordDecl(hasName("A")))))))
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
@@ -3954,7 +4395,7 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
internal::Matcher<NestedNameSpecifier>, InnerMatcher,
0) {
- NestedNameSpecifier *NextNode = Node.getPrefix();
+ const NestedNameSpecifier *NextNode = Node.getPrefix();
if (!NextNode)
return false;
return InnerMatcher.matches(*NextNode, Finder, Builder);
@@ -4008,10 +4449,15 @@ AST_MATCHER_P_OVERLOAD(Decl, equalsNode, const Decl*, Other, 0) {
/// \brief Matches if a node equals another node.
///
/// \c Stmt has pointer identity in the AST.
-///
AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, const Stmt*, Other, 1) {
return &Node == Other;
}
+/// \brief Matches if a node equals another node.
+///
+/// \c Type has pointer identity in the AST.
+AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) {
+ return &Node == Other;
+}
/// @}
@@ -4053,7 +4499,9 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
/// \code
/// class A { A() : i(42), j(42) {} int i; int j; };
/// \endcode
-/// constructorDecl(forEachConstructorInitializer(forField(decl().bind("x"))))
+/// cxxConstructorDecl(forEachConstructorInitializer(
+/// forField(decl().bind("x"))
+/// ))
/// will trigger two matches, binding for 'i' and 'j' respectively.
AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
@@ -4070,6 +4518,109 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
return Matched;
}
+/// \brief Matches constructor declarations that are copy constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isCopyConstructor()) will match #2, but not #1 or #3.
+AST_MATCHER(CXXConstructorDecl, isCopyConstructor) {
+ return Node.isCopyConstructor();
+}
+
+/// \brief Matches constructor declarations that are move constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isMoveConstructor()) will match #3, but not #1 or #2.
+AST_MATCHER(CXXConstructorDecl, isMoveConstructor) {
+ return Node.isMoveConstructor();
+}
+
+/// \brief Matches constructor declarations that are default constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
+AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
+ return Node.isDefaultConstructor();
+}
+
+/// \brief Matches constructor and conversion declarations that are marked with
+/// the explicit keyword.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(int); // #1
+/// explicit S(double); // #2
+/// operator int(); // #3
+/// explicit operator bool(); // #4
+/// };
+/// \endcode
+/// cxxConstructorDecl(isExplicit()) will match #2, but not #1.
+/// cxxConversionDecl(isExplicit()) will match #4, but not #3.
+AST_POLYMORPHIC_MATCHER(isExplicit,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXConstructorDecl,
+ CXXConversionDecl)) {
+ return Node.isExplicit();
+}
+
+/// \brief Matches function and namespace declarations that are marked with
+/// the inline keyword.
+///
+/// Given
+/// \code
+/// inline void f();
+/// void g();
+/// namespace n {
+/// inline namespace m {}
+/// }
+/// \endcode
+/// functionDecl(isInline()) will match ::f().
+/// namespaceDecl(isInline()) will match n::m.
+AST_POLYMORPHIC_MATCHER(isInline,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
+ FunctionDecl)) {
+ // This is required because the spelling of the function used to determine
+ // whether inline is specified or not differs between the polymorphic types.
+ if (const auto *FD = dyn_cast<FunctionDecl>(&Node))
+ return FD->isInlineSpecified();
+ else if (const auto *NSD = dyn_cast<NamespaceDecl>(&Node))
+ return NSD->isInline();
+ llvm_unreachable("Not a valid polymorphic type");
+}
+
+/// \brief Matches anonymous namespace declarations.
+///
+/// Given
+/// \code
+/// namespace n {
+/// namespace {} // #1
+/// }
+/// \endcode
+/// namespaceDecl(isAnonymous()) will match #1 but not ::n.
+AST_MATCHER(NamespaceDecl, isAnonymous) {
+ return Node.isAnonymousNamespace();
+}
+
/// \brief If the given case statement does not use the GNU case range
/// extension, matches the constant given in the statement.
///
@@ -4094,7 +4645,8 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
/// __attribute__((device)) void f() { ... }
/// \endcode
/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
-/// f.
+/// f. If the matcher is use from clang-query, attr::Kind parameter should be
+/// passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
for (const auto *Attr : Node.attrs()) {
if (Attr->getKind() == AttrKind)
@@ -4109,8 +4661,9 @@ AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
/// \code
/// kernel<<<i,j>>>();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
- CUDAKernelCallExpr;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CUDAKernelCallExpr> cudaKernelCallExpr;
} // end namespace ast_matchers
} // end namespace clang
OpenPOWER on IntegriCloud