diff options
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchers.h')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 573 |
1 files changed, 497 insertions, 76 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index a70dd5c..f10addc 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -142,7 +142,7 @@ inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> anything() /// friend X; /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, Decl> decl; +const internal::VariadicAllOfMatcher<Decl> decl; /// \brief Matches a declaration of anything that could have a name. /// @@ -192,6 +192,69 @@ const internal::VariadicDynCastAllOfMatcher< Decl, ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; +/// \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 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 classTemplateSpecializations that have at least one /// TemplateArgument matching the given InnerMatcher. /// @@ -453,7 +516,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// stmt() /// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> stmt; +const internal::VariadicAllOfMatcher<Stmt> stmt; /// \brief Matches declaration statements. /// @@ -922,6 +985,16 @@ 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, @@ -1090,10 +1163,36 @@ const internal::VariadicDynCastAllOfMatcher< const internal::VariadicAllOfMatcher<QualType> qualType; /// \brief Matches \c Types in the clang AST. -const internal::VariadicDynCastAllOfMatcher<Type, Type> type; +const internal::VariadicAllOfMatcher<Type> type; /// \brief Matches \c TypeLocs in the clang AST. -const internal::VariadicDynCastAllOfMatcher<TypeLoc, TypeLoc> typeLoc; +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 +/// recordDecl(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 +template <typename M1, typename M2> +internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, M2> +eachOf(const M1 &P1, const M2 &P2) { + return internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, + M2>(P1, P2); +} /// \brief Various overloads for the anyOf matcher. /// @{ @@ -1139,18 +1238,40 @@ anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { /// \brief Matches if all given matchers match. /// /// Usable as: Any Matcher -template<typename M1, typename M2> +template <typename M1, typename M2> internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2> allOf(const M1 &P1, const M2 &P2) { - return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, - M1, M2>(P1, P2); + return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2>( + P1, P2); } -template<typename M1, typename M2, typename M3> -internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, +template <typename M1, typename M2, typename M3> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M2, M3> > allOf(const M1 &P1, const M2 &P2, const M3 &P3) { return allOf(P1, allOf(P2, P3)); } +template <typename M1, typename M2, typename M3, typename M4> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M2, internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M3, M4> > > +allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) { + return allOf(P1, allOf(P2, P3, P4)); +} +template <typename M1, typename M2, typename M3, typename M4, typename M5> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M2, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M3, + internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M4, + M5> > > > +allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { + return allOf(P1, allOf(P2, P3, P4, P5)); +} /// @} @@ -1198,7 +1319,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { /// alignof. inline internal::Matcher<Stmt> alignOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { - return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( + return stmt(unaryExprOrTypeTraitExpr(allOf( ofKind(UETT_AlignOf), InnerMatcher))); } @@ -1206,8 +1327,8 @@ inline internal::Matcher<Stmt> alignOfExpr( /// sizeof. inline internal::Matcher<Stmt> sizeOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { - return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_SizeOf), InnerMatcher))); + return stmt(unaryExprOrTypeTraitExpr( + allOf(ofKind(UETT_SizeOf), InnerMatcher))); } /// \brief Matches NamedDecl nodes that have the specified name. @@ -1228,8 +1349,8 @@ inline internal::Matcher<Stmt> sizeOfExpr( AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { assert(!Name.empty()); const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); - const llvm::StringRef FullName = FullNameString; - const llvm::StringRef Pattern = Name; + const StringRef FullName = FullNameString; + const StringRef Pattern = Name; if (Pattern.startswith("::")) { return FullName == Pattern; } else { @@ -1237,8 +1358,8 @@ AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { } } -/// \brief Matches NamedDecl nodes whose full names partially match the -/// given RegExp. +/// \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 @@ -1263,18 +1384,26 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// \brief Matches overloaded operator names. /// /// Matches overloaded operator names specified in strings without the -/// "operator" prefix, such as "<<", for OverloadedOperatorCall's. +/// "operator" prefix: e.g. "<<". /// -/// Example matches a << b -/// (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) +/// Given: /// \code -/// a << b; -/// c && d; // assuming both operator<< -/// // and operator&& are overloaded somewhere. +/// class A { int operator*(); }; +/// const A &operator<<(const A &a, const A &b); +/// A a; +/// a << a; // <-- This matches /// \endcode -AST_MATCHER_P(CXXOperatorCallExpr, - hasOverloadedOperatorName, std::string, Name) { - return getOperatorSpelling(Node.getOperator()) == Name; +/// +/// \c operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified +/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches +/// the declaration of \c A. +/// +/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl> +inline internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef> +hasOverloadedOperatorName(const StringRef Name) { + return internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef>(Name); } /// \brief Matches C++ classes that are directly or indirectly derived from @@ -1324,6 +1453,27 @@ inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom( return isSameOrDerivedFrom(hasName(BaseName)); } +/// \brief Matches the first method of a class or struct that satisfies \c +/// InnerMatcher. +/// +/// Given: +/// \code +/// class A { void func(); }; +/// class B { void member(); }; +/// \code +/// +/// \c recordDecl(hasMethod(hasName("func"))) matches the declaration of \c A +/// but not \c B. +AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>, + InnerMatcher) { + for (CXXRecordDecl::method_iterator I = Node.method_begin(), + E = Node.method_end(); + I != E; ++I) + if (InnerMatcher.matches(**I, Finder, Builder)) + return true; + return false; +} + /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// @@ -1424,6 +1574,29 @@ forEachDescendant( DescendantT>(DescendantMatcher); } +/// \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 +/// recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m"))) +/// \endcode +/// will generate results for \c A, \c B and \c C. +/// +/// Usable as: Any Matcher +template <typename T> +internal::PolymorphicMatcherWithParam2< + internal::EachOfMatcher, internal::Matcher<T>, + internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, 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. /// @@ -1480,8 +1653,13 @@ unless(const M &InnerMatcher) { /// \brief Matches a type if the declaration of the type matches the given /// matcher. /// +/// In addition to being usable as Matcher<TypedefType>, also usable as +/// Matcher<T> for any T supporting the getDecl() member function. e.g. various +/// subtypes of clang::Type. +/// /// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>, -/// Matcher<MemberExpr> +/// Matcher<MemberExpr>, Matcher<TypedefType>, +/// Matcher<TemplateSpecializationType> inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher<Decl> > hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { @@ -1501,9 +1679,8 @@ inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, /// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, InnerMatcher) { - const Expr *ExprNode = const_cast<CXXMemberCallExpr&>(Node) - .getImplicitObjectArgument() - ->IgnoreParenImpCasts(); + const Expr *ExprNode = Node.getImplicitObjectArgument() + ->IgnoreParenImpCasts(); return (ExprNode != NULL && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1541,7 +1718,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, /// \endcode inline internal::Matcher<CallExpr> callee( const internal::Matcher<Decl> &InnerMatcher) { - return internal::Matcher<CallExpr>(hasDeclaration(InnerMatcher)); + return callExpr(hasDeclaration(InnerMatcher)); } /// \brief Matches if the expression's or declaration's type matches a type @@ -1579,11 +1756,10 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>, /// /// Usable as: Matcher<Expr>, Matcher<ValueDecl> inline internal::PolymorphicMatcherWithParam1< - internal::matcher_hasTypeMatcher, + internal::matcher_hasType0Matcher, internal::Matcher<QualType> > hasType(const internal::Matcher<Decl> &InnerMatcher) { - return hasType(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return hasType(qualType(hasDeclaration(InnerMatcher))); } /// \brief Matches if the matched type is represented by the given string. @@ -1618,8 +1794,7 @@ AST_MATCHER_P( /// \brief Overloaded to match the pointee type's declaration. inline internal::Matcher<QualType> pointsTo( const internal::Matcher<Decl> &InnerMatcher) { - return pointsTo(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return pointsTo(qualType(hasDeclaration(InnerMatcher))); } /// \brief Matches if the matched type is a reference type and the referenced @@ -1640,17 +1815,32 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, 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; +/// \code +/// +/// \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) { + return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder); +} + /// \brief Overloaded to match the referenced type's declaration. inline internal::Matcher<QualType> references( const internal::Matcher<Decl> &InnerMatcher) { - return references(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return references(qualType(hasDeclaration(InnerMatcher))); } AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, internal::Matcher<Expr>, InnerMatcher) { - const Expr *ExprNode = - const_cast<CXXMemberCallExpr&>(Node).getImplicitObjectArgument(); + const Expr *ExprNode = Node.getImplicitObjectArgument(); return (ExprNode != NULL && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1705,8 +1895,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, AST_MATCHER_P(DeclRefExpr, throughUsingDecl, internal::Matcher<UsingShadowDecl>, InnerMatcher) { const NamedDecl *FoundDecl = Node.getFoundDecl(); - if (const UsingShadowDecl *UsingDecl = - llvm::dyn_cast<UsingShadowDecl>(FoundDecl)) + if (const UsingShadowDecl *UsingDecl = dyn_cast<UsingShadowDecl>(FoundDecl)) return InnerMatcher.matches(*UsingDecl, Finder, Builder); return false; } @@ -1974,6 +2163,19 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, return false; } +/// \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: @@ -2279,10 +2481,13 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression, /// \endcode /// /// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> -inline internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher> -isDefinition() { - return internal::PolymorphicMatcherWithParam0< - internal::IsDefinitionMatcher>(); +AST_POLYMORPHIC_MATCHER(isDefinition) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<TagDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<FunctionDecl, NodeType>::value), + is_definition_requires_isThisDeclarationADefinition_method); + return Node.isThisDeclarationADefinition(); } /// \brief Matches the class declaration that the given method declaration @@ -2324,8 +2529,8 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, /// \endcode /// memberExpr(isArrow()) /// matches this->x, x, y.x, a, this->b -inline internal::Matcher<MemberExpr> isArrow() { - return makeMatcher(new internal::IsArrowMatcher()); +AST_MATCHER(MemberExpr, isArrow) { + return Node.isArrow(); } /// \brief Matches QualType nodes that are of integer type. @@ -2357,8 +2562,25 @@ AST_MATCHER(QualType, isInteger) { /// 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 *". -inline internal::Matcher<QualType> isConstQualified() { - return makeMatcher(new internal::IsConstQualifiedMatcher()); +AST_MATCHER(QualType, isConstQualified) { + return Node.isConstQualified(); +} + +/// \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 @@ -2454,11 +2676,14 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, /// does not match, as X<A> is an explicit template specialization. /// /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -inline internal::PolymorphicMatcherWithParam0< - internal::IsTemplateInstantiationMatcher> -isTemplateInstantiation() { - return internal::PolymorphicMatcherWithParam0< - internal::IsTemplateInstantiationMatcher>(); +AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<CXXRecordDecl, NodeType>::value), + requires_getTemplateSpecializationKind_method); + return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation || + Node.getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition); } /// \brief Matches explicit template specializations of function, class, or @@ -2473,11 +2698,12 @@ isTemplateInstantiation() { /// matches the specialization A<int>(). /// /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -inline internal::PolymorphicMatcherWithParam0< - internal::IsExplicitTemplateSpecializationMatcher> -isExplicitTemplateSpecialization() { - return internal::PolymorphicMatcherWithParam0< - internal::IsExplicitTemplateSpecializationMatcher>(); +AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<CXXRecordDecl, NodeType>::value), + requires_getTemplateSpecializationKind_method); + return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); } /// \brief Matches \c TypeLocs for which the given inner @@ -2685,6 +2911,32 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); /// 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); + /// \brief Matches block pointer types, i.e. types syntactically represented as /// "void (^)(int)". /// @@ -2713,18 +2965,56 @@ AST_TYPE_MATCHER(MemberPointerType, memberPointerType); /// matches "int *a" AST_TYPE_MATCHER(PointerType, pointerType); -/// \brief Matches reference types. +/// \brief Matches both lvalue and rvalue reference types. /// /// Given /// \code /// int *a; /// int &b = *a; -/// int c = 5; +/// int &&c = 1; +/// auto &d = b; +/// auto &&e = c; +/// auto &&f = 2; +/// int g = 5; /// \endcode -/// pointerType() -/// matches "int &b" +/// +/// \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. /// @@ -2751,11 +3041,116 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); /// matches "typedef int X" AST_TYPE_MATCHER(TypedefType, typedefType); -/// \brief Matches \c TypedefTypes referring to a specific -/// \c TypedefNameDecl. -AST_MATCHER_P(TypedefType, hasDecl, - internal::Matcher<TypedefNameDecl>, InnerMatcher) { - return InnerMatcher.matches(*Node.getDecl(), Finder, Builder); +/// \brief Matches template specialization types. +/// +/// Given +/// \code +/// template <typename T> +/// class C { }; +/// +/// template class C<int>; // A +/// C<char> var; // B +/// \code +/// +/// \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 record types (e.g. structs, classes). +/// +/// Given +/// \code +/// class C {}; +/// struct S {}; +/// +/// C c; +/// S s; +/// \code +/// +/// \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; +/// \code +/// +/// \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; +/// \code +/// +/// \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; +/// \code +/// +/// \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 declarations whose declaration context, interpreted as a +/// Decl, matches \c InnerMatcher. +/// +/// Given +/// \code +/// namespace N { +/// namespace M { +/// class D {}; +/// } +/// } +/// \code +/// +/// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the +/// declaration of \c class \c D. +AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) { + return InnerMatcher.matches(*Decl::castFromDeclContext(Node.getDeclContext()), + Finder, Builder); } /// \brief Matches nested name specifiers. @@ -2828,10 +3223,13 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, /// \endcode /// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and /// matches "A::" -inline internal::Matcher<NestedNameSpecifier> hasPrefix( - const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { - return internal::makeMatcher( - new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher)); +AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, + internal::Matcher<NestedNameSpecifier>, InnerMatcher, + 0) { + NestedNameSpecifier *NextNode = Node.getPrefix(); + if (NextNode == NULL) + return false; + return InnerMatcher.matches(*NextNode, Finder, Builder); } /// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. @@ -2843,10 +3241,13 @@ inline internal::Matcher<NestedNameSpecifier> hasPrefix( /// \endcode /// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A"))))) /// matches "A::" -inline internal::Matcher<NestedNameSpecifierLoc> hasPrefix( - const internal::Matcher<NestedNameSpecifierLoc> &InnerMatcher) { - return internal::makeMatcher( - new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher)); +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 @@ -2866,6 +3267,26 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, 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, 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, Stmt*, Other, 1) { + return &Node == Other; +} + +/// @} + } // end namespace ast_matchers } // end namespace clang |