From: Manuel Klimek Date: Thu, 20 Jun 2013 13:08:29 +0000 (+0000) Subject: Implements declaratorDecl, parmVarDecl and hassTypeLoc matchers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1a68afd5bbecd05a3bb22854954aa4e5448c4470;p=clang Implements declaratorDecl, parmVarDecl and hassTypeLoc matchers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184419 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index c80a749df2..8e31d583cb 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -134,6 +134,17 @@ Examples matches X, C, and the friend declaration inside C; +Matcher<Decl>declaratorDeclMatcher<DeclaratorDecl>... +
Matches declarator declarations (field, variable, function
+and non-type template parameter declarations).
+
+Given
+  class X { int y; };
+declaratorDecl()
+  matches int y.
+
+ + Matcher<Decl>destructorDeclMatcher<CXXDestructorDecl>...
Matches explicit C++ destructor declarations.
 
@@ -223,6 +234,16 @@ namespaceDecl()
 
+Matcher<Decl>parmVarDeclMatcher<ParmVarDecl>... +
Matches parameter variable declarations.
+
+Given
+  void f(int x);
+parmVarDecl()
+  matches int x.
+
+ + Matcher<Decl>recordDeclMatcher<CXXRecordDecl>...
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.
 
@@ -2719,6 +2745,17 @@ declStmt(hasSingleDecl(anything())) +Matcher<DeclaratorDecl>hasTypeLocMatcher<TypeLoc> Inner +
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
+
+ + Matcher<Decl>hasDeclContextMatcher<Decl> InnerMatcher
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 dede68961f..50da7d6a9c 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
+    declaratorDecl;
+
+/// \brief Matches parameter variable declarations.
+///
+/// Given
+/// \code
+///   void f(int x);
+/// \endcode
+/// parmVarDecl()
+///   matches \c int x.
+const internal::VariadicDynCastAllOfMatcher parmVarDecl;
+
 /// \brief Matches C++ access specifier declarations.
 ///
 /// Given
@@ -1794,6 +1816,22 @@ hasType(const internal::Matcher &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, 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 9f0d7afb95..a7ccb56cd6 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, 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 struct B {};"