CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
460 lines
20 KiB
C++
460 lines
20 KiB
C++
// RUN: %check_clang_tidy %s readability-container-contains %t
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <unordered_set>
|
|
|
|
// Check that we detect various common ways to check for membership
|
|
int testDifferentCheckTypes(std::map<int, int> &MyMap) {
|
|
if (MyMap.count(0))
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap.contains(0))
|
|
return 1;
|
|
bool C1 = MyMap.count(1);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C1 = MyMap.contains(1);
|
|
auto C2 = static_cast<bool>(MyMap.count(1));
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C2 = static_cast<bool>(MyMap.contains(1));
|
|
auto C3 = MyMap.count(2) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C3 = MyMap.contains(2);
|
|
auto C4 = MyMap.count(3) > 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C4 = MyMap.contains(3);
|
|
auto C5 = MyMap.count(4) >= 1;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C5 = MyMap.contains(4);
|
|
auto C6 = MyMap.find(5) != MyMap.end();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C6 = MyMap.contains(5);
|
|
return C1 + C2 + C3 + C4 + C5 + C6;
|
|
}
|
|
|
|
// Check that we detect various common ways to check for non-membership
|
|
int testNegativeChecks(std::map<int, int> &MyMap) {
|
|
bool C1 = !MyMap.count(-1);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C1 = !MyMap.contains(-1);
|
|
auto C2 = MyMap.count(-2) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C2 = !MyMap.contains(-2);
|
|
auto C3 = MyMap.count(-3) <= 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C3 = !MyMap.contains(-3);
|
|
auto C4 = MyMap.count(-4) < 1;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C4 = !MyMap.contains(-4);
|
|
auto C5 = MyMap.find(-5) == MyMap.end();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C5 = !MyMap.contains(-5);
|
|
return C1 + C2 + C3 + C4 + C5;
|
|
}
|
|
|
|
// Check for various types
|
|
int testDifferentTypes(std::map<int, int> &M, std::unordered_set<int> &US, std::set<int> &S, std::multimap<int, int> &MM) {
|
|
bool C1 = M.count(1001);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C1 = M.contains(1001);
|
|
bool C2 = US.count(1002);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C2 = US.contains(1002);
|
|
bool C3 = S.count(1003);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C3 = S.contains(1003);
|
|
bool C4 = MM.count(1004);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C4 = MM.contains(1004);
|
|
return C1 + C2 + C3 + C4;
|
|
}
|
|
|
|
// The check detects all kind of `const`, reference, rvalue-reference and value types.
|
|
int testQualifiedTypes(std::map<int, int> ValueM, std::map<int, int> &RefM, const std::map<int, int> &ConstRefM, std::map<int, int> &&RValueM) {
|
|
bool C1 = ValueM.count(2001);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C1 = ValueM.contains(2001);
|
|
bool C2 = RefM.count(2002);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C2 = RefM.contains(2002);
|
|
bool C3 = ConstRefM.count(2003);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C3 = ConstRefM.contains(2003);
|
|
bool C4 = RValueM.count(2004);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C4 = RValueM.contains(2004);
|
|
return C1 + C2 + C3 + C4;
|
|
}
|
|
|
|
// This is effectively a membership check, as the result is implicitly casted
|
|
// to `bool`.
|
|
bool returnContains(std::map<int, int> &M) {
|
|
return M.count(42);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: return M.contains(42);
|
|
}
|
|
|
|
// This returns the actual count and should not be rewritten
|
|
int actualCount(std::multimap<int, int> &M) {
|
|
return M.count(21);
|
|
// NO-WARNING.
|
|
// CHECK-FIXES: return M.count(21);
|
|
}
|
|
|
|
// Check that we are not confused by aliases
|
|
namespace s2 = std;
|
|
using MyMapT = s2::map<int, int>;
|
|
int typeAliases(MyMapT &MyMap) {
|
|
bool C1 = MyMap.count(99);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: bool C1 = MyMap.contains(99);
|
|
return C1;
|
|
}
|
|
|
|
// Check that the tests also trigger for a local variable and not only for
|
|
// function arguments.
|
|
bool localVar() {
|
|
using namespace std;
|
|
map<int, int> LocalM;
|
|
return LocalM.count(42);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: return LocalM.contains(42);
|
|
}
|
|
|
|
// Check various usages of an actual `count` which isn't rewritten
|
|
int nonRewrittenCount(std::multimap<int, int> &MyMap) {
|
|
// This is an actual test if we have at least 2 usages. Shouldn't be rewritten.
|
|
bool C1 = MyMap.count(1) >= 2;
|
|
// NO-WARNING.
|
|
// CHECK-FIXES: bool C1 = MyMap.count(1) >= 2;
|
|
|
|
// "< 0" makes little sense and is always `false`. Still, let's ensure we
|
|
// don't accidentally rewrite it to 'contains'.
|
|
bool C2 = MyMap.count(2) < 0;
|
|
// NO-WARNING.
|
|
// CHECK-FIXES: bool C2 = MyMap.count(2) < 0;
|
|
|
|
// The `count` is used in some more complicated formula.
|
|
bool C3 = MyMap.count(1) + MyMap.count(2) * 2 + MyMap.count(3) / 3 >= 20;
|
|
// NO-WARNING.
|
|
// CHECK-FIXES: bool C3 = MyMap.count(1) + MyMap.count(2) * 2 + MyMap.count(3) / 3 >= 20;
|
|
|
|
// This could theoretically be rewritten into a 'contains' after removig the
|
|
// `4` on both sides of the comparison. For the time being, we don't detect
|
|
// this case.
|
|
bool C4 = MyMap.count(1) + 4 > 4;
|
|
// NO-WARNING.
|
|
// CHECK-FIXES: bool C4 = MyMap.count(1) + 4 > 4;
|
|
|
|
return C1 + C2 + C3 + C4;
|
|
}
|
|
|
|
// Check different integer literal suffixes
|
|
int testDifferentIntegerLiteralSuffixes(std::map<int, int> &MyMap) {
|
|
|
|
auto C1 = MyMap.count(2) != 0U;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C1 = MyMap.contains(2);
|
|
auto C2 = MyMap.count(2) != 0UL;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C2 = MyMap.contains(2);
|
|
auto C3 = 0U != MyMap.count(2);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C3 = MyMap.contains(2);
|
|
auto C4 = 0UL != MyMap.count(2);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C4 = MyMap.contains(2);
|
|
auto C5 = MyMap.count(2) < 1U;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C5 = !MyMap.contains(2);
|
|
auto C6 = MyMap.count(2) < 1UL;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C6 = !MyMap.contains(2);
|
|
auto C7 = 1U > MyMap.count(2);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C7 = !MyMap.contains(2);
|
|
auto C8 = 1UL > MyMap.count(2);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: auto C8 = !MyMap.contains(2);
|
|
|
|
return C1 + C2 + C3 + C4 + C5 + C6 + C7 + C8;
|
|
}
|
|
|
|
// We don't want to rewrite if the `contains` call is from a macro expansion
|
|
int testMacroExpansion(std::unordered_set<int> &MySet) {
|
|
#define COUNT_ONES(SET) SET.count(1)
|
|
// Rewriting the macro would break the code
|
|
// CHECK-FIXES: #define COUNT_ONES(SET) SET.count(1)
|
|
// We still want to warn the user even if we don't offer a fixit
|
|
if (COUNT_ONES(MySet)) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-MESSAGES: note: expanded from macro 'COUNT_ONES'
|
|
return COUNT_ONES(MySet);
|
|
}
|
|
#undef COUNT_ONES
|
|
#define COUNT_ONES count(1)
|
|
// Rewriting the macro would break the code
|
|
// CHECK-FIXES: #define COUNT_ONES count(1)
|
|
// We still want to warn the user even if we don't offer a fixit
|
|
if (MySet.COUNT_ONES) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-MESSAGES: note: expanded from macro 'COUNT_ONES'
|
|
return MySet.COUNT_ONES;
|
|
}
|
|
#undef COUNT_ONES
|
|
#define MY_SET MySet
|
|
// CHECK-FIXES: #define MY_SET MySet
|
|
// We still want to rewrite one of the two calls to `count`
|
|
if (MY_SET.count(1)) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MY_SET.contains(1)) {
|
|
return MY_SET.count(1);
|
|
}
|
|
#undef MY_SET
|
|
return 0;
|
|
}
|
|
|
|
// The following map has the same interface as `std::map`.
|
|
template <class Key, class T>
|
|
struct CustomMap {
|
|
unsigned count(const Key &K) const;
|
|
bool contains(const Key &K) const;
|
|
void *find(const Key &K);
|
|
void *end();
|
|
};
|
|
|
|
void testDifferentCheckTypes(CustomMap<int, int> &MyMap) {
|
|
if (MyMap.count(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap.contains(0)) {}
|
|
|
|
MyMap.find(0) != MyMap.end();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: MyMap.contains(0);
|
|
}
|
|
|
|
struct MySubmap : public CustomMap<int, int> {};
|
|
|
|
void testSubclass(MySubmap& MyMap) {
|
|
if (MyMap.count(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap.contains(0)) {}
|
|
}
|
|
|
|
using UsingMap = CustomMap<int, int>;
|
|
struct MySubmap2 : public UsingMap {};
|
|
using UsingMap2 = MySubmap2;
|
|
|
|
void testUsing(UsingMap2& MyMap) {
|
|
if (MyMap.count(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap.contains(0)) {}
|
|
}
|
|
|
|
template <class Key, class T>
|
|
struct CustomMapContainsDeleted {
|
|
unsigned count(const Key &K) const;
|
|
bool contains(const Key &K) const = delete;
|
|
void *find(const Key &K);
|
|
void *end();
|
|
};
|
|
|
|
struct SubmapContainsDeleted : public CustomMapContainsDeleted<int, int> {};
|
|
|
|
void testContainsDeleted(CustomMapContainsDeleted<int, int> &MyMap,
|
|
SubmapContainsDeleted &MyMap2) {
|
|
// No warning if the `contains` method is deleted.
|
|
if (MyMap.count(0)) {}
|
|
if (MyMap2.count(0)) {}
|
|
}
|
|
|
|
template <class Key, class T>
|
|
struct CustomMapPrivateContains {
|
|
unsigned count(const Key &K) const;
|
|
void *find(const Key &K);
|
|
void *end();
|
|
|
|
private:
|
|
bool contains(const Key &K) const;
|
|
};
|
|
|
|
struct SubmapPrivateContains : public CustomMapPrivateContains<int, int> {};
|
|
|
|
void testPrivateContains(CustomMapPrivateContains<int, int> &MyMap,
|
|
SubmapPrivateContains &MyMap2) {
|
|
// No warning if the `contains` method is not public.
|
|
if (MyMap.count(0)) {}
|
|
if (MyMap2.count(0)) {}
|
|
}
|
|
|
|
struct WeirdNonMatchingContains {
|
|
unsigned count(char) const;
|
|
bool contains(const std::string&) const;
|
|
};
|
|
|
|
// False positives: when count/find and contains take different types,
|
|
// the check will suggest an invalid code transformation. These cases
|
|
// should not exist in real code or be rare enough.
|
|
void f(WeirdNonMatchingContains MyMap) {
|
|
if (MyMap.count('a')) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap.contains('a')) {}
|
|
}
|
|
|
|
template <class T>
|
|
struct SmallPtrSet {
|
|
using ConstPtrType = const T*;
|
|
unsigned count(ConstPtrType Ptr) const;
|
|
bool contains(ConstPtrType Ptr) const;
|
|
};
|
|
|
|
template <class T>
|
|
struct SmallPtrPtrSet {
|
|
using ConstPtrType = const T**;
|
|
unsigned count(ConstPtrType Ptr) const;
|
|
bool contains(ConstPtrType Ptr) const;
|
|
};
|
|
|
|
template <class T>
|
|
struct SmallPtrPtrPtrSet {
|
|
using ConstPtrType = const T***;
|
|
unsigned count(ConstPtrType Ptr) const;
|
|
bool contains(ConstPtrType Ptr) const;
|
|
};
|
|
|
|
void testSmallPtrSet(const int ***Ptr,
|
|
SmallPtrSet<int> &MySet,
|
|
SmallPtrPtrSet<int> &MySet2,
|
|
SmallPtrPtrPtrSet<int> &MySet3) {
|
|
if (MySet.count(**Ptr)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MySet.contains(**Ptr)) {}
|
|
if (MySet2.count(*Ptr)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MySet2.contains(*Ptr)) {}
|
|
if (MySet3.count(Ptr)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MySet3.contains(Ptr)) {}
|
|
}
|
|
|
|
struct X {};
|
|
struct Y : public X {};
|
|
|
|
void testSubclassEntry(SmallPtrSet<X>& Set, Y* Entry) {
|
|
if (Set.count(Entry)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Set.contains(Entry)) {}
|
|
}
|
|
|
|
void testIntUnsigned(std::set<int>& S, unsigned U) {
|
|
if (S.count(U)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (S.contains(U)) {}
|
|
}
|
|
|
|
template <class T>
|
|
struct CustomSetConvertible {
|
|
unsigned count(const T &K) const;
|
|
bool contains(const T &K) const;
|
|
};
|
|
|
|
struct A {};
|
|
struct B { B() = default; B(const A&) {} };
|
|
struct C { operator A() const; };
|
|
|
|
void testConvertibleTypes() {
|
|
CustomSetConvertible<B> MyMap;
|
|
if (MyMap.count(A())) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap.contains(A())) {}
|
|
|
|
CustomSetConvertible<A> MyMap2;
|
|
if (MyMap2.count(C())) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap2.contains(C())) {}
|
|
|
|
if (MyMap2.count(C()) != 0) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (MyMap2.contains(C())) {}
|
|
}
|
|
|
|
template<class U>
|
|
using Box = const U& ;
|
|
|
|
template <class T>
|
|
struct CustomBoxedSet {
|
|
unsigned count(Box<T> K) const;
|
|
bool contains(Box<T> K) const;
|
|
};
|
|
|
|
void testBox() {
|
|
CustomBoxedSet<int> Set;
|
|
if (Set.count(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Set.contains(0)) {}
|
|
}
|
|
|
|
void testOperandPermutations(std::map<int, int>& Map) {
|
|
if (Map.count(0) != 0) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Map.contains(0)) {}
|
|
if (0 != Map.count(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Map.contains(0)) {}
|
|
if (Map.count(0) == 0) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!Map.contains(0)) {}
|
|
if (0 == Map.count(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!Map.contains(0)) {}
|
|
if (Map.find(0) != Map.end()) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Map.contains(0)) {}
|
|
if (Map.end() != Map.find(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Map.contains(0)) {}
|
|
if (Map.find(0) == Map.end()) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!Map.contains(0)) {}
|
|
if (Map.end() == Map.find(0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!Map.contains(0)) {}
|
|
}
|
|
|
|
void testStringNpos(std::string Str1, std::string Str2, std::string_view StrView) {
|
|
if (Str1.find(Str2) == std::string::npos) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!Str1.contains(Str2)) {}
|
|
|
|
if (Str1.find("test") == std::string::npos) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!Str1.contains("test")) {}
|
|
|
|
if (Str1.find('c') != std::string::npos) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Str1.contains('c')) {}
|
|
|
|
if (Str1.find(Str2, 0) != std::string::npos) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (Str1.contains(Str2)) {}
|
|
|
|
if (std::string::npos == Str1.find("test", 0)) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!Str1.contains("test")) {}
|
|
|
|
if (StrView.find("test") == std::string_view::npos) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (!StrView.contains("test")) {}
|
|
|
|
if (StrView.find('c') != std::string_view::npos) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (StrView.contains('c')) {}
|
|
|
|
if (StrView.find('c') != StrView.npos) {}
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use 'contains' to check for membership [readability-container-contains]
|
|
// CHECK-FIXES: if (StrView.contains('c')) {}
|
|
|
|
// These should not match.
|
|
if (Str1.find('c', 1) != Str1.npos) {}
|
|
if (Str1.find(StrView, 1) != Str1.npos) {}
|
|
}
|