From ccbd7aeb11adc607a43f7d95deee4c1b9c9afc94 Mon Sep 17 00:00:00 2001 From: Manuel Klimek <klimek@google.com> Date: Mon, 25 Aug 2014 11:23:50 +0000 Subject: [PATCH] Add hasAttr matcher for declarations. 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 | 25 ++--------- include/clang/ASTMatchers/ASTMatchers.h | 45 ++++++------------- lib/ASTMatchers/Dynamic/Marshallers.h | 21 +++++++++ lib/ASTMatchers/Dynamic/Registry.cpp | 4 +- unittests/ASTMatchers/ASTMatchersTest.cpp | 19 ++++---- .../ASTMatchers/Dynamic/RegistryTest.cpp | 8 ++++ 6 files changed, 58 insertions(+), 64 deletions(-) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 03910f0f665..1a494e6aea4 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1612,30 +1612,13 @@ and reference to that variable declaration within a compound statement. </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('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<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></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<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></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<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></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> diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 1f3e6501603..7063606b59c 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -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 diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h index 96438005ce5..0bae3ada5a0 100644 --- a/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/lib/ASTMatchers/Dynamic/Marshallers.h @@ -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 diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index ed95073397b..8d580214279 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -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); diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 7a639aac81c..9263736fef8 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -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 diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index 5552790bcac..f8a9430f169 100644 --- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -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 -- GitLab