diff options
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchers.h')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 148 |
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. /// |