ajohnson-uoregon updated this revision to Diff 419248.
ajohnson-uoregon added a comment.
Okay, I put the assert back in and made a thing similar to HasSizeMatcher that
works and all the tests pass.
What do you mean by a release note, in the commit message, in the docs...?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D120949/new/
https://reviews.llvm.org/D120949
Files:
clang/docs/LibASTMatchersReference.html
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/include/clang/ASTMatchers/ASTMatchersInternal.h
clang/lib/ASTMatchers/ASTMatchersInternal.cpp
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -184,9 +184,9 @@
TEST(ASTMatchersTestCUDA, HasAttrCUDA) {
EXPECT_TRUE(matchesWithCuda("__attribute__((device)) void f() {}",
- hasAttr(clang::attr::CUDADevice)));
+ decl(hasAttr(clang::attr::CUDADevice))));
EXPECT_FALSE(notMatchesWithCuda("__attribute__((global)) void f() {}",
- hasAttr(clang::attr::CUDAGlobal)));
+ decl(hasAttr(clang::attr::CUDAGlobal))));
}
TEST_P(ASTMatchersTest, ValueDecl) {
@@ -2509,6 +2509,37 @@
EXPECT_FALSE(Finder.addDynamicMatcher(hasName("x"), nullptr));
}
+TEST(ASTMatchersTest, AttributedStmtBasic) {
+ StringRef Code = "int foo() { [[likely]] return 1; }";
+ EXPECT_TRUE(
+ matchesConditionally(Code, attributedStmt(), true, {"-std=c++20"}));
+}
+
+TEST(ASTMatchersTest, AttributedStmt_hasAttr) {
+ StringRef Code = "int foo() { [[unlikely]] return 1; }";
+ EXPECT_TRUE(matchesConditionally(
+ Code, attributedStmt(hasAttr(attr::Unlikely)), true, {"-std=c++20"}));
+ EXPECT_FALSE(matchesConditionally(
+ Code, attributedStmt(hasAttr(attr::Builtin)), true, {"-std=c++20"}));
+}
+
+TEST(ASTMatchersTest, AttributedStmt_hasSubStmt) {
+ StringRef Code = "int foo() { [[likely]] return 1; }";
+ EXPECT_TRUE(matchesConditionally(
+ Code, attributedStmt(hasSubStmt(returnStmt())), true, {"-std=c++20"}));
+ EXPECT_FALSE(matchesConditionally(Code, attributedStmt(hasSubStmt(ifStmt())),
+ true, {"-std=c++20"}));
+}
+
+TEST(ASTMatchersTest, AttributedStmt_multipleAttrs) {
+ StringRef Code = "int foo();\n int main() {\n [[clang::nomerge]] [[likely]] "
+ "return foo();\n }";
+ EXPECT_TRUE(matchesConditionally(Code, attributedStmt(hasAttr(attr::Likely)),
+ true, {"-std=c++20"}));
+ EXPECT_TRUE(matchesConditionally(Code, attributedStmt(hasAttr(attr::NoMerge)),
+ true, {"-std=c++20"}));
+}
+
TEST(MatchFinderAPI, MatchesDynamic) {
StringRef SourceCode = "struct A { void f() {} };";
auto Matcher = functionDecl(isDefinition()).bind("method");
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -142,6 +142,7 @@
REGISTER_MATCHER(atomicExpr);
REGISTER_MATCHER(atomicType);
REGISTER_MATCHER(attr);
+ REGISTER_MATCHER(attributedStmt);
REGISTER_MATCHER(autoType);
REGISTER_MATCHER(autoreleasePoolStmt)
REGISTER_MATCHER(binaryConditionalOperator);
@@ -355,6 +356,7 @@
REGISTER_MATCHER(hasSpecializedTemplate);
REGISTER_MATCHER(hasStaticStorageDuration);
REGISTER_MATCHER(hasStructuredBlock);
+ REGISTER_MATCHER(hasSubStmt);
REGISTER_MATCHER(hasSyntacticForm);
REGISTER_MATCHER(hasTargetDecl);
REGISTER_MATCHER(hasTemplateArgument);
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -981,6 +981,8 @@
predefinedExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr>
designatedInitExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, AttributedStmt>
+ attributedStmt;
const internal::VariadicOperatorMatcherFunc<
2, std::numeric_limits<unsigned>::max()>
eachOf = {internal::DynTypedMatcher::VO_EachOf};
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -35,6 +35,7 @@
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
@@ -2187,6 +2188,21 @@
return Node.getSubStmt();
}
+template <typename Ty> struct HasAttrMatcher {
+ static bool hasAttr(const Ty &Node, attr::Kind AttrKind) {
+ return llvm::any_of(Node.getAttrs(), [&](const Attr *A) {
+ return A->getKind() == AttrKind;
+ });
+ }
+};
+
+template <>
+inline bool HasAttrMatcher<Decl>::hasAttr(const Decl &Node,
+ attr::Kind AttrKind) {
+ return llvm::any_of(Node.attrs(),
+ [&](const Attr *A) { return A->getKind() == AttrKind; });
+}
+
/// If \p Loc is (transitively) expanded from macro \p MacroName, returns the
/// location (in the chain of expansions) at which \p MacroName was
/// expanded. Since the macro may have been expanded inside a series of
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2699,6 +2699,40 @@
return Node.size() == N;
}
+/// Matches the attribute(s) attached to a Stmt
+///
+/// Given:
+/// \code
+/// constexpr double pow(double x, long long n) noexcept {
+/// if (n > 0) [[likely]]
+/// return x * pow(x, n - 1);
+/// else [[unlikely]]
+/// return 1;
+/// }
+/// \endcode
+/// attributedStmt() matches "[[likely]] return ...;" and
+/// "[[unlikely]] return 1;"
+extern const internal::VariadicDynCastAllOfMatcher<Stmt, AttributedStmt>
+ attributedStmt;
+
+/// Matches the statement an attribute is attached to.
+///
+/// Example:
+/// \code
+/// attributedStmt(hasSubStmt(returnStmt()))
+/// \endcode
+/// would match "return 1;" here:
+/// \code
+/// else [[unlikely]]
+/// return 1;
+/// \endcode
+AST_MATCHER_P(AttributedStmt, hasSubStmt, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ const Stmt *Statement = Node.getSubStmt();
+ return Statement != nullptr &&
+ InnerMatcher.matches(*Statement, Finder, Builder);
+}
+
/// Matches \c QualTypes in the clang AST.
extern const internal::VariadicAllOfMatcher<QualType> qualType;
@@ -7760,12 +7794,10 @@
/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
/// f. If the matcher is used from clang-query, attr::Kind parameter should be
/// passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
-AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
- for (const auto *Attr : Node.attrs()) {
- if (Attr->getKind() == AttrKind)
- return true;
- }
- return false;
+AST_POLYMORPHIC_MATCHER_P(hasAttr,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, AttributedStmt),
+ attr::Kind, AttrKind) {
+ return internal::HasAttrMatcher<NodeType>::hasAttr(Node, AttrKind);
}
/// Matches the return value expression of a return statement
Index: clang/docs/LibASTMatchersReference.html
===================================================================
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -1283,6 +1283,21 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('attributedStmt0')"><a name="attributedStmt0Anchor">attributedStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AttributedStmt.html">AttributedStmt</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="attributedStmt0"><pre>Matches the attribute(s) attached to a Stmt
+
+Given:
+ constexpr double pow(double x, long long n) noexcept {
+ if (n > 0) [[likely]]
+ return x * pow(x, n - 1);
+ else [[unlikely]]
+ return 1;
+ }
+attributedStmt() matches "[[likely]] return ...;" and
+"[[unlikely]] return 1;"
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('autoreleasePoolStmt0')"><a name="autoreleasePoolStmt0Anchor">autoreleasePoolStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCAutoreleasePoolStmt.html">ObjCAutoreleasePoolStmt</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="autoreleasePoolStmt0"><pre>Matches an Objective-C autorelease pool statement.
@@ -2852,6 +2867,17 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AttributedStmt.html">AttributedStmt</a>></td><td class="name" onclick="toggle('hasAttr1')"><a name="hasAttr1Anchor">hasAttr</a></td><td>attr::Kind AttrKind</td></tr>
+<tr><td colspan="4" class="doc" id="hasAttr1"><pre>Matches declaration that has a given attribute.
+
+Given
+ __attribute__((device)) void f() { ... }
+decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+f. If the matcher is used from clang-query, attr::Kind parameter should be
+passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Attr.html">Attr</a>></td><td class="name" onclick="toggle('isImplicit1')"><a name="isImplicit1Anchor">isImplicit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isImplicit1"><pre>Matches an entity that has been implicitly added by the compiler (e.g.
implicit default/copy constructors).
@@ -6214,6 +6240,17 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AttributedStmt.html">AttributedStmt</a>></td><td class="name" onclick="toggle('hasSubStmt0')"><a name="hasSubStmt0Anchor">hasSubStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasSubStmt0"><pre>Matches the statement an attribute is attached to.
+
+Example:
+ attributedStmt(hasSubStmt(returnStmt()))
+would match "return 1;" here:
+ else [[unlikely]]
+ return 1;
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1AutoType.html">AutoType</a>></td><td class="name" onclick="toggle('hasDeducedType0')"><a name="hasDeducedType0Anchor">hasDeducedType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td></tr>
<tr><td colspan="4" class="doc" id="hasDeducedType0"><pre>Matches AutoType nodes where the deduced type is a specific type.
@@ -9799,5 +9836,3 @@
</div>
</body>
</html>
-
-
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits