steveire created this revision.
steveire added a reviewer: ymandel.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D80654
Files:
clang/include/clang/ASTMatchers/ASTMatchersInternal.h
clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
clang/lib/ASTMatchers/ASTMatchersInternal.cpp
clang/lib/ASTMatchers/Dynamic/Marshallers.h
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
Index: clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
===
--- clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -505,6 +505,25 @@
EXPECT_FALSE(matches("struct X {};", Value));
}
+TEST_F(RegistryTest, Traverse) {
+ EXPECT_TRUE(
+ matches(R"cpp(
+int foo()
+{
+double d = 0;
+return d;
+}
+)cpp",
+ constructMatcher(
+ "returnStmt",
+ constructMatcher(
+ "hasReturnValue",
+ constructMatcher("traverse",
+ StringRef("IgnoreUnlessSpelledInSource"),
+ constructMatcher("declRefExpr"
+ .getTypedMatcher()));
+}
+
TEST_F(RegistryTest, ParenExpr) {
Matcher Value = constructMatcher("parenExpr").getTypedMatcher();
EXPECT_TRUE(
Index: clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
===
--- clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -80,6 +80,44 @@
VariantMatcher::Payload::~Payload() {}
+class VariantMatcher::TraversalPayload : public VariantMatcher::Payload {
+public:
+ TraversalPayload(ast_type_traits::TraversalKind TK,
+ const DynTypedMatcher )
+ : TK(TK), Matcher(Matcher) {}
+
+ llvm::Optional getSingleMatcher() const override {
+return Matcher;
+ }
+
+ std::string getTypeAsString() const override {
+return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
+.str();
+ }
+
+ llvm::Optional
+ getTypedMatcher(const MatcherOps ) const override {
+// llvm::errs() << "TraversalCode" << "\n";
+// std::terminate();
+
+bool Ignore;
+if (Ops.canConstructFrom(Matcher, Ignore)) {
+ return DynTypedMatcher::constructTraversalWrapper(Matcher, TK);
+}
+return llvm::None;
+ }
+
+ bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+ unsigned *Specificity) const override {
+return ArgKind(Matcher.getSupportedKind())
+.isConvertibleTo(Kind, Specificity);
+ }
+
+private:
+ ast_type_traits::TraversalKind TK;
+ const DynTypedMatcher Matcher;
+};
+
class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
public:
SinglePayload(const DynTypedMatcher ) : Matcher(Matcher) {}
@@ -219,6 +257,12 @@
return VariantMatcher(std::make_shared(Matcher));
}
+VariantMatcher
+VariantMatcher::TraversalMatcher(ast_type_traits::TraversalKind TK,
+ const DynTypedMatcher ) {
+ return VariantMatcher(std::make_shared(TK, Matcher));
+}
+
VariantMatcher
VariantMatcher::PolymorphicMatcher(std::vector Matchers) {
return VariantMatcher(
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -101,6 +101,9 @@
// Other:
// equalsNode
+ registerMatcher("traverse",
+ std::make_unique());
+
REGISTER_OVERLOADED_2(callee);
REGISTER_OVERLOADED_2(hasAnyCapture);
REGISTER_OVERLOADED_2(hasPrefix);
Index: clang/lib/ASTMatchers/Dynamic/Marshallers.h
===
--- clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -244,6 +244,31 @@
static llvm::Optional getBestGuess(const VariantValue );
};
+template <> struct ArgTypeTraits {
+private:
+ static Optional
+ getTraversalKind(llvm::StringRef TK) {
+return llvm::StringSwitch>(TK)
+.Case("TK::AsIs", ast_type_traits::TK_AsIs)
+.Case("TK::IgnoreUnlessSpelledInSource",
+ ast_type_traits::TK_IgnoreUnlessSpelledInSource)
+.Case("TK::IgnoreImplicitCastsAndParentheses",
+ ast_type_traits::TK_IgnoreImplicitCastsAndParentheses)
+.Default(llvm::None);
+ }
+
+public:
+ static bool is(const VariantValue ) {
+return Value.isString() && getTraversalKind(Value.getString());
+ }
+
+ static ast_type_traits::TraversalKind get(const VariantValue ) {
+return *getTraversalKind(Value.getString());
+ }
+
+ static ArgKind getKind() { return