]> granicus.if.org Git - clang/commitdiff
Add hasAttr matcher for declarations.
authorManuel Klimek <klimek@google.com>
Mon, 25 Aug 2014 11:23:50 +0000 (11:23 +0000)
committerManuel Klimek <klimek@google.com>
Mon, 25 Aug 2014 11:23:50 +0000 (11:23 +0000)
Delete special-case CUDA attribute matchers.

Patch by Jacques Pienaar.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216379 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LibASTMatchersReference.html
include/clang/ASTMatchers/ASTMatchers.h
lib/ASTMatchers/Dynamic/Marshallers.h
lib/ASTMatchers/Dynamic/Registry.cpp
unittests/ASTMatchers/ASTMatchersTest.cpp
unittests/ASTMatchers/Dynamic/RegistryTest.cpp

index 03910f0f66547bbf992a472488b5869fc63aa4cc..1a494e6aea4309f95d5008c9b2a0a6a94fe904e4 100644 (file)
@@ -1612,30 +1612,13 @@ and reference to that variable declaration within a compound statement.
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasCudaDeviceAttr0')"><a name="hasCudaDeviceAttr0Anchor">hasCudaDeviceAttr</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="hasCudaDeviceAttr0"><pre>Matches declaration that has CUDA device attribute.
+<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasAttr0')"><a name="hasAttr0Anchor">hasAttr</a></td><td>attr::Kind AttrKind</td></tr>
+<tr><td colspan="4" class="doc" id="hasAttr0"><pre>Matches declaration that has a given attribute.
 
 Given
   __attribute__((device)) void f() { ... }
-matches the function declaration of f.
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasCudaGlobalAttr0')"><a name="hasCudaGlobalAttr0Anchor">hasCudaGlobalAttr</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="hasCudaGlobalAttr0"><pre>Matches declaration that has CUDA global attribute.
-
-Given
-  __attribute__((global)) void f() { ... }
-matches the function declaration of f.
-</pre></td></tr>
-
-
-<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('hasCudaHostAttr0')"><a name="hasCudaHostAttr0Anchor">hasCudaHostAttr</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="hasCudaHostAttr0"><pre>Matches declaration that has CUDA host attribute.
-
-Given
-  __attribute__((host)) void f() { ... }
-matches the function declaration of f.
+decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+f.
 </pre></td></tr>
 
 
index 1f3e6501603219b545eea486f51cc4d8aabb6ab1..7063606b59c1f0210d50b54d03ca92723d4022e7 100644 (file)
@@ -3658,47 +3658,30 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
   return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
 }
 
-/// \brief Matches CUDA kernel call expression.
-///
-/// Example matches,
-/// \code
-///   kernel<<<i,j>>>();
-/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
-    CUDAKernelCallExpr;
-
-/// \brief Matches declaration that has CUDA device attribute.
+/// \brief Matches declaration that has a given attribute.
 ///
 /// Given
 /// \code
 ///   __attribute__((device)) void f() { ... }
 /// \endcode
-/// matches the function declaration of f.
-AST_MATCHER(Decl, hasCudaDeviceAttr) {
-  return Node.hasAttr<clang::CUDADeviceAttr>();
-}
-
-/// \brief Matches declaration that has CUDA host attribute.
-///
-/// Given
-/// \code
-///   __attribute__((host)) void f() { ... }
-/// \endcode
-/// matches the function declaration of f.
-AST_MATCHER(Decl, hasCudaHostAttr) {
-  return Node.hasAttr<clang::CUDAHostAttr>();
+/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+/// f.
+AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
+  for (const auto *Attr : Node.attrs()) {
+    if (Attr->getKind() == AttrKind)
+      return true;
+  }
+  return false;
 }
 
-/// \brief  Matches declaration that has CUDA global attribute.
+/// \brief Matches CUDA kernel call expression.
 ///
-/// Given
+/// Example matches,
 /// \code
-///   __attribute__((global)) void f() { ... }
+///   kernel<<<i,j>>>();
 /// \endcode
-/// matches the function declaration of f.
-AST_MATCHER(Decl, hasCudaGlobalAttr) {
-  return Node.hasAttr<clang::CUDAGlobalAttr>();
-}
+const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
+    CUDAKernelCallExpr;
 
 } // end namespace ast_matchers
 } // end namespace clang
index 96438005ce583270930edca7fb8e77506c6572d1..0bae3ada5a07f36ebfbe7aa4fbbefd41ed476938 100644 (file)
@@ -76,6 +76,27 @@ template <> struct ArgTypeTraits<unsigned> {
   }
 };
 
+template <> struct ArgTypeTraits<attr::Kind> {
+private:
+  static attr::Kind getAttrKind(llvm::StringRef AttrKind) {
+    return llvm::StringSwitch<attr::Kind>(AttrKind)
+#define ATTR(X) .Case("attr::" #X, attr:: X)
+#include "clang/Basic/AttrList.inc"
+        .Default(attr::Kind(-1));
+  }
+public:
+  static bool is(const VariantValue &Value) {
+    return Value.isString() &&
+        getAttrKind(Value.getString()) != attr::Kind(-1);
+  }
+  static attr::Kind get(const VariantValue &Value) {
+    return getAttrKind(Value.getString());
+  }
+  static ArgKind getKind() {
+    return ArgKind(ArgKind::AK_String);
+  }
+};
+
 /// \brief Matcher descriptor interface.
 ///
 /// Provides a \c create() method that constructs the matcher from the provided
index ed95073397bcc46838b001ce9d2faa6e6c01c511..8d580214279d0e8ede190d4511b73b3825e62daf 100644 (file)
@@ -176,15 +176,13 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(hasAnyUsingShadowDecl);
   REGISTER_MATCHER(hasArgument);
   REGISTER_MATCHER(hasArgumentOfType);
+  REGISTER_MATCHER(hasAttr);
   REGISTER_MATCHER(hasBase);
   REGISTER_MATCHER(hasBody);
   REGISTER_MATCHER(hasCanonicalType);
   REGISTER_MATCHER(hasCaseConstant);
   REGISTER_MATCHER(hasCondition);
   REGISTER_MATCHER(hasConditionVariableStatement);
-  REGISTER_MATCHER(hasCudaDeviceAttr);
-  REGISTER_MATCHER(hasCudaGlobalAttr);
-  REGISTER_MATCHER(hasCudaHostAttr);
   REGISTER_MATCHER(hasDeclContext);
   REGISTER_MATCHER(hasDeclaration);
   REGISTER_MATCHER(hasDeducedType);
index 7a639aac81caa3ef59454d90b9547facf1e54cfd..9263736fef8e5b92d3749575fb50eac1d064eacf 100644 (file)
@@ -649,22 +649,23 @@ TEST(DeclarationMatcher, HasDescendantMemoization) {
   EXPECT_TRUE(matches("void f() { int i; }", CannotMemoize));
 }
 
+TEST(DeclarationMatcher, HasAttr) {
+  EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};",
+                      decl(hasAttr(clang::attr::WarnUnused))));
+  EXPECT_FALSE(matches("struct X {};",
+                       decl(hasAttr(clang::attr::WarnUnused))));
+}
+
 TEST(DeclarationMatcher, MatchCudaDecl) {
   EXPECT_TRUE(matchesWithCuda("__global__ void f() { }"
                               "void g() { f<<<1, 2>>>(); }",
                               CUDAKernelCallExpr()));
   EXPECT_TRUE(matchesWithCuda("__attribute__((device)) void f() {}",
-                              hasCudaDeviceAttr()));
-  EXPECT_TRUE(matchesWithCuda("__attribute__((host)) void f() {}",
-                              hasCudaHostAttr()));
-  EXPECT_TRUE(matchesWithCuda("__attribute__((global)) void f() {}",
-                              hasCudaGlobalAttr()));
-  EXPECT_FALSE(matchesWithCuda("void f() {}",
-                               hasCudaGlobalAttr()));
+                              hasAttr(clang::attr::CUDADevice)));
   EXPECT_TRUE(notMatchesWithCuda("void f() {}",
-                                 hasCudaGlobalAttr()));
+                                 CUDAKernelCallExpr()));
   EXPECT_FALSE(notMatchesWithCuda("__attribute__((global)) void f() {}",
-                                  hasCudaGlobalAttr()));
+                                  hasAttr(clang::attr::CUDAGlobal)));
 }
 
 // Implements a run method that returns whether BoundNodes contains a
index 5552790bcacbc69ba9f6739285d2495e6efd147d..f8a9430f169dc462232140ef1f91e1e970dcb14c 100644 (file)
@@ -472,6 +472,14 @@ TEST_F(RegistryTest, Completion) {
                             "Matcher<NamedDecl> hasName(string)"));
 }
 
+TEST_F(RegistryTest, HasArgs) {
+  Matcher<Decl> Value = constructMatcher(
+      "decl", constructMatcher("hasAttr", std::string("attr::WarnUnused")))
+      .getTypedMatcher<Decl>();
+  EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value));
+  EXPECT_FALSE(matches("struct X {};", Value));
+}
+
 } // end anonymous namespace
 } // end namespace dynamic
 } // end namespace ast_matchers