diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index c80a749df28430651d497a74044bbf49bdd1a9cb..8e31d583cb78215cc8731b73f38f2868411ba9be 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -134,6 +134,17 @@ Examples matches X, C, and the friend declaration inside C; </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('declaratorDecl0')"><a name="declaratorDecl0Anchor">declaratorDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="declaratorDecl0"><pre>Matches declarator declarations (field, variable, function +and non-type template parameter declarations). + +Given + class X { int y; }; +declaratorDecl() + matches int y. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('destructorDecl0')"><a name="destructorDecl0Anchor">destructorDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXDestructorDecl.html">CXXDestructorDecl</a>>...</td></tr> <tr><td colspan="4" class="doc" id="destructorDecl0"><pre>Matches explicit C++ destructor declarations. @@ -223,6 +234,16 @@ namespaceDecl() </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('parmVarDecl0')"><a name="parmVarDecl0Anchor">parmVarDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="parmVarDecl0"><pre>Matches parameter variable declarations. + +Given + void f(int x); +parmVarDecl() + matches int x. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('recordDecl0')"><a name="recordDecl0Anchor">recordDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>>...</td></tr> <tr><td colspan="4" class="doc" id="recordDecl0"><pre>Matches C++ class declarations. @@ -2509,6 +2530,11 @@ 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 ignoreImplicit() +has been implemented. </pre></td></tr> @@ -2719,6 +2745,17 @@ declStmt(hasSingleDecl(anything())) </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1DeclaratorDecl.html">DeclaratorDecl</a>></td><td class="name" onclick="toggle('hasTypeLoc0')"><a name="hasTypeLoc0Anchor">hasTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> Inner</td></tr> +<tr><td colspan="4" class="doc" id="hasTypeLoc0"><pre>Matches if the type location of the declarator decl's type matches +the inner matcher. + +Given + int x; +declaratorDecl(hasTypeLoc(loc(asString("int")))) + matches int x +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('hasDeclContext0')"><a name="hasDeclContext0Anchor">hasDeclContext</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasDeclContext0"><pre>Matches declarations whose declaration context, interpreted as a Decl, matches InnerMatcher. diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index dede68961fbcbe1a314273d3e34ab57b9bbecb6c..50da7d6a9c1c9c73f483208de7cf48ea8991e602 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -204,6 +204,28 @@ 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 @@ -1794,6 +1816,22 @@ hasType(const internal::Matcher<Decl> &InnerMatcher) { return hasType(qualType(hasDeclaration(InnerMatcher))); } +/// \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 diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 9f0d7afb95770a0ced1a02f3e53d61f17d31d0ec..a7ccb56cd64fa691405e6f65314dfe3c61cda050 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -912,6 +912,15 @@ TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) { notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX)))); } +TEST(HasTypeLoc, MatchesDeclaratorDecls) { + EXPECT_TRUE(matches("int x;", + varDecl(hasName("x"), hasTypeLoc(loc(asString("int")))))); + + // Make sure we don't crash on implicit constructors. + EXPECT_TRUE(notMatches("class X {}; X x;", + declaratorDecl(hasTypeLoc(loc(asString("int")))))); +} + TEST(Matcher, Call) { // FIXME: Do we want to overload Call() to directly take // Matcher<Decl>, too? @@ -1452,6 +1461,16 @@ TEST(Matcher, MatchesClassTemplateSpecialization) { classTemplateSpecializationDecl())); } +TEST(DeclaratorDecl, MatchesDeclaratorDecls) { + EXPECT_TRUE(matches("int x;", declaratorDecl())); + EXPECT_TRUE(notMatches("class A {};", declaratorDecl())); +} + +TEST(ParmVarDecl, MatchesParmVars) { + EXPECT_TRUE(matches("void f(int x);", parmVarDecl())); + EXPECT_TRUE(notMatches("void f();", parmVarDecl())); +} + TEST(Matcher, MatchesTypeTemplateArgument) { EXPECT_TRUE(matches( "template<typename T> struct B {};"