1*d5617adaSAlexander Shaposhnikov // RUN: %clangxx_nsan -O2 -g %s -o %t 2*d5617adaSAlexander Shaposhnikov // RUN: %run %t 2>&1 | FileCheck %s 3*d5617adaSAlexander Shaposhnikov 4*d5617adaSAlexander Shaposhnikov // Check compilation mode that is required to call memcpy/memmove. 5*d5617adaSAlexander Shaposhnikov // RUN: %clangxx_nsan -fno-builtin -O2 -g %s -o %t 6*d5617adaSAlexander Shaposhnikov // RUN: %run %t 2>&1 | FileCheck %s 7*d5617adaSAlexander Shaposhnikov 8*d5617adaSAlexander Shaposhnikov // This tests a particularaly hard case of memory tracking. stable_sort does 9*d5617adaSAlexander Shaposhnikov // conditional swaps of pairs of elements with mixed types (int/double). 10*d5617adaSAlexander Shaposhnikov 11*d5617adaSAlexander Shaposhnikov #include <algorithm> 12*d5617adaSAlexander Shaposhnikov #include <cstddef> 13*d5617adaSAlexander Shaposhnikov #include <cstdio> 14*d5617adaSAlexander Shaposhnikov #include <utility> 15*d5617adaSAlexander Shaposhnikov #include <vector> 16*d5617adaSAlexander Shaposhnikov 17*d5617adaSAlexander Shaposhnikov extern "C" void __nsan_dump_shadow_mem(const char *addr, size_t size_bytes, 18*d5617adaSAlexander Shaposhnikov size_t bytes_per_line, size_t reserved); 19*d5617adaSAlexander Shaposhnikov 20*d5617adaSAlexander Shaposhnikov __attribute__((noinline)) void Run(std::vector<int> &indices, 21*d5617adaSAlexander Shaposhnikov std::vector<double> &values) { 22*d5617adaSAlexander Shaposhnikov const auto num_entries = indices.size(); 23*d5617adaSAlexander Shaposhnikov std::vector<std::pair<int, double>> entries; 24*d5617adaSAlexander Shaposhnikov entries.reserve(num_entries); 25*d5617adaSAlexander Shaposhnikov for (size_t i = 0; i < num_entries; ++i) 26*d5617adaSAlexander Shaposhnikov entries.emplace_back(indices[i], values[i]); 27*d5617adaSAlexander Shaposhnikov 28*d5617adaSAlexander Shaposhnikov __nsan_dump_shadow_mem((const char *)&entries[0].second, sizeof(double), 29*d5617adaSAlexander Shaposhnikov sizeof(double), 0); 30*d5617adaSAlexander Shaposhnikov __nsan_dump_shadow_mem((const char *)&entries[1].second, sizeof(double), 31*d5617adaSAlexander Shaposhnikov sizeof(double), 0); 32*d5617adaSAlexander Shaposhnikov // CHECK: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (1.02800000000000002487) 33*d5617adaSAlexander Shaposhnikov // CHECK-NEXT: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (7.95099999999999962341) 34*d5617adaSAlexander Shaposhnikov std::stable_sort( 35*d5617adaSAlexander Shaposhnikov entries.begin(), entries.end(), 36*d5617adaSAlexander Shaposhnikov [](const std::pair<int, double> &a, const std::pair<int, double> &b) { 37*d5617adaSAlexander Shaposhnikov return a.first < b.first; 38*d5617adaSAlexander Shaposhnikov }); 39*d5617adaSAlexander Shaposhnikov __nsan_dump_shadow_mem((const char *)&entries[0].second, sizeof(double), 40*d5617adaSAlexander Shaposhnikov sizeof(double), 0); 41*d5617adaSAlexander Shaposhnikov __nsan_dump_shadow_mem((const char *)&entries[1].second, sizeof(double), 42*d5617adaSAlexander Shaposhnikov sizeof(double), 0); 43*d5617adaSAlexander Shaposhnikov // We make sure that the shadow values have been swapped correctly. 44*d5617adaSAlexander Shaposhnikov // CHECK-NEXT: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (7.95099999999999962341) 45*d5617adaSAlexander Shaposhnikov // CHECK-NEXT: {{.*}}: d0 d1 d2 d3 d4 d5 d6 d7 (1.02800000000000002487) 46*d5617adaSAlexander Shaposhnikov } 47*d5617adaSAlexander Shaposhnikov 48*d5617adaSAlexander Shaposhnikov int main() { 49*d5617adaSAlexander Shaposhnikov std::vector<int> indices; 50*d5617adaSAlexander Shaposhnikov std::vector<double> values; 51*d5617adaSAlexander Shaposhnikov indices.push_back(75); 52*d5617adaSAlexander Shaposhnikov values.push_back(1.028); 53*d5617adaSAlexander Shaposhnikov indices.push_back(74); 54*d5617adaSAlexander Shaposhnikov values.push_back(7.951); 55*d5617adaSAlexander Shaposhnikov Run(indices, values); 56*d5617adaSAlexander Shaposhnikov } 57