summaryrefslogtreecommitdiffstats
path: root/include/clang/ASTMatchers/ASTMatchers.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchers.h')
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h573
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
OpenPOWER on IntegriCloud