njames93 updated this revision to Diff 246203. njames93 added a comment. - Improved docs
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75040/new/ https://reviews.llvm.org/D75040 Files: clang/docs/LibASTMatchersReference.html clang/docs/tools/dump_ast_matchers.py 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/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1123,6 +1123,19 @@ EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr)); } +TEST(MatchBinaryOperator, HasAnyOperatorName) { + StatementMatcher Matcher = + binaryOperator(hasAnyOperatorName("+", "-", "*", "/")); + + EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher)); + EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher)); + // Ensure '+= isn't mistaken. + EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher)); +} + TEST(MatchBinaryOperator, HasLHSAndHasRHS) { StatementMatcher OperatorTrueFalse = binaryOperator(hasLHS(cxxBoolLiteral(equals(true))), @@ -1255,6 +1268,18 @@ EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot)); } +TEST(MatchUnaryOperator, HasAnyOperatorName) { + StatementMatcher Matcher = unaryOperator(hasAnyOperatorName("-", "*", "++")); + + EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher)); + EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher)); + EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher)); + EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher)); + EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher)); + EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher)); + EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher)); +} + TEST(MatchUnaryOperator, HasUnaryOperand) { StatementMatcher OperatorOnFalse = unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false)))); Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -243,6 +243,7 @@ REGISTER_MATCHER(hasAnyConstructorInitializer); REGISTER_MATCHER(hasAnyDeclaration); REGISTER_MATCHER(hasAnyName); + REGISTER_MATCHER(hasAnyOperatorName); REGISTER_MATCHER(hasAnyParameter); REGISTER_MATCHER(hasAnyPlacementArg); REGISTER_MATCHER(hasAnySelector); Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -380,6 +380,10 @@ return hasAnySelectorMatcher(vectorFromRefs(NameRefs)); } +HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs) { + return HasOpNameMatcher(vectorFromRefs(NameRefs)); +} + HasNameMatcher::HasNameMatcher(std::vector<std::string> N) : UseUnqualifiedMatch(std::all_of( N.begin(), N.end(), @@ -854,6 +858,10 @@ const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef, internal::hasAnyNameFunc> hasAnyName = {}; + +const internal::VariadicFunction<internal::HasOpNameMatcher, StringRef, + internal::hasAnyOperatorNameFunc> + hasAnyOperatorName = {}; const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, StringRef, internal::hasAnySelectorFunc> hasAnySelector = {}; Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1858,6 +1858,47 @@ llvm::Optional<SourceLocation> getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc, const ASTContext &Context); + +/// Matches overloaded operators with a specific name. +/// +/// The type argument ArgT is not used by this matcher but is used by +/// PolymorphicMatcherWithParam1 and should be std::vector<std::string>>. +template <typename T, typename ArgT = std::vector<std::string>> +class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> { + static_assert(std::is_same<T, BinaryOperator>::value || + std::is_same<T, UnaryOperator>::value, + "Matcher only supports `BinaryOperator` and `UnaryOperator`"); + static_assert(std::is_same<ArgT, std::vector<std::string>>::value, + "Matcher ArgT must be std::vector<std::string>"); + +public: + explicit HasAnyOperatorNameMatcher(std::vector<std::string> Names) + : SingleNodeMatcherInterface<T>(), Names(std::move(Names)) {} + + bool matchesNode(const T &Node) const override { + StringRef OpName = getOpName(Node); + return llvm::any_of( + Names, [&](const std::string &Name) { return Name == OpName; }); + } + +private: + static StringRef getOpName(const UnaryOperator &Node) { + return Node.getOpcodeStr(Node.getOpcode()); + } + static StringRef getOpName(const BinaryOperator &Node) { + return Node.getOpcodeStr(); + } + + const std::vector<std::string> Names; +}; + +using HasOpNameMatcher = + PolymorphicMatcherWithParam1<HasAnyOperatorNameMatcher, + std::vector<std::string>, + void(TypeList<BinaryOperator, UnaryOperator>)>; + +HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs); + } // namespace internal } // namespace ast_matchers Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4762,6 +4762,19 @@ return Name == Node.getOpcodeStr(Node.getOpcode()); } +/// Matches operator expressions (binary or unary) that have any of the +/// specified names. +/// +/// hasAnyOperatorName("+", "-") +/// Is equivalent to +/// anyOf(hasOperatorName("+"), hasOperatorName("-")) +extern const internal::VariadicFunction< + internal::PolymorphicMatcherWithParam1< + internal::HasAnyOperatorNameMatcher, std::vector<std::string>, + AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, UnaryOperator)>, + StringRef, internal::hasAnyOperatorNameFunc> + hasAnyOperatorName; + /// Matches all kinds of assignment operators. /// /// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator())) Index: clang/docs/tools/dump_ast_matchers.py =================================================================== --- clang/docs/tools/dump_ast_matchers.py +++ clang/docs/tools/dump_ast_matchers.py @@ -278,6 +278,22 @@ add_matcher(result, name, '%s, ..., %s' % (arg, arg), comment) return + m = re.match( + r"""^.*internal::VariadicFunction\s*<\s* + internal::PolymorphicMatcherWithParam1<[\S\s]+ + AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\)>,\s*([^,]+), + \s*[^>]+>\s*([a-zA-Z]*);$""", + declaration, flags=re.X) + + if m: + results, arg, name = m.groups()[:3] + + result_types = [r.strip() for r in results.split(',')] + for result_type in result_types: + add_matcher(result_type, name, '%s, ..., %s' % (arg, arg), comment) + return + + # Parse Variadic operator matchers. m = re.match( r"""^.*VariadicOperatorMatcherFunc\s*<\s*([^,]+),\s*([^\s]+)\s*>\s* Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -2128,6 +2128,16 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasAnyOperatorName0')"><a name="hasAnyOperatorName0Anchor">hasAnyOperatorName</a></td><td>StringRef, ..., StringRef</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyOperatorName0"><pre>Matches operator expressions (binary or unary) that have any of the +specified names. + + hasAnyOperatorName("+", "-") + Is equivalent to + anyOf(hasOperatorName("+"), hasOperatorName("-")) +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName0')"><a name="hasOperatorName0Anchor">hasOperatorName</a></td><td>std::string Name</td></tr> <tr><td colspan="4" class="doc" id="hasOperatorName0"><pre>Matches the operator Name of operator expressions (binary or unary). @@ -4312,6 +4322,16 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasAnyOperatorName1')"><a name="hasAnyOperatorName1Anchor">hasAnyOperatorName</a></td><td>StringRef, ..., StringRef</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyOperatorName1"><pre>Matches operator expressions (binary or unary) that have any of the +specified names. + + hasAnyOperatorName("+", "-") + Is equivalent to + anyOf(hasOperatorName("+"), hasOperatorName("-")) +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName1')"><a name="hasOperatorName1Anchor">hasOperatorName</a></td><td>std::string Name</td></tr> <tr><td colspan="4" class="doc" id="hasOperatorName1"><pre>Matches the operator Name of operator expressions (binary or unary). @@ -4552,6 +4572,17 @@ </pre></td></tr> +<tr><td>Matcher<clang::Stmt></td><td class="name" onclick="toggle('isExpandedFromMacro0')"><a name="isExpandedFromMacro0Anchor">isExpandedFromMacro</a></td><td>llvm::StringRef MacroName</td></tr> +<tr><td colspan="4" class="doc" id="isExpandedFromMacro0"><pre>Matches statements that are (transitively) expanded from the named macro. +Does not match if only part of the statement is expanded from that macro or +if different parts of the the statement are expanded from different +appearances of the macro. + +FIXME: Change to be a polymorphic matcher that works on any syntactic +node. There's nothing `Stmt`-specific about it. +</pre></td></tr> + + <tr><td>Matcher<internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>></td><td class="name" onclick="toggle('isInstantiated0')"><a name="isInstantiated0Anchor">isInstantiated</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isInstantiated0"><pre>Matches declarations that are template instantiations or are inside template instantiations.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits