diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 60d1c62b06819..a6532eee164d8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -682,6 +682,27 @@ enum ModuleArch { kModuleArchRISCV64 }; +// Sorts and removes duplicates from the container. +template > +void SortAndDedup(Container &v, Compare comp = {}) { + Sort(v.data(), v.size(), comp); + uptr size = v.size(); + if (size < 2) + return; + uptr last = 0; + for (uptr i = 1; i < size; ++i) { + if (comp(v[last], v[i])) { + ++last; + if (last != i) + v[last] = v[i]; + } else { + CHECK(!comp(v[i], v[last])); + } + } + v.resize(last + 1); +} + // Opens the file 'file_name" and reads up to 'max_len' bytes. // The resulting buffer is mmaped and stored in '*buff'. // Returns true if file was successfully opened and read. diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp index 1d0806c4c404b..4d9f2c1c831b0 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp @@ -269,6 +269,35 @@ TEST(SanitizerCommon, InternalLowerBoundVsStdLowerBound) { } } +class SortAndDedupTest : public ::testing::TestWithParam> {}; + +TEST_P(SortAndDedupTest, SortAndDedup) { + std::vector v_std = GetParam(); + std::sort(v_std.begin(), v_std.end()); + v_std.erase(std::unique(v_std.begin(), v_std.end()), v_std.end()); + + std::vector v = GetParam(); + SortAndDedup(v); + + EXPECT_EQ(v_std, v); +} + +const std::vector kSortAndDedupTests[] = { + {}, + {1}, + {1, 1}, + {1, 1, 1}, + {1, 2, 3}, + {3, 2, 1}, + {1, 2, 2, 3}, + {3, 3, 2, 1, 2}, + {3, 3, 2, 1, 2}, + {1, 2, 1, 1, 2, 1, 1, 1, 2, 2}, + {1, 3, 3, 2, 3, 1, 3, 1, 4, 4, 2, 1, 4, 1, 1, 2, 2}, +}; +INSTANTIATE_TEST_CASE_P(SortAndDedupTest, SortAndDedupTest, + ::testing::ValuesIn(kSortAndDedupTests)); + #if SANITIZER_LINUX && !SANITIZER_ANDROID TEST(SanitizerCommon, FindPathToBinary) { char *true_path = FindPathToBinary("true");