|
13 | 13 | using namespace clang::ast_matchers;
|
14 | 14 |
|
15 | 15 | namespace clang::tidy::readability {
|
16 |
| - |
17 | 16 | void ContainerContainsCheck::registerMatchers(MatchFinder *Finder) {
|
18 |
| - const auto SupportedContainers = hasType( |
19 |
| - hasUnqualifiedDesugaredType(recordType(hasDeclaration(cxxRecordDecl( |
20 |
| - hasAnyName("::std::set", "::std::unordered_set", "::std::map", |
21 |
| - "::std::unordered_map", "::std::multiset", |
22 |
| - "::std::unordered_multiset", "::std::multimap", |
23 |
| - "::std::unordered_multimap")))))); |
| 17 | + const auto HasContainsMatchingArgType = hasMethod( |
| 18 | + cxxMethodDecl(isConst(), parameterCountIs(1), returns(booleanType()), |
| 19 | + hasName("contains"), unless(isDeleted()), isPublic(), |
| 20 | + hasParameter(0, hasType(hasUnqualifiedDesugaredType( |
| 21 | + equalsBoundNode("parameterType")))))); |
24 | 22 |
|
25 | 23 | const auto CountCall =
|
26 |
| - cxxMemberCallExpr(on(SupportedContainers), |
27 |
| - callee(cxxMethodDecl(hasName("count"))), |
28 |
| - argumentCountIs(1)) |
| 24 | + cxxMemberCallExpr( |
| 25 | + argumentCountIs(1), |
| 26 | + callee(cxxMethodDecl( |
| 27 | + hasName("count"), |
| 28 | + hasParameter(0, hasType(hasUnqualifiedDesugaredType( |
| 29 | + type().bind("parameterType")))), |
| 30 | + ofClass(cxxRecordDecl(HasContainsMatchingArgType))))) |
29 | 31 | .bind("call");
|
30 | 32 |
|
31 | 33 | const auto FindCall =
|
32 |
| - cxxMemberCallExpr(on(SupportedContainers), |
33 |
| - callee(cxxMethodDecl(hasName("find"))), |
34 |
| - argumentCountIs(1)) |
| 34 | + cxxMemberCallExpr( |
| 35 | + argumentCountIs(1), |
| 36 | + callee(cxxMethodDecl( |
| 37 | + hasName("find"), |
| 38 | + hasParameter(0, hasType(hasUnqualifiedDesugaredType( |
| 39 | + type().bind("parameterType")))), |
| 40 | + ofClass(cxxRecordDecl(HasContainsMatchingArgType))))) |
35 | 41 | .bind("call");
|
36 | 42 |
|
37 |
| - const auto EndCall = cxxMemberCallExpr(on(SupportedContainers), |
38 |
| - callee(cxxMethodDecl(hasName("end"))), |
39 |
| - argumentCountIs(0)); |
| 43 | + const auto EndCall = cxxMemberCallExpr( |
| 44 | + argumentCountIs(0), |
| 45 | + callee( |
| 46 | + cxxMethodDecl(hasName("end"), |
| 47 | + // In the matchers below, FindCall should always appear |
| 48 | + // before EndCall so 'parameterType' is properly bound. |
| 49 | + ofClass(cxxRecordDecl(HasContainsMatchingArgType))))); |
40 | 50 |
|
41 | 51 | const auto Literal0 = integerLiteral(equals(0));
|
42 | 52 | const auto Literal1 = integerLiteral(equals(1));
|
43 | 53 |
|
44 |
| - auto AddSimpleMatcher = [&](auto Matcher) { |
45 |
| - Finder->addMatcher( |
46 |
| - traverse(TK_IgnoreUnlessSpelledInSource, std::move(Matcher)), this); |
47 |
| - }; |
48 |
| - |
49 | 54 | // Find membership tests which use `count()`.
|
50 | 55 | Finder->addMatcher(implicitCastExpr(hasImplicitDestinationType(booleanType()),
|
51 | 56 | hasSourceExpression(CountCall))
|
52 | 57 | .bind("positiveComparison"),
|
53 | 58 | this);
|
54 |
| - AddSimpleMatcher( |
55 |
| - binaryOperator(hasLHS(CountCall), hasOperatorName("!="), hasRHS(Literal0)) |
56 |
| - .bind("positiveComparison")); |
57 |
| - AddSimpleMatcher( |
58 |
| - binaryOperator(hasLHS(Literal0), hasOperatorName("!="), hasRHS(CountCall)) |
59 |
| - .bind("positiveComparison")); |
60 |
| - AddSimpleMatcher( |
61 |
| - binaryOperator(hasLHS(CountCall), hasOperatorName(">"), hasRHS(Literal0)) |
62 |
| - .bind("positiveComparison")); |
63 |
| - AddSimpleMatcher( |
64 |
| - binaryOperator(hasLHS(Literal0), hasOperatorName("<"), hasRHS(CountCall)) |
65 |
| - .bind("positiveComparison")); |
66 |
| - AddSimpleMatcher( |
67 |
| - binaryOperator(hasLHS(CountCall), hasOperatorName(">="), hasRHS(Literal1)) |
68 |
| - .bind("positiveComparison")); |
69 |
| - AddSimpleMatcher( |
70 |
| - binaryOperator(hasLHS(Literal1), hasOperatorName("<="), hasRHS(CountCall)) |
71 |
| - .bind("positiveComparison")); |
| 59 | + Finder->addMatcher( |
| 60 | + binaryOperator(hasOperatorName("!="), |
| 61 | + hasOperands(ignoringParenImpCasts(CountCall), |
| 62 | + ignoringParenImpCasts(Literal0))) |
| 63 | + .bind("positiveComparison"), |
| 64 | + this); |
| 65 | + Finder->addMatcher(binaryOperator(hasOperatorName(">"), |
| 66 | + hasLHS(ignoringParenImpCasts(CountCall)), |
| 67 | + hasRHS(ignoringParenImpCasts(Literal0))) |
| 68 | + .bind("positiveComparison"), |
| 69 | + this); |
| 70 | + Finder->addMatcher(binaryOperator(hasOperatorName("<"), |
| 71 | + hasLHS(ignoringParenImpCasts(Literal0)), |
| 72 | + hasRHS(ignoringParenImpCasts(CountCall))) |
| 73 | + .bind("positiveComparison"), |
| 74 | + this); |
| 75 | + Finder->addMatcher(binaryOperator(hasOperatorName(">="), |
| 76 | + hasLHS(ignoringParenImpCasts(CountCall)), |
| 77 | + hasRHS(ignoringParenImpCasts(Literal1))) |
| 78 | + .bind("positiveComparison"), |
| 79 | + this); |
| 80 | + Finder->addMatcher(binaryOperator(hasOperatorName("<="), |
| 81 | + hasLHS(ignoringParenImpCasts(Literal1)), |
| 82 | + hasRHS(ignoringParenImpCasts(CountCall))) |
| 83 | + .bind("positiveComparison"), |
| 84 | + this); |
72 | 85 |
|
73 | 86 | // Find inverted membership tests which use `count()`.
|
74 |
| - AddSimpleMatcher( |
75 |
| - binaryOperator(hasLHS(CountCall), hasOperatorName("=="), hasRHS(Literal0)) |
76 |
| - .bind("negativeComparison")); |
77 |
| - AddSimpleMatcher( |
78 |
| - binaryOperator(hasLHS(Literal0), hasOperatorName("=="), hasRHS(CountCall)) |
79 |
| - .bind("negativeComparison")); |
80 |
| - AddSimpleMatcher( |
81 |
| - binaryOperator(hasLHS(CountCall), hasOperatorName("<="), hasRHS(Literal0)) |
82 |
| - .bind("negativeComparison")); |
83 |
| - AddSimpleMatcher( |
84 |
| - binaryOperator(hasLHS(Literal0), hasOperatorName(">="), hasRHS(CountCall)) |
85 |
| - .bind("negativeComparison")); |
86 |
| - AddSimpleMatcher( |
87 |
| - binaryOperator(hasLHS(CountCall), hasOperatorName("<"), hasRHS(Literal1)) |
88 |
| - .bind("negativeComparison")); |
89 |
| - AddSimpleMatcher( |
90 |
| - binaryOperator(hasLHS(Literal1), hasOperatorName(">"), hasRHS(CountCall)) |
91 |
| - .bind("negativeComparison")); |
| 87 | + Finder->addMatcher( |
| 88 | + binaryOperator(hasOperatorName("=="), |
| 89 | + hasOperands(ignoringParenImpCasts(CountCall), |
| 90 | + ignoringParenImpCasts(Literal0))) |
| 91 | + .bind("negativeComparison"), |
| 92 | + this); |
| 93 | + Finder->addMatcher(binaryOperator(hasOperatorName("<="), |
| 94 | + hasLHS(ignoringParenImpCasts(CountCall)), |
| 95 | + hasRHS(ignoringParenImpCasts(Literal0))) |
| 96 | + .bind("negativeComparison"), |
| 97 | + this); |
| 98 | + Finder->addMatcher(binaryOperator(hasOperatorName(">="), |
| 99 | + hasLHS(ignoringParenImpCasts(Literal0)), |
| 100 | + hasRHS(ignoringParenImpCasts(CountCall))) |
| 101 | + .bind("negativeComparison"), |
| 102 | + this); |
| 103 | + Finder->addMatcher(binaryOperator(hasOperatorName("<"), |
| 104 | + hasLHS(ignoringParenImpCasts(CountCall)), |
| 105 | + hasRHS(ignoringParenImpCasts(Literal1))) |
| 106 | + .bind("negativeComparison"), |
| 107 | + this); |
| 108 | + Finder->addMatcher(binaryOperator(hasOperatorName(">"), |
| 109 | + hasLHS(ignoringParenImpCasts(Literal1)), |
| 110 | + hasRHS(ignoringParenImpCasts(CountCall))) |
| 111 | + .bind("negativeComparison"), |
| 112 | + this); |
92 | 113 |
|
93 | 114 | // Find membership tests based on `find() == end()`.
|
94 |
| - AddSimpleMatcher( |
95 |
| - binaryOperator(hasLHS(FindCall), hasOperatorName("!="), hasRHS(EndCall)) |
96 |
| - .bind("positiveComparison")); |
97 |
| - AddSimpleMatcher( |
98 |
| - binaryOperator(hasLHS(FindCall), hasOperatorName("=="), hasRHS(EndCall)) |
99 |
| - .bind("negativeComparison")); |
| 115 | + Finder->addMatcher(binaryOperator(hasOperatorName("!="), |
| 116 | + hasOperands(ignoringParenImpCasts(FindCall), |
| 117 | + ignoringParenImpCasts(EndCall))) |
| 118 | + .bind("positiveComparison"), |
| 119 | + this); |
| 120 | + Finder->addMatcher(binaryOperator(hasOperatorName("=="), |
| 121 | + hasOperands(ignoringParenImpCasts(FindCall), |
| 122 | + ignoringParenImpCasts(EndCall))) |
| 123 | + .bind("negativeComparison"), |
| 124 | + this); |
100 | 125 | }
|
101 | 126 |
|
102 | 127 | void ContainerContainsCheck::check(const MatchFinder::MatchResult &Result) {
|
|
0 commit comments