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.h148
1 files changed, 148 insertions, 0 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 37e82e8..33ef3dc 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -50,6 +50,7 @@
#include "clang/ASTMatchers/ASTMatchersMacros.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Regex.h"
+#include <iterator>
namespace clang {
namespace ast_matchers {
@@ -195,6 +196,75 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
return false;
}
+/// \brief Matches expressions that match InnerMatcher after any implicit casts
+/// are stripped off.
+///
+/// Parentheses and explicit casts are not discarded.
+/// Given
+/// int arr[5];
+/// int a = 0;
+/// char b = 0;
+/// const int c = a;
+/// int *d = arr;
+/// long e = (long) 0l;
+/// The matchers
+/// variable(hasInitializer(ignoringImpCasts(integerLiteral())))
+/// variable(hasInitializer(ignoringImpCasts(declarationReference())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+/// variable(hasInitializer(integerLiteral()))
+/// variable(hasInitializer(declarationReference()))
+/// only match the declarations for b, c, and d.
+AST_MATCHER_P(Expr, ignoringImpCasts,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after parentheses and
+/// casts are stripped off.
+///
+/// Implicit and non-C Style casts are also discarded.
+/// Given
+/// int a = 0;
+/// char b = (0);
+/// void* c = reinterpret_cast<char*>(0);
+/// char d = char(0);
+/// The matcher
+/// variable(hasInitializer(ignoringParenCasts(integerLiteral())))
+/// would match the declarations for a, b, c, and d.
+/// while
+/// variable(hasInitializer(integerLiteral()))
+/// only match the declaration for a.
+AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after implicit casts and
+/// parentheses are stripped off.
+///
+/// Explicit casts are not discarded.
+/// Given
+/// int arr[5];
+/// int a = 0;
+/// char b = (0);
+/// const int c = a;
+/// int *d = (arr);
+/// long e = ((long) 0l);
+/// The matchers
+/// variable(hasInitializer(ignoringParenImpCasts(
+/// integerLiteral())))
+/// variable(hasInitializer(ignoringParenImpCasts(
+/// declarationReference())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+/// variable(hasInitializer(integerLiteral()))
+/// variable(hasInitializer(declarationReference()))
+/// would only match the declaration for a.
+AST_MATCHER_P(Expr, ignoringParenImpCasts,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder);
+}
+
/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
/// matches the given Matcher.
///
@@ -691,6 +761,19 @@ const internal::VariadicDynCastAllOfMatcher<
Expr,
ImplicitCastExpr> implicitCast;
+/// \brief Matches any cast nodes of Clang's AST.
+///
+/// Example: castExpr() matches each of the following:
+/// (int) 3;
+/// const_cast<Expr *>(SubExpr);
+/// char c = 0;
+/// but does not match
+/// int i = (0);
+/// int k = 0;
+const internal::VariadicDynCastAllOfMatcher<
+ Expr,
+ CastExpr> castExpr;
+
/// \brief Matches functional cast expressions
///
/// Example: Matches Foo(bar);
@@ -1193,6 +1276,21 @@ AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
return false;
}
+/// \brief Matches the Decl of a DeclStmt which has a single declaration.
+///
+/// Given
+/// int a, b;
+/// int c;
+/// declarationStatement(hasSingleDecl(anything()))
+/// matches 'int c;' but not 'int a, b;'.
+AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) {
+ if (Node.isSingleDecl()) {
+ const Decl *FoundDecl = Node.getSingleDecl();
+ return InnerMatcher.matches(*FoundDecl, Finder, Builder);
+ }
+ return false;
+}
+
/// \brief Matches a variable declaration that has an initializer expression
/// that matches the given matcher.
///
@@ -1238,6 +1336,44 @@ AST_POLYMORPHIC_MATCHER_P2(
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
}
+/// \brief Matches declaration statements that contain a specific number of
+/// declarations.
+///
+/// Example: Given
+/// int a, b;
+/// int c;
+/// int d = 2, e;
+/// declCountIs(2)
+/// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'.
+AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) {
+ return std::distance(Node.decl_begin(), Node.decl_end()) == N;
+}
+
+/// \brief Matches the n'th declaration of a declaration statement.
+///
+/// Note that this does not work for global declarations because the AST
+/// breaks up multiple-declaration DeclStmt's into multiple single-declaration
+/// DeclStmt's.
+/// Example: Given non-global declarations
+/// int a, b = 0;
+/// int c;
+/// int d = 2, e;
+/// declarationStatement(containsDeclaration(
+/// 0, variable(hasInitializer(anything()))))
+/// matches only 'int d = 2, e;', and
+/// declarationStatement(containsDeclaration(1, variable()))
+/// matches 'int a, b = 0' as well as 'int d = 2, e;'
+/// but 'int c;' is not matched.
+AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
+ internal::Matcher<Decl>, InnerMatcher) {
+ const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end());
+ if (N >= NumDecls)
+ return false;
+ DeclStmt::const_decl_iterator Iterator = Node.decl_begin();
+ std::advance(Iterator, N);
+ return InnerMatcher.matches(**Iterator, Finder, Builder);
+}
+
/// \brief Matches a constructor initializer.
///
/// Given
@@ -1385,6 +1521,18 @@ AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, Matcher) {
return Matcher.matches(Node.getResultType(), Finder, Builder);
}
+/// \brief Matches extern "C" function declarations.
+///
+/// Given:
+/// extern "C" void f() {}
+/// extern "C" { void g() {} }
+/// void h() {}
+/// function(isExternC())
+/// matches the declaration of f and g, but not the declaration h
+AST_MATCHER(FunctionDecl, isExternC) {
+ return Node.isExternC();
+}
+
/// \brief Matches the condition expression of an if statement, for loop,
/// or conditional operator.
///
OpenPOWER on IntegriCloud