diff options
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchers.h')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 4671 |
1 files changed, 0 insertions, 4671 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h deleted file mode 100644 index e6ba877..0000000 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ /dev/null @@ -1,4671 +0,0 @@ -//===--- ASTMatchers.h - Structural query framework -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements matchers to be used together with the MatchFinder to -// match AST nodes. -// -// Matchers are created by generator functions, which can be combined in -// 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: -// cxxRecordDecl(hasName("MyClass")) -// which returns a matcher that can be used to find all AST nodes that declare -// a class named 'MyClass'. -// -// For more complicated match expressions we're often interested in accessing -// multiple parts of the matched AST nodes once a match is found. In that case, -// use the id(...) matcher around the match expressions that match the nodes -// you want to access. -// -// For example, when we're interested in child classes of a certain class, we -// would write: -// 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 RecordDecl node of the matching child -// class declaration. -// -// See ASTMatchersInternal.h for a more in-depth explanation of the -// implementation details of the matcher framework. -// -// See ASTMatchFinder.h for how to use the generated matchers to run over -// an AST. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H -#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H - -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.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" -#include <iterator> - -namespace clang { -namespace ast_matchers { - -/// \brief Maps string IDs to AST nodes matched by parts of a matcher. -/// -/// The bound nodes are generated by calling \c bind("id") on the node matchers -/// of the nodes we want to access later. -/// -/// The instances of BoundNodes are created by \c MatchFinder when the user's -/// callbacks are executed every time a match is found. -class BoundNodes { -public: - /// \brief Returns the AST node bound to \c ID. - /// - /// Returns NULL if there was no node bound to \c ID or if there is a node but - /// it cannot be converted to the specified type. - template <typename T> - const T *getNodeAs(StringRef ID) const { - return MyBoundNodes.getNodeAs<T>(ID); - } - - /// \brief Deprecated. Please use \c getNodeAs instead. - /// @{ - template <typename T> - const T *getDeclAs(StringRef ID) const { - return getNodeAs<T>(ID); - } - template <typename T> - const T *getStmtAs(StringRef ID) const { - return getNodeAs<T>(ID); - } - /// @} - - /// \brief Type of mapping from binding identifiers to bound nodes. This type - /// is an associative container with a key type of \c std::string and a value - /// type of \c clang::ast_type_traits::DynTypedNode - typedef internal::BoundNodesMap::IDToNodeMap IDToNodeMap; - - /// \brief Retrieve mapping from binding identifiers to bound nodes. - const IDToNodeMap &getMap() const { - return MyBoundNodes.getMap(); - } - -private: - /// \brief Create BoundNodes from a pre-filled map of bindings. - BoundNodes(internal::BoundNodesMap &MyBoundNodes) - : MyBoundNodes(MyBoundNodes) {} - - internal::BoundNodesMap MyBoundNodes; - - friend class internal::BoundNodesTreeBuilder; -}; - -/// \brief If the provided matcher matches a node, binds the node to \c ID. -/// -/// FIXME: Do we want to support this now that we have bind()? -template <typename T> -internal::Matcher<T> id(StringRef ID, - const internal::BindableMatcher<T> &InnerMatcher) { - return InnerMatcher.bind(ID); -} - -/// \brief Types of matchers for the top-level classes in the AST class -/// hierarchy. -/// @{ -typedef internal::Matcher<Decl> DeclarationMatcher; -typedef internal::Matcher<Stmt> StatementMatcher; -typedef internal::Matcher<QualType> TypeMatcher; -typedef internal::Matcher<TypeLoc> TypeLocMatcher; -typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher; -typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher; -/// @} - -/// \brief Matches any node. -/// -/// Useful when another matcher requires a child matcher, but there's no -/// additional constraint. This will often be used with an explicit conversion -/// to an \c internal::Matcher<> type such as \c TypeMatcher. -/// -/// Example: \c DeclarationMatcher(anything()) matches all declarations, e.g., -/// \code -/// "int* p" and "void f()" in -/// int* p; -/// void f(); -/// \endcode -/// -/// Usable as: Any Matcher -inline internal::TrueMatcher anything() { return internal::TrueMatcher(); } - -/// \brief Matches the top declaration context. -/// -/// Given -/// \code -/// int X; -/// namespace NS { -/// int Y; -/// } // namespace NS -/// \endcode -/// decl(hasDeclContext(translationUnitDecl())) -/// matches "int X", but not "int Y". -const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> - translationUnitDecl; - -/// \brief Matches typedef declarations. -/// -/// Given -/// \code -/// typedef int X; -/// \endcode -/// typedefDecl() -/// matches "typedef int X" -const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl; - -/// \brief Matches AST nodes that were expanded within the main-file. -/// -/// Example matches X but not Y -/// (matcher = cxxRecordDecl(isExpansionInMainFile()) -/// \code -/// #include <Y.h> -/// class X {}; -/// \endcode -/// Y.h: -/// \code -/// class Y {}; -/// \endcode -/// -/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc> -AST_POLYMORPHIC_MATCHER(isExpansionInMainFile, - AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) { - auto &SourceManager = Finder->getASTContext().getSourceManager(); - return SourceManager.isInMainFile( - SourceManager.getExpansionLoc(Node.getLocStart())); -} - -/// \brief Matches AST nodes that were expanded within system-header-files. -/// -/// Example matches Y but not X -/// (matcher = cxxRecordDecl(isExpansionInSystemHeader()) -/// \code -/// #include <SystemHeader.h> -/// class X {}; -/// \endcode -/// SystemHeader.h: -/// \code -/// class Y {}; -/// \endcode -/// -/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc> -AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader, - AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) { - auto &SourceManager = Finder->getASTContext().getSourceManager(); - auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart()); - if (ExpansionLoc.isInvalid()) { - return false; - } - return SourceManager.isInSystemHeader(ExpansionLoc); -} - -/// \brief Matches AST nodes that were expanded within files whose name is -/// partially matching a given regex. -/// -/// Example matches Y but not X -/// (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*")) -/// \code -/// #include "ASTMatcher.h" -/// class X {}; -/// \endcode -/// ASTMatcher.h: -/// \code -/// class Y {}; -/// \endcode -/// -/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc> -AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching, - AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc), - std::string, RegExp) { - auto &SourceManager = Finder->getASTContext().getSourceManager(); - auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart()); - if (ExpansionLoc.isInvalid()) { - return false; - } - auto FileEntry = - SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc)); - if (!FileEntry) { - return false; - } - - auto Filename = FileEntry->getName(); - llvm::Regex RE(RegExp); - return RE.match(Filename); -} - -/// \brief Matches declarations. -/// -/// Examples matches \c X, \c C, and the friend declaration inside \c C; -/// \code -/// void X(); -/// class C { -/// friend X; -/// }; -/// \endcode -const internal::VariadicAllOfMatcher<Decl> decl; - -/// \brief Matches a declaration of a linkage specification. -/// -/// Given -/// \code -/// extern "C" {} -/// \endcode -/// linkageSpecDecl() -/// matches "extern "C" {}" -const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> - linkageSpecDecl; - -/// \brief Matches a declaration of anything that could have a name. -/// -/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U; -/// \code -/// typedef int X; -/// struct S { -/// union { -/// int i; -/// } U; -/// }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; - -/// \brief Matches a declaration of a namespace. -/// -/// Given -/// \code -/// namespace {} -/// namespace test {} -/// \endcode -/// namespaceDecl() -/// 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 -/// \code -/// class X; -/// template<class T> class Z {}; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - CXXRecordDecl> cxxRecordDecl; - -/// \brief Matches C++ class template declarations. -/// -/// Example matches \c Z -/// \code -/// template<class T> class Z {}; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - ClassTemplateDecl> classTemplateDecl; - -/// \brief Matches C++ class template specializations. -/// -/// Given -/// \code -/// template<typename T> class A {}; -/// template<> class A<double> {}; -/// A<int> a; -/// \endcode -/// classTemplateSpecializationDecl() -/// matches the specializations \c A<int> and \c A<double> -const internal::VariadicDynCastAllOfMatcher< - Decl, - ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; - -/// \brief Matches declarator declarations (field, variable, function -/// and non-type template parameter declarations). -/// -/// Given -/// \code -/// class X { int y; }; -/// \endcode -/// declaratorDecl() -/// matches \c int y. -const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> - declaratorDecl; - -/// \brief Matches parameter variable declarations. -/// -/// Given -/// \code -/// void f(int x); -/// \endcode -/// parmVarDecl() -/// matches \c int x. -const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl; - -/// \brief Matches C++ access specifier declarations. -/// -/// Given -/// \code -/// class C { -/// public: -/// int a; -/// }; -/// \endcode -/// accessSpecDecl() -/// matches 'public:' -const internal::VariadicDynCastAllOfMatcher< - Decl, - AccessSpecDecl> accessSpecDecl; - -/// \brief Matches constructor initializers. -/// -/// Examples matches \c i(42). -/// \code -/// class C { -/// C() : i(42) {} -/// int i; -/// }; -/// \endcode -const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer; - -/// \brief Matches template arguments. -/// -/// Given -/// \code -/// template <typename T> struct C {}; -/// C<int> c; -/// \endcode -/// templateArgument() -/// 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 -/// \code -/// class C { -/// public: int a; -/// protected: int b; -/// private: int c; -/// }; -/// \endcode -/// fieldDecl(isPublic()) -/// matches 'int a;' -AST_MATCHER(Decl, isPublic) { - return Node.getAccess() == AS_public; -} - -/// \brief Matches protected C++ declarations. -/// -/// Given -/// \code -/// class C { -/// public: int a; -/// protected: int b; -/// private: int c; -/// }; -/// \endcode -/// fieldDecl(isProtected()) -/// matches 'int b;' -AST_MATCHER(Decl, isProtected) { - return Node.getAccess() == AS_protected; -} - -/// \brief Matches private C++ declarations. -/// -/// Given -/// \code -/// class C { -/// public: int a; -/// protected: int b; -/// private: int c; -/// }; -/// \endcode -/// fieldDecl(isPrivate()) -/// matches 'int c;' -AST_MATCHER(Decl, isPrivate) { - return Node.getAccess() == AS_private; -} - -/// \brief Matches a declaration that has been implicitly added -/// by the compiler (eg. implicit default/copy constructors). -AST_MATCHER(Decl, isImplicit) { - return Node.isImplicit(); -} - -/// \brief Matches classTemplateSpecializations that have at least one -/// TemplateArgument matching the given InnerMatcher. -/// -/// Given -/// \code -/// template<typename T> class A {}; -/// template<> class A<double> {}; -/// A<int> a; -/// \endcode -/// classTemplateSpecializationDecl(hasAnyTemplateArgument( -/// refersToType(asString("int")))) -/// matches the specialization \c A<int> -AST_POLYMORPHIC_MATCHER_P( - hasAnyTemplateArgument, - AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - TemplateSpecializationType), - internal::Matcher<TemplateArgument>, InnerMatcher) { - ArrayRef<TemplateArgument> List = - internal::getTemplateSpecializationArgs(Node); - return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder, - Builder); -} - -/// \brief Matches expressions that match InnerMatcher after any implicit casts -/// are stripped off. -/// -/// Parentheses and explicit casts are not discarded. -/// Given -/// \code -/// int arr[5]; -/// int a = 0; -/// char b = 0; -/// const int c = a; -/// int *d = arr; -/// long e = (long) 0l; -/// \endcode -/// The matchers -/// \code -/// varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))) -/// varDecl(hasInitializer(ignoringImpCasts(declRefExpr()))) -/// \endcode -/// would match the declarations for a, b, c, and d, but not e. -/// While -/// \code -/// varDecl(hasInitializer(integerLiteral())) -/// varDecl(hasInitializer(declRefExpr())) -/// \endcode -/// 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 -/// \code -/// int a = 0; -/// char b = (0); -/// void* c = reinterpret_cast<char*>(0); -/// char d = char(0); -/// \endcode -/// The matcher -/// varDecl(hasInitializer(ignoringParenCasts(integerLiteral()))) -/// would match the declarations for a, b, c, and d. -/// while -/// varDecl(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 -/// \code -/// int arr[5]; -/// int a = 0; -/// char b = (0); -/// const int c = a; -/// int *d = (arr); -/// long e = ((long) 0l); -/// \endcode -/// The matchers -/// varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral()))) -/// varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr()))) -/// would match the declarations for a, b, c, and d, but not e. -/// while -/// varDecl(hasInitializer(integerLiteral())) -/// varDecl(hasInitializer(declRefExpr())) -/// 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 InnerMatcher. -/// -/// Given -/// \code -/// template<typename T, typename U> class A {}; -/// A<bool, int> b; -/// A<int, bool> c; -/// \endcode -/// classTemplateSpecializationDecl(hasTemplateArgument( -/// 1, refersToType(asString("int")))) -/// matches the specialization \c A<bool, int> -AST_POLYMORPHIC_MATCHER_P2( - hasTemplateArgument, - AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - TemplateSpecializationType), - unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) { - ArrayRef<TemplateArgument> List = - internal::getTemplateSpecializationArgs(Node); - if (List.size() <= N) - return false; - return InnerMatcher.matches(List[N], Finder, Builder); -} - -/// \brief Matches if the number of template arguments equals \p N. -/// -/// Given -/// \code -/// template<typename T> struct C {}; -/// C<int> c; -/// \endcode -/// classTemplateSpecializationDecl(templateArgumentCountIs(1)) -/// matches C<int>. -AST_POLYMORPHIC_MATCHER_P( - templateArgumentCountIs, - AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - TemplateSpecializationType), - unsigned, N) { - return internal::getTemplateSpecializationArgs(Node).size() == N; -} - -/// \brief Matches a TemplateArgument that refers to a certain type. -/// -/// Given -/// \code -/// struct X {}; -/// template<typename T> struct A {}; -/// A<X> a; -/// \endcode -/// classTemplateSpecializationDecl(hasAnyTemplateArgument( -/// refersToType(class(hasName("X"))))) -/// matches the specialization \c A<X> -AST_MATCHER_P(TemplateArgument, refersToType, - internal::Matcher<QualType>, InnerMatcher) { - if (Node.getKind() != TemplateArgument::Type) - return false; - return InnerMatcher.matches(Node.getAsType(), Finder, Builder); -} - -/// \brief Matches a canonical TemplateArgument that refers to a certain -/// declaration. -/// -/// Given -/// \code -/// template<typename T> struct A {}; -/// struct B { B* next; }; -/// A<&B::next> a; -/// \endcode -/// classTemplateSpecializationDecl(hasAnyTemplateArgument( -/// refersToDeclaration(fieldDecl(hasName("next")))) -/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching -/// \c B::next -AST_MATCHER_P(TemplateArgument, refersToDeclaration, - internal::Matcher<Decl>, InnerMatcher) { - if (Node.getKind() == TemplateArgument::Declaration) - return InnerMatcher.matches(*Node.getAsDecl(), Finder, Builder); - return false; -} - -/// \brief Matches a sugar TemplateArgument that refers to a certain expression. -/// -/// Given -/// \code -/// template<typename T> struct A {}; -/// struct B { B* next; }; -/// A<&B::next> a; -/// \endcode -/// templateSpecializationType(hasAnyTemplateArgument( -/// isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next")))))))) -/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching -/// \c B::next -AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) { - if (Node.getKind() == TemplateArgument::Expression) - return InnerMatcher.matches(*Node.getAsExpr(), Finder, Builder); - return false; -} - -/// \brief Matches a TemplateArgument that is an integral value. -/// -/// Given -/// \code -/// template<int T> struct A {}; -/// C<42> c; -/// \endcode -/// classTemplateSpecializationDecl( -/// hasAnyTemplateArgument(isIntegral())) -/// matches the implicit instantiation of C in C<42> -/// with isIntegral() matching 42. -AST_MATCHER(TemplateArgument, isIntegral) { - return Node.getKind() == TemplateArgument::Integral; -} - -/// \brief Matches a TemplateArgument that referes to an integral type. -/// -/// Given -/// \code -/// template<int T> struct A {}; -/// C<42> c; -/// \endcode -/// classTemplateSpecializationDecl( -/// hasAnyTemplateArgument(refersToIntegralType(asString("int")))) -/// matches the implicit instantiation of C in C<42>. -AST_MATCHER_P(TemplateArgument, refersToIntegralType, - internal::Matcher<QualType>, InnerMatcher) { - if (Node.getKind() != TemplateArgument::Integral) - return false; - return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder); -} - -/// \brief Matches a TemplateArgument of integral type with a given value. -/// -/// Note that 'Value' is a string as the template argument's value is -/// an arbitrary precision integer. 'Value' must be euqal to the canonical -/// representation of that integral value in base 10. -/// -/// Given -/// \code -/// template<int T> struct A {}; -/// C<42> c; -/// \endcode -/// classTemplateSpecializationDecl( -/// hasAnyTemplateArgument(equalsIntegralValue("42"))) -/// matches the implicit instantiation of C in C<42>. -AST_MATCHER_P(TemplateArgument, equalsIntegralValue, - std::string, Value) { - if (Node.getKind() != TemplateArgument::Integral) - return false; - return Node.getAsIntegral().toString(10) == Value; -} - -/// \brief Matches any value declaration. -/// -/// Example matches A, B, C and F -/// \code -/// enum X { A, B, C }; -/// void F(); -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; - -/// \brief Matches C++ constructor declarations. -/// -/// Example matches Foo::Foo() and Foo::Foo(int) -/// \code -/// class Foo { -/// public: -/// Foo(); -/// Foo(int); -/// int DoSomething(); -/// }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - CXXConstructorDecl> cxxConstructorDecl; - -/// \brief Matches explicit C++ destructor declarations. -/// -/// Example matches Foo::~Foo() -/// \code -/// class Foo { -/// public: -/// virtual ~Foo(); -/// }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - CXXDestructorDecl> cxxDestructorDecl; - -/// \brief Matches enum declarations. -/// -/// Example matches X -/// \code -/// enum X { -/// A, B, C -/// }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; - -/// \brief Matches enum constants. -/// -/// Example matches A, B, C -/// \code -/// enum X { -/// A, B, C -/// }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - EnumConstantDecl> enumConstantDecl; - -/// \brief Matches method declarations. -/// -/// Example matches y -/// \code -/// class X { void y(); }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; - -/// \brief Matches conversion operator declarations. -/// -/// Example matches the operator. -/// \code -/// class X { operator int() const; }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> - cxxConversionDecl; - -/// \brief Matches variable declarations. -/// -/// Note: this does not match declarations of member variables, which are -/// "field" declarations in Clang parlance. -/// -/// Example matches a -/// \code -/// int a; -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; - -/// \brief Matches field declarations. -/// -/// Given -/// \code -/// class X { int m; }; -/// \endcode -/// fieldDecl() -/// matches 'm'. -const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; - -/// \brief Matches function declarations. -/// -/// Example matches f -/// \code -/// void f(); -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl; - -/// \brief Matches C++ function template declarations. -/// -/// Example matches f -/// \code -/// template<class T> void f(T t) {} -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - FunctionTemplateDecl> functionTemplateDecl; - -/// \brief Matches friend declarations. -/// -/// Given -/// \code -/// class X { friend void foo(); }; -/// \endcode -/// friendDecl() -/// matches 'friend void foo()'. -const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; - -/// \brief Matches statements. -/// -/// Given -/// \code -/// { ++a; } -/// \endcode -/// stmt() -/// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicAllOfMatcher<Stmt> stmt; - -/// \brief Matches declaration statements. -/// -/// Given -/// \code -/// int a; -/// \endcode -/// declStmt() -/// matches 'int a'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - DeclStmt> declStmt; - -/// \brief Matches member expressions. -/// -/// Given -/// \code -/// class Y { -/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } -/// int a; static int b; -/// }; -/// \endcode -/// memberExpr() -/// matches this->x, x, y.x, a, this->b -const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; - -/// \brief Matches call expressions. -/// -/// Example matches x.y() and y() -/// \code -/// X x; -/// x.y(); -/// y(); -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; - -/// \brief Matches lambda expressions. -/// -/// Example matches [&](){return 5;} -/// \code -/// [&](){return 5;} -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; - -/// \brief Matches member call expressions. -/// -/// Example matches x.y() -/// \code -/// X x; -/// x.y(); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXMemberCallExpr> cxxMemberCallExpr; - -/// \brief Matches ObjectiveC Message invocation expressions. -/// -/// The innermost message send invokes the "alloc" class method on the -/// NSString class, while the outermost message send invokes the -/// "initWithString" instance method on the object returned from -/// NSString's "alloc". This matcher should match both message sends. -/// \code -/// [[NSString alloc] initWithString:@"Hello"] -/// \endcode -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. -/// -/// Example matches std::string() -/// \code -/// const std::string str = std::string(); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ExprWithCleanups> exprWithCleanups; - -/// \brief Matches init list expressions. -/// -/// Given -/// \code -/// int a[] = { 1, 2 }; -/// struct B { int x, y; }; -/// B b = { 5, 6 }; -/// \endcode -/// initListExpr() -/// matches "{ 1, 2 }" and "{ 5, 6 }" -const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; - -/// \brief Matches substitutions of non-type template parameters. -/// -/// Given -/// \code -/// template <int N> -/// struct A { static const int n = N; }; -/// struct B : public A<42> {}; -/// \endcode -/// substNonTypeTemplateParmExpr() -/// matches "N" in the right-hand side of "static const int n = N;" -const internal::VariadicDynCastAllOfMatcher< - Stmt, - SubstNonTypeTemplateParmExpr> substNonTypeTemplateParmExpr; - -/// \brief Matches using declarations. -/// -/// Given -/// \code -/// namespace X { int x; } -/// using X::x; -/// \endcode -/// usingDecl() -/// matches \code using X::x \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; - -/// \brief Matches using namespace declarations. -/// -/// Given -/// \code -/// namespace X { int x; } -/// using namespace X; -/// \endcode -/// usingDirectiveDecl() -/// matches \code using namespace X \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - UsingDirectiveDecl> usingDirectiveDecl; - -/// \brief Matches unresolved using value declarations. -/// -/// Given -/// \code -/// template<typename X> -/// class C : private X { -/// using X::x; -/// }; -/// \endcode -/// unresolvedUsingValueDecl() -/// matches \code using X::x \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - UnresolvedUsingValueDecl> unresolvedUsingValueDecl; - -/// \brief Matches 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 = cxxConstructExpr()) -/// \code -/// void f(const string &a, const string &b); -/// char *ptr; -/// int n; -/// f(string(ptr, n), ptr); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXConstructExpr> cxxConstructExpr; - -/// \brief Matches unresolved constructor call expressions. -/// -/// Example matches T(t) in return statement of f -/// (matcher = cxxUnresolvedConstructExpr()) -/// \code -/// template <typename T> -/// void f(const T& t) { return T(t); } -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXUnresolvedConstructExpr> cxxUnresolvedConstructExpr; - -/// \brief Matches implicit and explicit this expressions. -/// -/// Example matches the implicit this expression in "return i". -/// (matcher = cxxThisExpr()) -/// \code -/// struct foo { -/// int i; -/// int f() { return i; } -/// }; -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr; - -/// \brief Matches nodes where temporaries are created. -/// -/// Example matches FunctionTakesString(GetStringByValue()) -/// (matcher = cxxBindTemporaryExpr()) -/// \code -/// FunctionTakesString(GetStringByValue()); -/// FunctionTakesStringByPointer(GetStringPointer()); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXBindTemporaryExpr> cxxBindTemporaryExpr; - -/// \brief Matches nodes where temporaries are materialized. -/// -/// Example: Given -/// \code -/// struct T {void func()}; -/// T f(); -/// void g(T); -/// \endcode -/// materializeTemporaryExpr() matches 'f()' in these statements -/// \code -/// T u(f()); -/// g(f()); -/// \endcode -/// but does not match -/// \code -/// f(); -/// f().func(); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - MaterializeTemporaryExpr> materializeTemporaryExpr; - -/// \brief Matches new expressions. -/// -/// Given -/// \code -/// new X; -/// \endcode -/// cxxNewExpr() -/// matches 'new X'. -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; - -/// \brief Matches delete expressions. -/// -/// Given -/// \code -/// delete X; -/// \endcode -/// cxxDeleteExpr() -/// matches 'delete X'. -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr; - -/// \brief Matches array subscript expressions. -/// -/// Given -/// \code -/// int i = a[1]; -/// \endcode -/// arraySubscriptExpr() -/// matches "a[1]" -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ArraySubscriptExpr> arraySubscriptExpr; - -/// \brief Matches the value of a default argument at the call site. -/// -/// Example matches the CXXDefaultArgExpr placeholder inserted for the -/// default value of the second parameter in the call expression f(42) -/// (matcher = cxxDefaultArgExpr()) -/// \code -/// void f(int x, int y = 0); -/// f(42); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXDefaultArgExpr> cxxDefaultArgExpr; - -/// \brief Matches overloaded operator calls. -/// -/// Note that if an operator isn't overloaded, it won't match. Instead, use -/// binaryOperator matcher. -/// Currently it does not match operators such as new delete. -/// FIXME: figure out why these do not match? -/// -/// Example matches both operator<<((o << b), c) and operator<<(o, b) -/// (matcher = cxxOperatorCallExpr()) -/// \code -/// ostream &operator<< (ostream &out, int i) { }; -/// ostream &o; int b = 1, c = 1; -/// o << b << c; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXOperatorCallExpr> cxxOperatorCallExpr; - -/// \brief Matches expressions. -/// -/// Example matches x() -/// \code -/// void f() { x(); } -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; - -/// \brief Matches expressions that refer to declarations. -/// -/// Example matches x in if (x) -/// \code -/// bool x; -/// if (x) {} -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; - -/// \brief Matches if statements. -/// -/// Example matches 'if (x) {}' -/// \code -/// if (x) {} -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; - -/// \brief Matches for statements. -/// -/// Example matches 'for (;;) {}' -/// \code -/// for (;;) {} -/// int i[] = {1, 2, 3}; for (auto a : i); -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; - -/// \brief Matches the increment statement of a for loop. -/// -/// Example: -/// forStmt(hasIncrement(unaryOperator(hasOperatorName("++")))) -/// matches '++x' in -/// \code -/// for (x; x < N; ++x) { } -/// \endcode -AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, - InnerMatcher) { - const Stmt *const Increment = Node.getInc(); - return (Increment != nullptr && - InnerMatcher.matches(*Increment, Finder, Builder)); -} - -/// \brief Matches the initialization statement of a for loop. -/// -/// Example: -/// forStmt(hasLoopInit(declStmt())) -/// matches 'int x = 0' in -/// \code -/// for (int x = 0; x < N; ++x) { } -/// \endcode -AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, - InnerMatcher) { - const Stmt *const Init = Node.getInit(); - return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder)); -} - -/// \brief Matches range-based for statements. -/// -/// 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> cxxForRangeStmt; - -/// \brief Matches the initialization statement of a for loop. -/// -/// Example: -/// forStmt(hasLoopVariable(anything())) -/// matches 'int x' in -/// \code -/// for (int x : a) { } -/// \endcode -AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher<VarDecl>, - InnerMatcher) { - const VarDecl *const Var = Node.getLoopVariable(); - return (Var != nullptr && InnerMatcher.matches(*Var, Finder, Builder)); -} - -/// \brief Matches the range initialization statement of a for loop. -/// -/// Example: -/// forStmt(hasRangeInit(anything())) -/// matches 'a' in -/// \code -/// for (int x : a) { } -/// \endcode -AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>, - InnerMatcher) { - const Expr *const Init = Node.getRangeInit(); - return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder)); -} - -/// \brief Matches while statements. -/// -/// Given -/// \code -/// while (true) {} -/// \endcode -/// whileStmt() -/// matches 'while (true) {}'. -const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; - -/// \brief Matches do statements. -/// -/// Given -/// \code -/// do {} while (true); -/// \endcode -/// doStmt() -/// matches 'do {} while(true)' -const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; - -/// \brief Matches break statements. -/// -/// Given -/// \code -/// while (true) { break; } -/// \endcode -/// breakStmt() -/// matches 'break' -const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; - -/// \brief Matches continue statements. -/// -/// Given -/// \code -/// while (true) { continue; } -/// \endcode -/// continueStmt() -/// matches 'continue' -const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; - -/// \brief Matches return statements. -/// -/// Given -/// \code -/// return 1; -/// \endcode -/// returnStmt() -/// matches 'return 1' -const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; - -/// \brief Matches goto statements. -/// -/// Given -/// \code -/// goto FOO; -/// FOO: bar(); -/// \endcode -/// gotoStmt() -/// matches 'goto FOO' -const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; - -/// \brief Matches label statements. -/// -/// Given -/// \code -/// goto FOO; -/// FOO: bar(); -/// \endcode -/// labelStmt() -/// matches 'FOO:' -const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; - -/// \brief Matches switch statements. -/// -/// Given -/// \code -/// switch(a) { case 42: break; default: break; } -/// \endcode -/// switchStmt() -/// matches 'switch(a)'. -const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; - -/// \brief Matches case and default statements inside switch statements. -/// -/// Given -/// \code -/// switch(a) { case 42: break; default: break; } -/// \endcode -/// switchCase() -/// matches 'case 42: break;' and 'default: break;'. -const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; - -/// \brief Matches case statements inside switch statements. -/// -/// Given -/// \code -/// switch(a) { case 42: break; default: break; } -/// \endcode -/// caseStmt() -/// matches 'case 42: break;'. -const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; - -/// \brief Matches default statements inside switch statements. -/// -/// Given -/// \code -/// switch(a) { case 42: break; default: break; } -/// \endcode -/// defaultStmt() -/// matches 'default: break;'. -const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt; - -/// \brief Matches compound statements. -/// -/// Example matches '{}' and '{{}}'in 'for (;;) {{}}' -/// \code -/// for (;;) {{}} -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt; - -/// \brief Matches catch statements. -/// -/// \code -/// try {} catch(int i) {} -/// \endcode -/// cxxCatchStmt() -/// matches 'catch(int i)' -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt; - -/// \brief Matches try statements. -/// -/// \code -/// try {} catch(int i) {} -/// \endcode -/// cxxTryStmt() -/// matches 'try {}' -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; - -/// \brief Matches throw expressions. -/// -/// \code -/// try { throw 5; } catch(int i) {} -/// \endcode -/// cxxThrowExpr() -/// matches 'throw 5' -const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr; - -/// \brief Matches null statements. -/// -/// \code -/// foo();; -/// \endcode -/// nullStmt() -/// matches the second ';' -const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; - -/// \brief Matches asm statements. -/// -/// \code -/// int i = 100; -/// __asm("mov al, 2"); -/// \endcode -/// asmStmt() -/// matches '__asm("mov al, 2")' -const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; - -/// \brief Matches bool literals. -/// -/// Example matches true -/// \code -/// true -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXBoolLiteralExpr> cxxBoolLiteral; - -/// \brief Matches string literals (also matches wide string literals). -/// -/// Example matches "abcd", L"abcd" -/// \code -/// char *s = "abcd"; wchar_t *ws = L"abcd" -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - StringLiteral> stringLiteral; - -/// \brief Matches character literals (also matches wchar_t). -/// -/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral), -/// though. -/// -/// Example matches 'a', L'a' -/// \code -/// char ch = 'a'; wchar_t chw = L'a'; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CharacterLiteral> characterLiteral; - -/// \brief Matches integer literals of all sizes / encodings, e.g. -/// 1, 1L, 0x1 and 1U. -/// -/// Does not match character-encoded integers such as L'a'. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - IntegerLiteral> integerLiteral; - -/// \brief Matches float literals of all sizes / encodings, e.g. -/// 1.0, 1.0f, 1.0L and 1e10. -/// -/// Does not match implicit conversions such as -/// \code -/// float a = 10; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - FloatingLiteral> floatLiteral; - -/// \brief Matches user defined literal operator call. -/// -/// Example match: "foo"_suffix -const internal::VariadicDynCastAllOfMatcher< - Stmt, - UserDefinedLiteral> userDefinedLiteral; - -/// \brief Matches compound (i.e. non-scalar) literals -/// -/// Example match: {1}, (1, 2) -/// \code -/// int array[4] = {1}; vector int myvec = (vector int)(1, 2); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CompoundLiteralExpr> compoundLiteralExpr; - -/// \brief Matches nullptr literal. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; - -/// \brief Matches GNU __null expression. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - GNUNullExpr> gnuNullExpr; - -/// \brief Matches binary operator expressions. -/// -/// Example matches a || b -/// \code -/// !(a || b) -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - BinaryOperator> binaryOperator; - -/// \brief Matches unary operator expressions. -/// -/// Example matches !a -/// \code -/// !a || b -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - UnaryOperator> unaryOperator; - -/// \brief Matches conditional operator expressions. -/// -/// Example matches a ? b : c -/// \code -/// (a ? b : c) + 42 -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ConditionalOperator> conditionalOperator; - -/// \brief Matches a C++ static_assert declaration. -/// -/// Example: -/// staticAssertExpr() -/// matches -/// static_assert(sizeof(S) == sizeof(int)) -/// in -/// \code -/// struct S { -/// int x; -/// }; -/// static_assert(sizeof(S) == sizeof(int)); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Decl, - StaticAssertDecl> staticAssertDecl; - -/// \brief Matches a reinterpret_cast expression. -/// -/// Either the source expression or the destination type can be matched -/// using has(), but hasDestinationType() is more specific and can be -/// more readable. -/// -/// Example matches reinterpret_cast<char*>(&p) in -/// \code -/// void* p = reinterpret_cast<char*>(&p); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXReinterpretCastExpr> cxxReinterpretCastExpr; - -/// \brief Matches a C++ static_cast expression. -/// -/// \see hasDestinationType -/// \see reinterpretCast -/// -/// Example: -/// cxxStaticCastExpr() -/// matches -/// static_cast<long>(8) -/// in -/// \code -/// long eight(static_cast<long>(8)); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXStaticCastExpr> cxxStaticCastExpr; - -/// \brief Matches a dynamic_cast expression. -/// -/// Example: -/// cxxDynamicCastExpr() -/// matches -/// dynamic_cast<D*>(&b); -/// in -/// \code -/// struct B { virtual ~B() {} }; struct D : B {}; -/// B b; -/// D* p = dynamic_cast<D*>(&b); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXDynamicCastExpr> cxxDynamicCastExpr; - -/// \brief Matches a const_cast expression. -/// -/// Example: Matches const_cast<int*>(&r) in -/// \code -/// int n = 42; -/// const int &r(n); -/// int* p = const_cast<int*>(&r); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXConstCastExpr> cxxConstCastExpr; - -/// \brief Matches a C-style cast expression. -/// -/// Example: Matches (int*) 2.2f in -/// \code -/// int i = (int) 2.2f; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CStyleCastExpr> cStyleCastExpr; - -/// \brief Matches explicit cast expressions. -/// -/// Matches any cast expression written in user code, whether it be a -/// C-style cast, a functional-style cast, or a keyword cast. -/// -/// Does not match implicit conversions. -/// -/// Note: the name "explicitCast" is chosen to match Clang's terminology, as -/// Clang uses the term "cast" to apply to implicit conversions as well as to -/// actual cast expressions. -/// -/// \see hasDestinationType. -/// -/// Example: matches all five of the casts in -/// \code -/// int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42))))) -/// \endcode -/// but does not match the implicit conversion in -/// \code -/// long ell = 42; -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - ExplicitCastExpr> explicitCastExpr; - -/// \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< - Stmt, - ImplicitCastExpr> implicitCastExpr; - -/// \brief Matches any cast nodes of Clang's AST. -/// -/// Example: castExpr() matches each of the following: -/// \code -/// (int) 3; -/// const_cast<Expr *>(SubExpr); -/// char c = 0; -/// \endcode -/// but does not match -/// \code -/// int i = (0); -/// int k = 0; -/// \endcode -const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; - -/// \brief Matches functional cast expressions -/// -/// Example: Matches Foo(bar); -/// \code -/// Foo f = bar; -/// Foo g = (Foo) bar; -/// Foo h = Foo(bar); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXFunctionalCastExpr> cxxFunctionalCastExpr; - -/// \brief Matches functional cast expressions having N != 1 arguments -/// -/// Example: Matches Foo(bar, bar) -/// \code -/// Foo h = Foo(bar, bar); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CXXTemporaryObjectExpr> cxxTemporaryObjectExpr; - -/// \brief Matches \c QualTypes in the clang AST. -const internal::VariadicAllOfMatcher<QualType> qualType; - -/// \brief Matches \c Types in the clang AST. -const internal::VariadicAllOfMatcher<Type> type; - -/// \brief Matches \c TypeLocs in the clang AST. -const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; - -/// \brief Matches if any of the given matchers matches. -/// -/// Unlike \c anyOf, \c eachOf will generate a match result for each -/// matching submatcher. -/// -/// For example, in: -/// \code -/// class A { int a; int b; }; -/// \endcode -/// The matcher: -/// \code -/// 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 -/// \c b. -/// -/// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = { - internal::DynTypedMatcher::VO_EachOf -}; - -/// \brief Matches if any of the given matchers matches. -/// -/// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = { - internal::DynTypedMatcher::VO_AnyOf -}; - -/// \brief Matches if all given matchers match. -/// -/// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = { - internal::DynTypedMatcher::VO_AllOf -}; - -/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) -/// -/// Given -/// \code -/// Foo x = bar; -/// int y = sizeof(x) + alignof(x); -/// \endcode -/// 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 -/// \code -/// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c); -/// \endcode -/// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")) -/// matches \c sizeof(a) and \c alignof(c) -AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType, - internal::Matcher<QualType>, InnerMatcher) { - const QualType ArgumentType = Node.getTypeOfArgument(); - return InnerMatcher.matches(ArgumentType, Finder, Builder); -} - -/// \brief Matches unary expressions of a certain kind. -/// -/// Given -/// \code -/// int x; -/// int s = sizeof(x) + alignof(x) -/// \endcode -/// 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> &InnerMatcher) { - return stmt(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_AlignOf), InnerMatcher))); -} - -/// \brief Same as unaryExprOrTypeTraitExpr, but only matching -/// sizeof. -inline internal::Matcher<Stmt> sizeOfExpr( - const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { - return stmt(unaryExprOrTypeTraitExpr( - allOf(ofKind(UETT_SizeOf), InnerMatcher))); -} - -/// \brief Matches NamedDecl nodes that have the specified name. -/// -/// 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 (Name == "X") -/// \code -/// class X; -/// \endcode -/// -/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X") -/// \code -/// namespace a { namespace b { class X; } } -/// \endcode -inline internal::Matcher<NamedDecl> hasName(const std::string &Name) { - return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Name)); -} - -/// \brief Matches NamedDecl nodes whose fully qualified names contain -/// a substring matched by 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") -/// \code -/// class X; -/// \endcode -/// -/// Example matches X (regexp is one of "::X", "^foo::.*X", among others) -/// \code -/// namespace foo { namespace bar { class X; } } -/// \endcode -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 -/// "operator" prefix: e.g. "<<". -/// -/// Given: -/// \code -/// class A { int operator*(); }; -/// const A &operator<<(const A &a, const A &b); -/// A a; -/// a << a; // <-- This matches -/// \endcode -/// -/// \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< - internal::HasOverloadedOperatorNameMatcher, StringRef, - AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)> -hasOverloadedOperatorName(StringRef Name) { - return internal::PolymorphicMatcherWithParam1< - internal::HasOverloadedOperatorNameMatcher, StringRef, - AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name); -} - -/// \brief Matches C++ classes that are directly or indirectly derived from -/// a class matching \c Base. -/// -/// Note that a class is not considered to be derived from itself. -/// -/// Example matches Y, Z, C (Base == hasName("X")) -/// \code -/// class X; -/// class Y : public X {}; // directly derived -/// class Z : public Y {}; // indirectly derived -/// typedef X A; -/// typedef A B; -/// class C : public B {}; // derived from a typedef of X -/// \endcode -/// -/// In the following example, Bar matches isDerivedFrom(hasName("X")): -/// \code -/// class Foo; -/// typedef Foo X; -/// class Bar : public Foo {}; // derived from a type that X is a typedef of -/// \endcode -AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, - internal::Matcher<NamedDecl>, Base) { - return Finder->classIsDerivedFrom(&Node, Base, Builder); -} - -/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)). -AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) { - assert(!BaseName.empty()); - return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); -} - -/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly -/// match \c Base. -AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, - internal::Matcher<NamedDecl>, Base, 0) { - return Matcher<CXXRecordDecl>(anyOf(Base, isDerivedFrom(Base))) - .matches(Node, Finder, Builder); -} - -/// \brief Overloaded method as shortcut for -/// \c isSameOrDerivedFrom(hasName(...)). -AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string, - BaseName, 1) { - assert(!BaseName.empty()); - return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); -} - -/// \brief Matches the first method of a class or struct that satisfies \c -/// InnerMatcher. -/// -/// Given: -/// \code -/// class A { void func(); }; -/// class B { void member(); }; -/// \endcode -/// -/// \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(), - Node.method_end(), Finder, Builder); -} - -/// \brief Matches AST nodes that have child AST nodes that match the -/// provided matcher. -/// -/// 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 {}; }; -/// class Z { class Y { class X {}; }; }; // Does not match Z. -/// \endcode -/// -/// ChildT must be an AST base type. -/// -/// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> -LLVM_ATTRIBUTE_UNUSED has = {}; - -/// \brief Matches AST nodes that have descendant AST nodes that match the -/// provided matcher. -/// -/// Example matches X, Y, Z -/// (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 {}; }; -/// class Z { class Y { class X {}; }; }; -/// \endcode -/// -/// DescendantT must be an AST base type. -/// -/// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher> -LLVM_ATTRIBUTE_UNUSED hasDescendant = {}; - -/// \brief Matches AST nodes that have child AST nodes that match the -/// provided matcher. -/// -/// 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 {}; }; -/// class Z { class Y { class X {}; }; }; // Does not match Z. -/// \endcode -/// -/// ChildT must be an AST base type. -/// -/// As opposed to 'has', 'forEach' will cause a match for each result that -/// matches instead of only on the first one. -/// -/// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> -LLVM_ATTRIBUTE_UNUSED forEach = {}; - -/// \brief Matches AST nodes that have descendant AST nodes that match the -/// provided matcher. -/// -/// Example matches X, A, B, C -/// (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 {}; }; -/// class B { class C { class X {}; }; }; -/// \endcode -/// -/// DescendantT must be an AST base type. -/// -/// As opposed to 'hasDescendant', 'forEachDescendant' will cause a match for -/// each result that matches instead of only on the first one. -/// -/// Note: Recursively combined ForEachDescendant can cause many matches: -/// 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 {}; }; }; }; }; -/// \endcode -/// -/// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher> -LLVM_ATTRIBUTE_UNUSED forEachDescendant = {}; - -/// \brief Matches if the node or any descendant matches. -/// -/// Generates results for each match. -/// -/// For example, in: -/// \code -/// class A { class B {}; class C {}; }; -/// \endcode -/// The matcher: -/// \code -/// cxxRecordDecl(hasName("::A"), -/// findAll(cxxRecordDecl(isDefinition()).bind("m"))) -/// \endcode -/// will generate results for \c A, \c B and \c C. -/// -/// Usable as: Any Matcher -template <typename T> -internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) { - return eachOf(Matcher, forEachDescendant(Matcher)); -} - -/// \brief Matches AST nodes that have a parent that matches the provided -/// matcher. -/// -/// Given -/// \code -/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } } -/// \endcode -/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }". -/// -/// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc< - 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. -/// -/// Given -/// \code -/// void f() { if (true) { int x = 42; } } -/// void g() { for (;;) { int x = 43; } } -/// \endcode -/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43. -/// -/// Usable as: Any Matcher -const internal::ArgumentAdaptingMatcherFunc< - 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 = cxxRecordDecl(unless(hasName("X")))) -/// \code -/// class X {}; -/// class Y {}; -/// \endcode -/// -/// Usable as: Any Matcher -const internal::VariadicOperatorMatcherFunc<1, 1> unless = { - internal::DynTypedMatcher::VO_UnaryNot -}; - -/// \brief Matches a node if the declaration associated with that node -/// matches the given matcher. -/// -/// The associated declaration is: -/// - for type nodes, the declaration of the underlying type -/// - for CallExpr, the declaration of the callee -/// - for MemberExpr, the declaration of the referenced member -/// - for CXXConstructExpr, the declaration of the constructor -/// -/// Also usable as Matcher<T> for any T supporting the getDecl() member -/// function. e.g. various subtypes of clang::Type and various expressions. -/// -/// Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>, -/// Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>, -/// Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>, -/// Matcher<RecordType>, Matcher<TagType>, -/// Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>, -/// Matcher<TypedefType>, Matcher<UnresolvedUsingType> -inline internal::PolymorphicMatcherWithParam1< - internal::HasDeclarationMatcher, internal::Matcher<Decl>, - void(internal::HasDeclarationSupportedTypes)> -hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { - return internal::PolymorphicMatcherWithParam1< - internal::HasDeclarationMatcher, internal::Matcher<Decl>, - void(internal::HasDeclarationSupportedTypes)>(InnerMatcher); -} - -/// \brief Matches on the implicit object argument of a member call expression. -/// -/// Example matches y.x() -/// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))) -/// \code -/// class Y { public: void x(); }; -/// void z() { Y y; y.x(); }", -/// \endcode -/// -/// FIXME: Overload to allow directly matching types? -AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, - InnerMatcher) { - const Expr *ExprNode = Node.getImplicitObjectArgument() - ->IgnoreParenImpCasts(); - return (ExprNode != nullptr && - InnerMatcher.matches(*ExprNode, Finder, Builder)); -} - - -/// \brief Matches on the receiver of an ObjectiveC Message expression. -/// -/// Example -/// matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *"))); -/// matches the [webView ...] message invocation. -/// \code -/// NSString *webViewJavaScript = ... -/// UIWebView *webView = ... -/// [webView stringByEvaluatingJavaScriptFromString:webViewJavascript]; -/// \endcode -AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>, - InnerMatcher) { - const QualType TypeDecl = Node.getReceiverType(); - return InnerMatcher.matches(TypeDecl, Finder, Builder); -} - -/// \brief Matches when BaseName == Selector.getAsString() -/// -/// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:")); -/// matches the outer message expr in the code below, but NOT the message -/// invocation for self.bodyView. -/// \code -/// [self.bodyView loadHTMLString:html baseURL:NULL]; -/// \endcode -AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) { - Selector Sel = Node.getSelector(); - return BaseName.compare(Sel.getAsString()) == 0; -} - - -/// \brief Matches ObjC selectors whose name contains -/// a substring matched by the given RegExp. -/// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?")); -/// matches the outer message expr in the code below, but NOT the message -/// invocation for self.bodyView. -/// \code -/// [self.bodyView loadHTMLString:html baseURL:NULL]; -/// \endcode -AST_MATCHER_P(ObjCMessageExpr, matchesSelector, std::string, RegExp) { - assert(!RegExp.empty()); - std::string SelectorString = Node.getSelector().getAsString(); - llvm::Regex RE(RegExp); - return RE.match(SelectorString); -} - -/// \brief Matches when the selector is the empty selector -/// -/// Matches only when the selector of the objCMessageExpr is NULL. This may -/// represent an error condition in the tree! -AST_MATCHER(ObjCMessageExpr, hasNullSelector) { - return Node.getSelector().isNull(); -} - -/// \brief Matches when the selector is a Unary Selector -/// -/// matcher = objCMessageExpr(matchesSelector(hasUnarySelector()); -/// matches self.bodyView in the code below, but NOT the outer message -/// invocation of "loadHTMLString:baseURL:". -/// \code -/// [self.bodyView loadHTMLString:html baseURL:NULL]; -/// \endcode -AST_MATCHER(ObjCMessageExpr, hasUnarySelector) { - return Node.getSelector().isUnarySelector(); -} - -/// \brief Matches when the selector is a keyword selector -/// -/// objCMessageExpr(hasKeywordSelector()) matches the generated setFrame -/// message expression in -/// -/// \code -/// UIWebView *webView = ...; -/// CGRect bodyFrame = webView.frame; -/// bodyFrame.size.height = self.bodyContentHeight; -/// 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(0)); -/// matches self.bodyView in the code below -/// -/// matcher = objCMessageExpr(numSelectorArgs(2)); -/// matches the invocation of "loadHTMLString:baseURL:" but not that -/// of self.bodyView -/// \code -/// [self.bodyView loadHTMLString:html baseURL:NULL]; -/// \endcode -AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) { - return Node.getSelector().getNumArgs() == N; -} - -/// \brief Matches if the call expression's callee expression matches. -/// -/// Given -/// \code -/// class Y { void x() { this->x(); x(); Y y; y.x(); } }; -/// void f() { f(); } -/// \endcode -/// callExpr(callee(expr())) -/// matches this->x(), x(), y.x(), f() -/// with callee(...) -/// matching this->x, x, y.x, f respectively -/// -/// Note: Callee cannot take the more general internal::Matcher<Expr> -/// because this introduces ambiguous overloads with calls to Callee taking a -/// internal::Matcher<Decl>, as the matcher hierarchy is purely -/// implemented in terms of implicit casts. -AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, - InnerMatcher) { - const Expr *ExprNode = Node.getCallee(); - return (ExprNode != nullptr && - InnerMatcher.matches(*ExprNode, Finder, Builder)); -} - -/// \brief Matches if the call expression's callee's declaration matches the -/// given matcher. -/// -/// Example matches y.x() (matcher = callExpr(callee( -/// cxxMethodDecl(hasName("x"))))) -/// \code -/// class Y { public: void x(); }; -/// void z() { Y y; y.x(); } -/// \endcode -AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher, - 1) { - return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder); -} - -/// \brief Matches if the expression's or declaration's type matches a type -/// matcher. -/// -/// 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; } -/// \endcode -AST_POLYMORPHIC_MATCHER_P_OVERLOAD( - hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, ValueDecl), - internal::Matcher<QualType>, InnerMatcher, 0) { - return InnerMatcher.matches(Node.getType(), Finder, Builder); -} - -/// \brief Overloaded to match the declaration of the expression's or value -/// declaration's type. -/// -/// 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;", 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(cxxRecordDecl(hasName("X"))))) -/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X"))))) -/// \code -/// class X {}; -/// void y(X &x) { x; X z; } -/// \endcode -/// -/// Usable as: Matcher<Expr>, Matcher<ValueDecl> -AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasType, - AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, - ValueDecl), - internal::Matcher<Decl>, InnerMatcher, 1) { - return qualType(hasDeclaration(InnerMatcher)) - .matches(Node.getType(), Finder, Builder); -} - -/// \brief Matches if the type location of the declarator decl's type matches -/// the inner matcher. -/// -/// Given -/// \code -/// int x; -/// \endcode -/// declaratorDecl(hasTypeLoc(loc(asString("int")))) -/// matches int x -AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) { - if (!Node.getTypeSourceInfo()) - // This happens for example for implicit destructors. - return false; - return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder); -} - -/// \brief Matches if the matched type is represented by the given string. -/// -/// Given -/// \code -/// class Y { public: void x(); }; -/// void z() { Y* y; y->x(); } -/// \endcode -/// cxxMemberCallExpr(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. -/// -/// Example matches y->x() -/// (matcher = cxxMemberCallExpr(on(hasType(pointsTo -/// cxxRecordDecl(hasName("Y"))))))) -/// \code -/// class Y { public: void x(); }; -/// void z() { Y *y; y->x(); } -/// \endcode -AST_MATCHER_P( - QualType, pointsTo, internal::Matcher<QualType>, - InnerMatcher) { - return (!Node.isNull() && Node->isAnyPointerType() && - InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); -} - -/// \brief Overloaded to match the pointee type's declaration. -AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>, - InnerMatcher, 1) { - return pointsTo(qualType(hasDeclaration(InnerMatcher))) - .matches(Node, Finder, Builder); -} - -/// \brief Matches if the matched type is a reference type and the referenced -/// type matches the specified matcher. -/// -/// Example matches X &x and const X &y -/// (matcher = varDecl(hasType(references(cxxRecordDecl(hasName("X")))))) -/// \code -/// class X { -/// void a(X b) { -/// X &x = b; -/// const X &y = b; -/// } -/// }; -/// \endcode -AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, - InnerMatcher) { - return (!Node.isNull() && Node->isReferenceType() && - InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); -} - -/// \brief Matches QualTypes whose canonical type matches InnerMatcher. -/// -/// Given: -/// \code -/// typedef int &int_ref; -/// int a; -/// int_ref b = a; -/// \endcode -/// -/// \c varDecl(hasType(qualType(referenceType()))))) will not match the -/// declaration of b but \c -/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does. -AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>, - InnerMatcher) { - if (Node.isNull()) - return false; - return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder); -} - -/// \brief Overloaded to match the referenced type's declaration. -AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>, - InnerMatcher, 1) { - return references(qualType(hasDeclaration(InnerMatcher))) - .matches(Node, Finder, Builder); -} - -AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, - internal::Matcher<Expr>, InnerMatcher) { - const Expr *ExprNode = Node.getImplicitObjectArgument(); - return (ExprNode != nullptr && - 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. -AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, - internal::Matcher<QualType>, InnerMatcher, 0) { - return onImplicitObjectArgument( - anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))) - .matches(Node, Finder, Builder); -} - -/// \brief Overloaded to match the type's declaration. -AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, - internal::Matcher<Decl>, InnerMatcher, 1) { - return onImplicitObjectArgument( - anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))) - .matches(Node, Finder, Builder); -} - -/// \brief Matches a DeclRefExpr that refers to a declaration that matches the -/// specified matcher. -/// -/// Example matches x in if(x) -/// (matcher = declRefExpr(to(varDecl(hasName("x"))))) -/// \code -/// bool x; -/// if (x) {} -/// \endcode -AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, - InnerMatcher) { - const Decl *DeclNode = Node.getDecl(); - return (DeclNode != nullptr && - InnerMatcher.matches(*DeclNode, Finder, Builder)); -} - -/// \brief Matches a \c DeclRefExpr that refers to a declaration through a -/// specific using shadow declaration. -/// -/// Given -/// \code -/// namespace a { void f() {} } -/// using a::f; -/// void g() { -/// f(); // Matches this .. -/// a::f(); // .. but not this. -/// } -/// \endcode -/// declRefExpr(throughUsingDecl(anything())) -/// matches \c f() -AST_MATCHER_P(DeclRefExpr, throughUsingDecl, - internal::Matcher<UsingShadowDecl>, InnerMatcher) { - const NamedDecl *FoundDecl = Node.getFoundDecl(); - if (const UsingShadowDecl *UsingDecl = dyn_cast<UsingShadowDecl>(FoundDecl)) - return InnerMatcher.matches(*UsingDecl, Finder, Builder); - return false; -} - -/// \brief Matches the Decl of a DeclStmt which has a single declaration. -/// -/// Given -/// \code -/// int a, b; -/// int c; -/// \endcode -/// declStmt(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. -/// -/// Example matches x (matcher = varDecl(hasInitializer(callExpr()))) -/// \code -/// bool y() { return true; } -/// bool x = y(); -/// \endcode -AST_MATCHER_P( - VarDecl, hasInitializer, internal::Matcher<Expr>, - InnerMatcher) { - const Expr *Initializer = Node.getAnyInitializer(); - return (Initializer != nullptr && - InnerMatcher.matches(*Initializer, Finder, Builder)); -} - -/// \brief Matches a variable declaration that has function scope and is a -/// non-static local variable. -/// -/// Example matches x (matcher = varDecl(hasLocalStorage()) -/// \code -/// void f() { -/// int x; -/// static int y; -/// } -/// int z; -/// \endcode -AST_MATCHER(VarDecl, hasLocalStorage) { - return Node.hasLocalStorage(); -} - -/// \brief Matches a variable declaration that does not have local storage. -/// -/// Example matches y and z (matcher = varDecl(hasGlobalStorage()) -/// \code -/// void f() { -/// int x; -/// static int y; -/// } -/// int z; -/// \endcode -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). -/// -/// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2))) -/// \code -/// void f(int x, int y); -/// f(0, 0); -/// \endcode -AST_POLYMORPHIC_MATCHER_P(argumentCountIs, - AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr, - CXXConstructExpr, - ObjCMessageExpr), - unsigned, N) { - return Node.getNumArgs() == N; -} - -/// \brief Matches the n'th argument of a call expression or a constructor -/// call expression. -/// -/// Example matches y in x(y) -/// (matcher = callExpr(hasArgument(0, declRefExpr()))) -/// \code -/// void x(int) { int y; x(y); } -/// \endcode -AST_POLYMORPHIC_MATCHER_P2(hasArgument, - AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr, - CXXConstructExpr, - ObjCMessageExpr), - unsigned, N, internal::Matcher<Expr>, InnerMatcher) { - return (N < Node.getNumArgs() && - InnerMatcher.matches( - *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); -} - -/// \brief Matches declaration statements that contain a specific number of -/// declarations. -/// -/// Example: Given -/// \code -/// int a, b; -/// int c; -/// int d = 2, e; -/// \endcode -/// 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()) == (ptrdiff_t)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 -/// \code -/// int a, b = 0; -/// int c; -/// int d = 2, e; -/// \endcode -/// declStmt(containsDeclaration( -/// 0, varDecl(hasInitializer(anything())))) -/// matches only 'int d = 2, e;', and -/// declStmt(containsDeclaration(1, varDecl())) -/// \code -/// matches 'int a, b = 0' as well as 'int d = 2, e;' -/// but 'int c;' is not matched. -/// \endcode -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 C++ catch statement that has a catch-all handler. -/// -/// Given -/// \code -/// try { -/// // ... -/// } catch (int) { -/// // ... -/// } catch (...) { -/// // ... -/// } -/// /endcode -/// cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int). -AST_MATCHER(CXXCatchStmt, isCatchAll) { - return Node.getExceptionDecl() == nullptr; -} - -/// \brief Matches a constructor initializer. -/// -/// Given -/// \code -/// struct Foo { -/// Foo() : foo_(1) { } -/// int foo_; -/// }; -/// \endcode -/// cxxRecordDecl(has(cxxConstructorDecl( -/// hasAnyConstructorInitializer(anything()) -/// ))) -/// record matches Foo, hasAnyConstructorInitializer matches foo_(1) -AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, - internal::Matcher<CXXCtorInitializer>, InnerMatcher) { - return matchesFirstInPointerRange(InnerMatcher, Node.init_begin(), - Node.init_end(), Finder, Builder); -} - -/// \brief Matches the field declaration of a constructor initializer. -/// -/// Given -/// \code -/// struct Foo { -/// Foo() : foo_(1) { } -/// int foo_; -/// }; -/// \endcode -/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer( -/// forField(hasName("foo_")))))) -/// matches Foo -/// with forField matching foo_ -AST_MATCHER_P(CXXCtorInitializer, forField, - internal::Matcher<FieldDecl>, InnerMatcher) { - const FieldDecl *NodeAsDecl = Node.getMember(); - return (NodeAsDecl != nullptr && - InnerMatcher.matches(*NodeAsDecl, Finder, Builder)); -} - -/// \brief Matches the initializer expression of a constructor initializer. -/// -/// Given -/// \code -/// struct Foo { -/// Foo() : foo_(1) { } -/// int foo_; -/// }; -/// \endcode -/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer( -/// withInitializer(integerLiteral(equals(1))))))) -/// matches Foo -/// with withInitializer matching (1) -AST_MATCHER_P(CXXCtorInitializer, withInitializer, - internal::Matcher<Expr>, InnerMatcher) { - const Expr* NodeAsExpr = Node.getInit(); - return (NodeAsExpr != nullptr && - InnerMatcher.matches(*NodeAsExpr, Finder, Builder)); -} - -/// \brief Matches a constructor initializer if it is explicitly written in -/// code (as opposed to implicitly added by the compiler). -/// -/// Given -/// \code -/// struct Foo { -/// Foo() { } -/// Foo(int) : foo_("A") { } -/// string foo_; -/// }; -/// \endcode -/// 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. -/// -/// Given -/// \code -/// void x(int, int, int) { int y; x(1, y, 42); } -/// \endcode -/// callExpr(hasAnyArgument(declRefExpr())) -/// matches x(1, y, 42) -/// with hasAnyArgument(...) -/// matching y -/// -/// FIXME: Currently this will ignore parentheses and implicit casts on -/// the argument before applying the inner matcher. We'll want to remove -/// this to allow for greater control by the user once \c ignoreImplicit() -/// has been implemented. -AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, - AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr, - CXXConstructExpr), - internal::Matcher<Expr>, InnerMatcher) { - for (const Expr *Arg : Node.arguments()) { - BoundNodesTreeBuilder Result(*Builder); - if (InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, &Result)) { - *Builder = std::move(Result); - return true; - } - } - return false; -} - -/// \brief Matches a constructor call expression which uses list initialization. -AST_MATCHER(CXXConstructExpr, isListInitialization) { - return Node.isListInitialization(); -} - -/// \brief Matches the n'th parameter of a function declaration. -/// -/// Given -/// \code -/// class X { void f(int x) {} }; -/// \endcode -/// cxxMethodDecl(hasParameter(0, hasType(varDecl()))) -/// matches f(int x) {} -/// with hasParameter(...) -/// matching int x -AST_MATCHER_P2(FunctionDecl, hasParameter, - unsigned, N, internal::Matcher<ParmVarDecl>, - InnerMatcher) { - return (N < Node.getNumParams() && - InnerMatcher.matches( - *Node.getParamDecl(N), Finder, Builder)); -} - -/// \brief Matches any parameter of a function declaration. -/// -/// Does not match the 'this' parameter of a method. -/// -/// Given -/// \code -/// class X { void f(int x, int y, int z) {} }; -/// \endcode -/// cxxMethodDecl(hasAnyParameter(hasName("y"))) -/// matches f(int x, int y, int z) {} -/// with hasAnyParameter(...) -/// matching int y -AST_MATCHER_P(FunctionDecl, hasAnyParameter, - internal::Matcher<ParmVarDecl>, InnerMatcher) { - return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(), - Node.param_end(), Finder, Builder); -} - -/// \brief Matches \c FunctionDecls that have a specific parameter count. -/// -/// Given -/// \code -/// void f(int i) {} -/// void g(int i, int j) {} -/// \endcode -/// functionDecl(parameterCountIs(2)) -/// matches g(int i, int j) {} -AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) { - return Node.getNumParams() == N; -} - -/// \brief Matches the return type of a function declaration. -/// -/// Given: -/// \code -/// class X { int f() { return 1; } }; -/// \endcode -/// cxxMethodDecl(returns(asString("int"))) -/// matches int f() { return 1; } -AST_MATCHER_P(FunctionDecl, returns, - internal::Matcher<QualType>, InnerMatcher) { - return InnerMatcher.matches(Node.getReturnType(), Finder, Builder); -} - -/// \brief Matches extern "C" function declarations. -/// -/// Given: -/// \code -/// extern "C" void f() {} -/// extern "C" { void g() {} } -/// void h() {} -/// \endcode -/// functionDecl(isExternC()) -/// matches the declaration of f and g, but not the declaration h -AST_MATCHER(FunctionDecl, isExternC) { - return Node.isExternC(); -} - -/// \brief Matches deleted function declarations. -/// -/// Given: -/// \code -/// void Func(); -/// void DeletedFunc() = delete; -/// \endcode -/// functionDecl(isDeleted()) -/// matches the declaration of DeletedFunc, but not Func. -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: -/// \code -/// constexpr int foo = 42; -/// constexpr int bar(); -/// \endcode -/// varDecl(isConstexpr()) -/// matches the declaration of foo. -/// functionDecl(isConstexpr()) -/// matches the declaration of bar. -AST_POLYMORPHIC_MATCHER(isConstexpr, - AST_POLYMORPHIC_SUPPORTED_TYPES(VarDecl, - FunctionDecl)) { - return Node.isConstexpr(); -} - -/// \brief Matches the condition expression of an if statement, for loop, -/// or conditional operator. -/// -/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true)))) -/// \code -/// if (true) {} -/// \endcode -AST_POLYMORPHIC_MATCHER_P(hasCondition, - AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt, - WhileStmt, DoStmt, - ConditionalOperator), - internal::Matcher<Expr>, InnerMatcher) { - const Expr *const Condition = Node.getCond(); - return (Condition != nullptr && - InnerMatcher.matches(*Condition, Finder, Builder)); -} - -/// \brief Matches the then-statement of an if statement. -/// -/// Examples matches the if statement -/// (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true))))) -/// \code -/// if (false) true; else false; -/// \endcode -AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) { - const Stmt *const Then = Node.getThen(); - return (Then != nullptr && InnerMatcher.matches(*Then, Finder, Builder)); -} - -/// \brief Matches the else-statement of an if statement. -/// -/// Examples matches the if statement -/// (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true))))) -/// \code -/// if (false) false; else true; -/// \endcode -AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) { - const Stmt *const Else = Node.getElse(); - return (Else != nullptr && InnerMatcher.matches(*Else, Finder, Builder)); -} - -/// \brief Matches if a node equals a previously bound node. -/// -/// Matches a node if it equals the node previously bound to \p ID. -/// -/// Given -/// \code -/// class X { int a; int b; }; -/// \endcode -/// 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. -/// -/// Note that when multiple matches are involved via \c forEach* matchers, -/// \c equalsBoundNodes acts as a filter. -/// For example: -/// compoundStmt( -/// forEachDescendant(varDecl().bind("d")), -/// forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d")))))) -/// will trigger a match for each combination of variable declaration -/// and reference to that variable declaration within a compound statement. -AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, - AST_POLYMORPHIC_SUPPORTED_TYPES(Stmt, Decl, Type, - QualType), - std::string, ID) { - // FIXME: Figure out whether it makes sense to allow this - // on any other node types. - // For *Loc it probably does not make sense, as those seem - // unique. For NestedNameSepcifier it might make sense, as - // those also have pointer identity, but I'm not sure whether - // they're ever reused. - internal::NotEqualsBoundNodePredicate Predicate; - Predicate.ID = ID; - Predicate.Node = ast_type_traits::DynTypedNode::create(Node); - return Builder->removeBindings(Predicate); -} - -/// \brief Matches the condition variable statement in an if statement. -/// -/// Given -/// \code -/// if (A* a = GetAPointer()) {} -/// \endcode -/// hasConditionVariableStatement(...) -/// matches 'A* a = GetAPointer()'. -AST_MATCHER_P(IfStmt, hasConditionVariableStatement, - internal::Matcher<DeclStmt>, InnerMatcher) { - const DeclStmt* const DeclarationStatement = - Node.getConditionVariableDeclStmt(); - return DeclarationStatement != nullptr && - InnerMatcher.matches(*DeclarationStatement, Finder, Builder); -} - -/// \brief Matches the index expression of an array subscript expression. -/// -/// Given -/// \code -/// int i[5]; -/// void f() { i[1] = 42; } -/// \endcode -/// arraySubscriptExpression(hasIndex(integerLiteral())) -/// matches \c i[1] with the \c integerLiteral() matching \c 1 -AST_MATCHER_P(ArraySubscriptExpr, hasIndex, - internal::Matcher<Expr>, InnerMatcher) { - if (const Expr* Expression = Node.getIdx()) - return InnerMatcher.matches(*Expression, Finder, Builder); - return false; -} - -/// \brief Matches the base expression of an array subscript expression. -/// -/// Given -/// \code -/// int i[5]; -/// void f() { i[1] = 42; } -/// \endcode -/// arraySubscriptExpression(hasBase(implicitCastExpr( -/// hasSourceExpression(declRefExpr())))) -/// matches \c i[1] with the \c declRefExpr() matching \c i -AST_MATCHER_P(ArraySubscriptExpr, hasBase, - internal::Matcher<Expr>, InnerMatcher) { - if (const Expr* Expression = Node.getBase()) - return InnerMatcher.matches(*Expression, Finder, Builder); - return false; -} - -/// \brief Matches a 'for', 'while', or 'do while' statement that has -/// a given body. -/// -/// Given -/// \code -/// for (;;) {} -/// \endcode -/// hasBody(compoundStmt()) -/// matches 'for (;;) {}' -/// with compoundStmt() -/// matching '{}' -AST_POLYMORPHIC_MATCHER_P(hasBody, - AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt, - WhileStmt, - CXXForRangeStmt), - internal::Matcher<Stmt>, InnerMatcher) { - const Stmt *const Statement = Node.getBody(); - return (Statement != nullptr && - InnerMatcher.matches(*Statement, Finder, Builder)); -} - -/// \brief Matches compound statements where at least one substatement matches -/// a given matcher. -/// -/// Given -/// \code -/// { {}; 1+2; } -/// \endcode -/// hasAnySubstatement(compoundStmt()) -/// matches '{ {}; 1+2; }' -/// with compoundStmt() -/// matching '{}' -AST_MATCHER_P(CompoundStmt, hasAnySubstatement, - internal::Matcher<Stmt>, InnerMatcher) { - return matchesFirstInPointerRange(InnerMatcher, Node.body_begin(), - Node.body_end(), Finder, Builder); -} - -/// \brief Checks that a compound statement contains a specific number of -/// child statements. -/// -/// Example: Given -/// \code -/// { for (;;) {} } -/// \endcode -/// compoundStmt(statementCountIs(0))) -/// matches '{}' -/// but does not match the outer compound statement. -AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { - return Node.size() == N; -} - -/// \brief Matches literals that are equal to the given value. -/// -/// Example matches true (matcher = cxxBoolLiteral(equals(true))) -/// \code -/// true -/// \endcode -/// -/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>, -/// Matcher<FloatingLiteral>, Matcher<IntegerLiteral> -template <typename ValueT> -internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher, ValueT> -equals(const ValueT &Value) { - return internal::PolymorphicMatcherWithParam1< - internal::ValueEqualsMatcher, - ValueT>(Value); -} - -/// \brief Matches the operator Name of operator expressions (binary or -/// unary). -/// -/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) -/// \code -/// !(a || b) -/// \endcode -AST_POLYMORPHIC_MATCHER_P(hasOperatorName, - AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, - UnaryOperator), - std::string, Name) { - return Name == Node.getOpcodeStr(Node.getOpcode()); -} - -/// \brief Matches the left hand side of binary operator expressions. -/// -/// Example matches a (matcher = binaryOperator(hasLHS())) -/// \code -/// a || b -/// \endcode -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)); -} - -/// \brief Matches the right hand side of binary operator expressions. -/// -/// Example matches b (matcher = binaryOperator(hasRHS())) -/// \code -/// a || b -/// \endcode -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)); -} - -/// \brief Matches if either the left hand side or the right hand side of a -/// binary operator matches. -inline internal::Matcher<BinaryOperator> hasEitherOperand( - const internal::Matcher<Expr> &InnerMatcher) { - return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)); -} - -/// \brief Matches if the operand of a unary operator matches. -/// -/// Example matches true (matcher = hasUnaryOperand( -/// cxxBoolLiteral(equals(true)))) -/// \code -/// !true -/// \endcode -AST_MATCHER_P(UnaryOperator, hasUnaryOperand, - internal::Matcher<Expr>, InnerMatcher) { - const Expr * const Operand = Node.getSubExpr(); - return (Operand != nullptr && - InnerMatcher.matches(*Operand, Finder, Builder)); -} - -/// \brief Matches if the cast's source expression matches the given matcher. -/// -/// Example: matches "a string" (matcher = -/// 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(); - return (SubExpression != nullptr && - InnerMatcher.matches(*SubExpression, Finder, Builder)); -} - -/// \brief Matches casts whose destination type matches a given matcher. -/// -/// (Note: Clang's AST refers to other conversions as "casts" too, and calls -/// actual casts "explicit" casts.) -AST_MATCHER_P(ExplicitCastExpr, hasDestinationType, - internal::Matcher<QualType>, InnerMatcher) { - const QualType NodeType = Node.getTypeAsWritten(); - return InnerMatcher.matches(NodeType, Finder, Builder); -} - -/// \brief Matches implicit casts whose destination type matches a given -/// matcher. -/// -/// FIXME: Unit test this matcher -AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, - internal::Matcher<QualType>, InnerMatcher) { - 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 -/// \code -/// condition ? a : b -/// \endcode -AST_MATCHER_P(ConditionalOperator, hasTrueExpression, - internal::Matcher<Expr>, InnerMatcher) { - const Expr *Expression = Node.getTrueExpr(); - return (Expression != nullptr && - InnerMatcher.matches(*Expression, Finder, Builder)); -} - -/// \brief Matches the false branch expression of a conditional operator. -/// -/// Example matches b -/// \code -/// condition ? a : b -/// \endcode -AST_MATCHER_P(ConditionalOperator, hasFalseExpression, - internal::Matcher<Expr>, InnerMatcher) { - const Expr *Expression = Node.getFalseExpr(); - return (Expression != nullptr && - InnerMatcher.matches(*Expression, Finder, Builder)); -} - -/// \brief Matches if a declaration has a body attached. -/// -/// Example matches A, va, fa -/// \code -/// class A {}; -/// class B; // Doesn't match, as it has no body. -/// int va; -/// extern int vb; // Doesn't match, as it doesn't define the variable. -/// void fa() {} -/// void fb(); // Doesn't match, as it has no body. -/// \endcode -/// -/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> -AST_POLYMORPHIC_MATCHER(isDefinition, - AST_POLYMORPHIC_SUPPORTED_TYPES(TagDecl, VarDecl, - FunctionDecl)) { - 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. -/// -/// FIXME: Generalize this for other kinds of declarations. -/// FIXME: What other kind of declarations would we need to generalize -/// this to? -/// -/// Example matches A() in the last line -/// (matcher = cxxConstructExpr(hasDeclaration(cxxMethodDecl( -/// ofClass(hasName("A")))))) -/// \code -/// class A { -/// public: -/// A(); -/// }; -/// A a = A(); -/// \endcode -AST_MATCHER_P(CXXMethodDecl, ofClass, - internal::Matcher<CXXRecordDecl>, InnerMatcher) { - const CXXRecordDecl *Parent = Node.getParent(); - return (Parent != nullptr && - InnerMatcher.matches(*Parent, Finder, Builder)); -} - -/// \brief Matches if the given method declaration is virtual. -/// -/// Given -/// \code -/// class A { -/// public: -/// virtual void x(); -/// }; -/// \endcode -/// matches A::x -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 -/// \code -/// class A { -/// public: -/// virtual void x() = 0; -/// }; -/// \endcode -/// matches A::x -AST_MATCHER(CXXMethodDecl, isPure) { - return Node.isPure(); -} - -/// \brief Matches if the given method declaration is const. -/// -/// Given -/// \code -/// struct A { -/// void foo() const; -/// void bar(); -/// }; -/// \endcode -/// -/// 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 -/// \code -/// class A { -/// public: -/// virtual void x(); -/// }; -/// class B : public A { -/// public: -/// virtual void x(); -/// }; -/// \endcode -/// matches B::x -AST_MATCHER(CXXMethodDecl, isOverride) { - return Node.size_overridden_methods() > 0 || Node.hasAttr<OverrideAttr>(); -} - -/// \brief Matches member expressions that are called with '->' as opposed -/// to '.'. -/// -/// Member calls on the implicit this pointer match as called with '->'. -/// -/// Given -/// \code -/// class Y { -/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } -/// int a; -/// static int b; -/// }; -/// \endcode -/// memberExpr(isArrow()) -/// matches this->x, x, y.x, a, this->b -AST_MATCHER(MemberExpr, isArrow) { - return Node.isArrow(); -} - -/// \brief Matches QualType nodes that are of integer type. -/// -/// Given -/// \code -/// void a(int); -/// void b(long); -/// void c(double); -/// \endcode -/// functionDecl(hasAnyParameter(hasType(isInteger()))) -/// matches "a(int)", "b(long)", but not "c(double)". -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. -/// -/// Given -/// \code -/// void a(int); -/// void b(int const); -/// void c(const int); -/// void d(const int*); -/// void e(int const) {}; -/// \endcode -/// functionDecl(hasAnyParameter(hasType(isConstQualified()))) -/// matches "void b(int const)", "void c(const int)" and -/// "void e(int const) {}". It does not match d as there -/// is no top-level const on the parameter type "const int *". -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. -/// -/// Given -/// \code -/// typedef const int const_int; -/// const_int i; -/// int *const j; -/// int *volatile k; -/// int m; -/// \endcode -/// \c varDecl(hasType(hasLocalQualifiers())) matches only \c j and \c k. -/// \c i is const-qualified but the qualifier is not local. -AST_MATCHER(QualType, hasLocalQualifiers) { - return Node.hasLocalQualifiers(); -} - -/// \brief Matches a member expression where the member is matched by a -/// given matcher. -/// -/// Given -/// \code -/// struct { int first, second; } first, second; -/// int i(second.first); -/// int j(first.second); -/// \endcode -/// memberExpr(member(hasName("first"))) -/// matches second.first -/// but not first.second (because the member name there is "second"). -AST_MATCHER_P(MemberExpr, member, - internal::Matcher<ValueDecl>, InnerMatcher) { - return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); -} - -/// \brief Matches a member expression where the object expression is -/// matched by a given matcher. -/// -/// Given -/// \code -/// struct X { int m; }; -/// void f(X x) { x.m; m; } -/// \endcode -/// 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*. -AST_MATCHER_P(MemberExpr, hasObjectExpression, - internal::Matcher<Expr>, InnerMatcher) { - return InnerMatcher.matches(*Node.getBase(), Finder, Builder); -} - -/// \brief Matches any using shadow declaration. -/// -/// Given -/// \code -/// namespace X { void b(); } -/// using X::b; -/// \endcode -/// usingDecl(hasAnyUsingShadowDecl(hasName("b")))) -/// matches \code using X::b \endcode -AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, - internal::Matcher<UsingShadowDecl>, InnerMatcher) { - return matchesFirstInPointerRange(InnerMatcher, Node.shadow_begin(), - Node.shadow_end(), Finder, Builder); -} - -/// \brief Matches a using shadow declaration where the target declaration is -/// matched by the given matcher. -/// -/// Given -/// \code -/// namespace X { int a; void b(); } -/// using X::a; -/// using X::b; -/// \endcode -/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl()))) -/// matches \code using X::b \endcode -/// but not \code using X::a \endcode -AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, - internal::Matcher<NamedDecl>, InnerMatcher) { - return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder); -} - -/// \brief Matches template instantiations of function, class, or static -/// member variable template instantiations. -/// -/// Given -/// \code -/// template <typename T> class X {}; class A {}; X<A> x; -/// \endcode -/// or -/// \code -/// template <typename T> class X {}; class A {}; template class X<A>; -/// \endcode -/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation()) -/// matches the template instantiation of X<A>. -/// -/// But given -/// \code -/// template <typename T> class X {}; class A {}; -/// template <> class X<A> {}; X<A> x; -/// \endcode -/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation()) -/// does not match, as X<A> is an explicit template specialization. -/// -/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -AST_POLYMORPHIC_MATCHER(isTemplateInstantiation, - AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl, - CXXRecordDecl)) { - return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation || - Node.getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition); -} - -/// \brief Matches declarations that are template instantiations or are inside -/// template instantiations. -/// -/// Given -/// \code -/// template<typename T> void A(T t) { T i; } -/// A(0); -/// A(0U); -/// \endcode -/// functionDecl(isInstantiated()) -/// matches 'A(int) {...};' and 'A(unsigned) {...}'. -AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) { - auto IsInstantiation = decl(anyOf(cxxRecordDecl(isTemplateInstantiation()), - functionDecl(isTemplateInstantiation()))); - return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation))); -} - -/// \brief Matches statements inside of a template instantiation. -/// -/// Given -/// \code -/// int j; -/// template<typename T> void A(T t) { T i; j += 42;} -/// A(0); -/// A(0U); -/// \endcode -/// declStmt(isInTemplateInstantiation()) -/// matches 'int i;' and 'unsigned i'. -/// unless(stmt(isInTemplateInstantiation())) -/// will NOT match j += 42; as it's shared between the template definition and -/// instantiation. -AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) { - return stmt( - hasAncestor(decl(anyOf(cxxRecordDecl(isTemplateInstantiation()), - functionDecl(isTemplateInstantiation()))))); -} - -/// \brief Matches explicit template specializations of function, class, or -/// static member variable template instantiations. -/// -/// Given -/// \code -/// template<typename T> void A(T t) { } -/// template<> void A(int N) { } -/// \endcode -/// functionDecl(isExplicitTemplateSpecialization()) -/// matches the specialization A<int>(). -/// -/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization, - AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl, - CXXRecordDecl)) { - return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); -} - -/// \brief Matches \c TypeLocs for which the given inner -/// QualType-matcher matches. -AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc, - internal::Matcher<QualType>, InnerMatcher, 0) { - return internal::BindableMatcher<TypeLoc>( - 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 -/// \code -/// struct S { void func(); }; -/// \endcode -/// functionDecl(returns(voidType())) -/// matches "void func();" -AST_MATCHER(Type, voidType) { - return Node.isVoidType(); -} - -/// \brief Matches builtin Types. -/// -/// Given -/// \code -/// struct A {}; -/// A a; -/// int b; -/// float c; -/// bool d; -/// \endcode -/// builtinType() -/// matches "int b", "float c" and "bool d" -AST_TYPE_MATCHER(BuiltinType, builtinType); - -/// \brief Matches all kinds of arrays. -/// -/// Given -/// \code -/// int a[] = { 2, 3 }; -/// int b[4]; -/// void f() { int c[a[0]]; } -/// \endcode -/// arrayType() -/// matches "int a[]", "int b[4]" and "int c[a[0]]"; -AST_TYPE_MATCHER(ArrayType, arrayType); - -/// \brief Matches C99 complex types. -/// -/// Given -/// \code -/// _Complex float f; -/// \endcode -/// complexType() -/// matches "_Complex float f" -AST_TYPE_MATCHER(ComplexType, complexType); - -/// \brief Matches arrays and C99 complex types that have a specific element -/// type. -/// -/// Given -/// \code -/// struct A {}; -/// A a[7]; -/// int b[7]; -/// \endcode -/// arrayType(hasElementType(builtinType())) -/// matches "int b[7]" -/// -/// Usable as: Matcher<ArrayType>, Matcher<ComplexType> -AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement, - AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType, - ComplexType)); - -/// \brief Matches C arrays with a specified constant size. -/// -/// Given -/// \code -/// void() { -/// int a[2]; -/// int b[] = { 2, 3 }; -/// int c[b[0]]; -/// } -/// \endcode -/// constantArrayType() -/// matches "int a[2]" -AST_TYPE_MATCHER(ConstantArrayType, constantArrayType); - -/// \brief Matches \c ConstantArrayType nodes that have the specified size. -/// -/// Given -/// \code -/// int a[42]; -/// int b[2 * 21]; -/// int c[41], d[43]; -/// \endcode -/// constantArrayType(hasSize(42)) -/// matches "int a[42]" and "int b[2 * 21]" -AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) { - return Node.getSize() == N; -} - -/// \brief Matches C++ arrays whose size is a value-dependent expression. -/// -/// Given -/// \code -/// template<typename T, int Size> -/// class array { -/// T data[Size]; -/// }; -/// \endcode -/// dependentSizedArrayType -/// matches "T data[Size]" -AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType); - -/// \brief Matches C arrays with unspecified size. -/// -/// Given -/// \code -/// int a[] = { 2, 3 }; -/// int b[42]; -/// void f(int c[]) { int d[a[0]]; }; -/// \endcode -/// incompleteArrayType() -/// matches "int a[]" and "int c[]" -AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); - -/// \brief Matches C arrays with a specified size that is not an -/// integer-constant-expression. -/// -/// Given -/// \code -/// void f() { -/// int a[] = { 2, 3 } -/// int b[42]; -/// int c[a[0]]; -/// } -/// \endcode -/// variableArrayType() -/// matches "int c[a[0]]" -AST_TYPE_MATCHER(VariableArrayType, variableArrayType); - -/// \brief Matches \c VariableArrayType nodes that have a specific size -/// expression. -/// -/// Given -/// \code -/// void f(int b) { -/// int a[b]; -/// } -/// \endcode -/// variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to( -/// varDecl(hasName("b"))))))) -/// matches "int a[b]" -AST_MATCHER_P(VariableArrayType, hasSizeExpr, - internal::Matcher<Expr>, InnerMatcher) { - return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder); -} - -/// \brief Matches atomic types. -/// -/// Given -/// \code -/// _Atomic(int) i; -/// \endcode -/// atomicType() -/// matches "_Atomic(int) i" -AST_TYPE_MATCHER(AtomicType, atomicType); - -/// \brief Matches atomic types with a specific value type. -/// -/// Given -/// \code -/// _Atomic(int) i; -/// _Atomic(float) f; -/// \endcode -/// atomicType(hasValueType(isInteger())) -/// matches "_Atomic(int) i" -/// -/// Usable as: Matcher<AtomicType> -AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue, - AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType)); - -/// \brief Matches types nodes representing C++11 auto types. -/// -/// Given: -/// \code -/// auto n = 4; -/// int v[] = { 2, 3 } -/// for (auto i : v) { } -/// \endcode -/// autoType() -/// matches "auto n" and "auto i" -AST_TYPE_MATCHER(AutoType, autoType); - -/// \brief Matches \c AutoType nodes where the deduced type is a specific type. -/// -/// Note: There is no \c TypeLoc for the deduced type and thus no -/// \c getDeducedLoc() matcher. -/// -/// Given -/// \code -/// auto a = 1; -/// auto b = 2.0; -/// \endcode -/// autoType(hasDeducedType(isInteger())) -/// matches "auto a" -/// -/// Usable as: Matcher<AutoType> -AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, - AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType)); - -/// \brief Matches \c FunctionType nodes. -/// -/// Given -/// \code -/// int (*f)(int); -/// void g(); -/// \endcode -/// functionType() -/// matches "int (*f)(int)" and the type of "g". -AST_TYPE_MATCHER(FunctionType, functionType); - -/// \brief Matches \c ParenType nodes. -/// -/// Given -/// \code -/// int (*ptr_to_array)[4]; -/// int *array_of_ptrs[4]; -/// \endcode -/// -/// \c varDecl(hasType(pointsTo(parenType()))) matches \c ptr_to_array but not -/// \c array_of_ptrs. -AST_TYPE_MATCHER(ParenType, parenType); - -/// \brief Matches \c ParenType nodes where the inner type is a specific type. -/// -/// Given -/// \code -/// int (*ptr_to_array)[4]; -/// int (*ptr_to_func)(int); -/// \endcode -/// -/// \c varDecl(hasType(pointsTo(parenType(innerType(functionType()))))) matches -/// \c ptr_to_func but not \c ptr_to_array. -/// -/// Usable as: Matcher<ParenType> -AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType, - AST_POLYMORPHIC_SUPPORTED_TYPES(ParenType)); - -/// \brief Matches block pointer types, i.e. types syntactically represented as -/// "void (^)(int)". -/// -/// The \c pointee is always required to be a \c FunctionType. -AST_TYPE_MATCHER(BlockPointerType, blockPointerType); - -/// \brief Matches member pointer types. -/// Given -/// \code -/// struct A { int i; } -/// A::* ptr = A::i; -/// \endcode -/// memberPointerType() -/// matches "A::* ptr" -AST_TYPE_MATCHER(MemberPointerType, memberPointerType); - -/// \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", 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 -/// \code -/// int *a; -/// int &b = *a; -/// int &&c = 1; -/// auto &d = b; -/// auto &&e = c; -/// auto &&f = 2; -/// int g = 5; -/// \endcode -/// -/// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f. -AST_TYPE_MATCHER(ReferenceType, referenceType); - -/// \brief Matches lvalue reference types. -/// -/// Given: -/// \code -/// int *a; -/// int &b = *a; -/// int &&c = 1; -/// auto &d = b; -/// auto &&e = c; -/// auto &&f = 2; -/// int g = 5; -/// \endcode -/// -/// \c lValueReferenceType() matches the types of \c b, \c d, and \c e. \c e is -/// matched since the type is deduced as int& by reference collapsing rules. -AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType); - -/// \brief Matches rvalue reference types. -/// -/// Given: -/// \code -/// int *a; -/// int &b = *a; -/// int &&c = 1; -/// auto &d = b; -/// auto &&e = c; -/// auto &&f = 2; -/// int g = 5; -/// \endcode -/// -/// \c rValueReferenceType() matches the types of \c c and \c f. \c e is not -/// matched as it is deduced to int& by reference collapsing rules. -AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType); - -/// \brief Narrows PointerType (and similar) matchers to those where the -/// \c pointee matches a given matcher. -/// -/// Given -/// \code -/// int *a; -/// int const *b; -/// float const *f; -/// \endcode -/// pointerType(pointee(isConstQualified(), isInteger())) -/// matches "int const *b" -/// -/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>, -/// Matcher<PointerType>, Matcher<ReferenceType> -AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee, - AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, - MemberPointerType, - PointerType, - ReferenceType)); - -/// \brief Matches typedef types. -/// -/// Given -/// \code -/// typedef int X; -/// \endcode -/// typedefType() -/// matches "typedef int X" -AST_TYPE_MATCHER(TypedefType, typedefType); - -/// \brief Matches template specialization types. -/// -/// Given -/// \code -/// template <typename T> -/// class C { }; -/// -/// template class C<int>; // A -/// C<char> var; // B -/// \endcode -/// -/// \c templateSpecializationType() matches the type of the explicit -/// instantiation in \c A and the type of the variable declaration in \c B. -AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType); - -/// \brief Matches types nodes representing unary type transformations. -/// -/// Given: -/// \code -/// typedef __underlying_type(T) type; -/// \endcode -/// unaryTransformType() -/// matches "__underlying_type(T)" -AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType); - -/// \brief Matches record types (e.g. structs, classes). -/// -/// Given -/// \code -/// class C {}; -/// struct S {}; -/// -/// C c; -/// S s; -/// \endcode -/// -/// \c recordType() matches the type of the variable declarations of both \c c -/// and \c s. -AST_TYPE_MATCHER(RecordType, recordType); - -/// \brief Matches types specified with an elaborated type keyword or with a -/// qualified name. -/// -/// Given -/// \code -/// namespace N { -/// namespace M { -/// class D {}; -/// } -/// } -/// class C {}; -/// -/// class C c; -/// N::M::D d; -/// \endcode -/// -/// \c elaboratedType() matches the type of the variable declarations of both -/// \c c and \c d. -AST_TYPE_MATCHER(ElaboratedType, elaboratedType); - -/// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier, -/// matches \c InnerMatcher if the qualifier exists. -/// -/// Given -/// \code -/// namespace N { -/// namespace M { -/// class D {}; -/// } -/// } -/// N::M::D d; -/// \endcode -/// -/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))) -/// matches the type of the variable declaration of \c d. -AST_MATCHER_P(ElaboratedType, hasQualifier, - internal::Matcher<NestedNameSpecifier>, InnerMatcher) { - if (const NestedNameSpecifier *Qualifier = Node.getQualifier()) - return InnerMatcher.matches(*Qualifier, Finder, Builder); - - return false; -} - -/// \brief Matches ElaboratedTypes whose named type matches \c InnerMatcher. -/// -/// Given -/// \code -/// namespace N { -/// namespace M { -/// class D {}; -/// } -/// } -/// N::M::D d; -/// \endcode -/// -/// \c elaboratedType(namesType(recordType( -/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable -/// declaration of \c d. -AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>, - InnerMatcher) { - 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. -/// -/// Given -/// \code -/// namespace N { -/// namespace M { -/// class D {}; -/// } -/// } -/// \endcode -/// -/// \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(); - if (!DC) return false; - return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder); -} - -/// \brief Matches nested name specifiers. -/// -/// Given -/// \code -/// namespace ns { -/// struct A { static void f(); }; -/// void A::f() {} -/// void g() { A::f(); } -/// } -/// ns::A a; -/// \endcode -/// nestedNameSpecifier() -/// matches "ns::" and both "A::" -const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; - -/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc. -const internal::VariadicAllOfMatcher< - NestedNameSpecifierLoc> nestedNameSpecifierLoc; - -/// \brief Matches \c NestedNameSpecifierLocs for which the given inner -/// NestedNameSpecifier-matcher matches. -AST_MATCHER_FUNCTION_P_OVERLOAD( - internal::BindableMatcher<NestedNameSpecifierLoc>, loc, - internal::Matcher<NestedNameSpecifier>, InnerMatcher, 1) { - return internal::BindableMatcher<NestedNameSpecifierLoc>( - new internal::LocMatcher<NestedNameSpecifierLoc, NestedNameSpecifier>( - InnerMatcher)); -} - -/// \brief Matches nested name specifiers that specify a type matching the -/// given \c QualType matcher without qualifiers. -/// -/// Given -/// \code -/// struct A { struct B { struct C {}; }; }; -/// A::B::C c; -/// \endcode -/// nestedNameSpecifier(specifiesType( -/// hasDeclaration(cxxRecordDecl(hasName("A"))) -/// )) -/// matches "A::" -AST_MATCHER_P(NestedNameSpecifier, specifiesType, - internal::Matcher<QualType>, InnerMatcher) { - if (!Node.getAsType()) - return false; - return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder); -} - -/// \brief Matches nested name specifier locs that specify a type matching the -/// given \c TypeLoc. -/// -/// Given -/// \code -/// struct A { struct B { struct C {}; }; }; -/// A::B::C c; -/// \endcode -/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type( -/// hasDeclaration(cxxRecordDecl(hasName("A"))))))) -/// matches "A::" -AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, - internal::Matcher<TypeLoc>, InnerMatcher) { - return Node && InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); -} - -/// \brief Matches on the prefix of a \c NestedNameSpecifier. -/// -/// Given -/// \code -/// struct A { struct B { struct C {}; }; }; -/// A::B::C c; -/// \endcode -/// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and -/// matches "A::" -AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, - internal::Matcher<NestedNameSpecifier>, InnerMatcher, - 0) { - const NestedNameSpecifier *NextNode = Node.getPrefix(); - if (!NextNode) - return false; - return InnerMatcher.matches(*NextNode, Finder, Builder); -} - -/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. -/// -/// Given -/// \code -/// struct A { struct B { struct C {}; }; }; -/// A::B::C c; -/// \endcode -/// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A"))))) -/// matches "A::" -AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, - internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher, - 1) { - NestedNameSpecifierLoc NextNode = Node.getPrefix(); - if (!NextNode) - return false; - return InnerMatcher.matches(NextNode, Finder, Builder); -} - -/// \brief Matches nested name specifiers that specify a namespace matching the -/// given namespace matcher. -/// -/// Given -/// \code -/// namespace ns { struct A {}; } -/// ns::A a; -/// \endcode -/// nestedNameSpecifier(specifiesNamespace(hasName("ns"))) -/// matches "ns::" -AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, - internal::Matcher<NamespaceDecl>, InnerMatcher) { - if (!Node.getAsNamespace()) - return false; - return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); -} - -/// \brief Overloads for the \c equalsNode matcher. -/// FIXME: Implement for other node types. -/// @{ - -/// \brief Matches if a node equals another node. -/// -/// \c Decl has pointer identity in the AST. -AST_MATCHER_P_OVERLOAD(Decl, equalsNode, const Decl*, Other, 0) { - return &Node == Other; -} -/// \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; -} - -/// @} - -/// \brief Matches each case or default statement belonging to the given switch -/// statement. This matcher may produce multiple matches. -/// -/// Given -/// \code -/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } } -/// \endcode -/// switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s") -/// matches four times, with "c" binding each of "case 1:", "case 2:", -/// "case 3:" and "case 4:", and "s" respectively binding "switch (1)", -/// "switch (1)", "switch (2)" and "switch (2)". -AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>, - InnerMatcher) { - BoundNodesTreeBuilder Result; - // FIXME: getSwitchCaseList() does not necessarily guarantee a stable - // iteration order. We should use the more general iterating matchers once - // they are capable of expressing this matcher (for example, it should ignore - // case statements belonging to nested switch statements). - bool Matched = false; - for (const SwitchCase *SC = Node.getSwitchCaseList(); SC; - SC = SC->getNextSwitchCase()) { - BoundNodesTreeBuilder CaseBuilder(*Builder); - bool CaseMatched = InnerMatcher.matches(*SC, Finder, &CaseBuilder); - if (CaseMatched) { - Matched = true; - Result.addMatch(CaseBuilder); - } - } - *Builder = std::move(Result); - return Matched; -} - -/// \brief Matches each constructor initializer in a constructor definition. -/// -/// Given -/// \code -/// class A { A() : i(42), j(42) {} int i; int j; }; -/// \endcode -/// 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) { - BoundNodesTreeBuilder Result; - bool Matched = false; - for (const auto *I : Node.inits()) { - BoundNodesTreeBuilder InitBuilder(*Builder); - if (InnerMatcher.matches(*I, Finder, &InitBuilder)) { - Matched = true; - Result.addMatch(InitBuilder); - } - } - *Builder = std::move(Result); - 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. -/// -/// Given -/// \code -/// switch (1) { case 1: case 1+1: case 3 ... 4: ; } -/// \endcode -/// caseStmt(hasCaseConstant(integerLiteral())) -/// matches "case 1:" -AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>, - InnerMatcher) { - if (Node.getRHS()) - return false; - - return InnerMatcher.matches(*Node.getLHS(), Finder, Builder); -} - -/// \brief Matches declaration that has a given attribute. -/// -/// Given -/// \code -/// __attribute__((device)) void f() { ... } -/// \endcode -/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of -/// 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) - return true; - } - return false; -} - -/// \brief Matches CUDA kernel call expression. -/// -/// Example matches, -/// \code -/// kernel<<<i,j>>>(); -/// \endcode -const internal::VariadicDynCastAllOfMatcher< - Stmt, - CUDAKernelCallExpr> cudaKernelCallExpr; - -} // end namespace ast_matchers -} // end namespace clang - -#endif |