forked from OSchip/llvm-project
[ASTMatchers] Adds a matcher called `hasAnyOperatorName`
Summary: Acts on `BinaryOperator` and `UnaryOperator` and functions the same as `anyOf(hasOperatorName(...), hasOperatorName(...), ...)` Documentation generation isn't perfect but I feel that the python doc script needs updating for that Reviewers: aaron.ballman, gribozavr2 Reviewed By: aaron.ballman, gribozavr2 Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D75040
This commit is contained in:
parent
3e9a7b2ba4
commit
6a0c066c61
|
@ -2128,6 +2128,16 @@ Usable as: Any Matcher
|
|||
</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).
|
||||
|
@ -4373,6 +4383,16 @@ should be passed as a quoted string. e.g., ofKind("UETT_SizeOf").
|
|||
</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).
|
||||
|
|
|
@ -284,6 +284,22 @@ def act_on_decl(declaration, comment, allowed_types):
|
|||
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*
|
||||
|
|
|
@ -4762,6 +4762,19 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
|
|||
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()))
|
||||
|
|
|
@ -1858,6 +1858,47 @@ CompoundStmtMatcher<StmtExpr>::get(const StmtExpr &Node) {
|
|||
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
|
||||
|
|
|
@ -375,6 +375,10 @@ Matcher<ObjCMessageExpr> hasAnySelectorFunc(
|
|||
return hasAnySelectorMatcher(vectorFromRefs(NameRefs));
|
||||
}
|
||||
|
||||
HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs) {
|
||||
return HasOpNameMatcher(vectorFromRefs(NameRefs));
|
||||
}
|
||||
|
||||
HasNameMatcher::HasNameMatcher(std::vector<std::string> N)
|
||||
: UseUnqualifiedMatch(llvm::all_of(
|
||||
N, [](StringRef Name) { return Name.find("::") == Name.npos; })),
|
||||
|
@ -849,6 +853,10 @@ const internal::VariadicOperatorMatcherFunc<
|
|||
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 = {};
|
||||
|
|
|
@ -243,6 +243,7 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(hasAnyConstructorInitializer);
|
||||
REGISTER_MATCHER(hasAnyDeclaration);
|
||||
REGISTER_MATCHER(hasAnyName);
|
||||
REGISTER_MATCHER(hasAnyOperatorName);
|
||||
REGISTER_MATCHER(hasAnyParameter);
|
||||
REGISTER_MATCHER(hasAnyPlacementArg);
|
||||
REGISTER_MATCHER(hasAnySelector);
|
||||
|
|
|
@ -1123,6 +1123,19 @@ TEST(MatchBinaryOperator, HasOperatorName) {
|
|||
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 @@ TEST(MatchUnaryOperator, HasOperatorName) {
|
|||
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))));
|
||||
|
|
Loading…
Reference in New Issue