1+ // RUN: %check_clang_tidy %s modernize-replace-memcpy-with-std-copy %t
2+
3+ // CHECK-FIXES: #include <algorithm>
4+
5+ namespace {
6+
7+ using size_t = decltype (sizeof (int ));
8+
9+ namespace std {
10+ typedef long long int64_t ;
11+ typedef short int16_t ;
12+ typedef char int8_t ;
13+
14+ void *memcpy (void *__restrict dest, const void *__restrict src, size_t n);
15+
16+ template <typename T> struct vector {
17+ vector (size_t );
18+
19+ T *data ();
20+ size_t size () const ;
21+ void resize (size_t );
22+ using value_type = T;
23+ };
24+
25+ size_t size (void *);
26+
27+ size_t strlen (const char *);
28+ } // namespace std
29+
30+ void *memcpy (void *__restrict dest, const void *__restrict src, size_t n);
31+ } // namespace
32+
33+ void notSupportedEx () {
34+ char source[] = " once upon a daydream..." , dest[4 ];
35+
36+ auto *primitiveDest = new std::int8_t ;
37+ std::memcpy (primitiveDest, source, sizeof primitiveDest);
38+
39+ auto *primitiveDest2 = new std::int16_t ;
40+ std::memcpy (primitiveDest2, source, sizeof primitiveDest);
41+ std::memcpy (primitiveDest2, source, sizeof primitiveDest2);
42+
43+ double d = 0.1 ;
44+ std::int64_t n;
45+ // don't warn on calls over non-sequences
46+ std::memcpy (&n, &d, sizeof d);
47+
48+ // object creation in destination buffer
49+ struct S {
50+ int x{42 };
51+ void *operator new (size_t , void *) noexcept { return nullptr ; }
52+ } s;
53+ alignas (S) char buf[sizeof (S)];
54+ S *ps = new (buf) S; // placement new
55+ // // don't warn on calls over non-sequences
56+ std::memcpy (ps, &s, sizeof s);
57+
58+ const char *pSource = " once upon a daydream..." ;
59+ char *pDest = new char [4 ];
60+ std::memcpy (dest, pSource, sizeof dest);
61+ std::memcpy (pDest, source, 4 );
62+ }
63+
64+ void noFixItEx () {
65+ char source[] = " once upon a daydream..." , dest[4 ];
66+
67+ // no FixIt when return value is used
68+ auto *ptr = std::memcpy (dest, source, sizeof dest);
69+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: prefer std::copy_n to memcpy
70+
71+ std::vector<std::int16_t > vec_i16 (4 );
72+ // not a supported type, should be a sequence of bytes, otherwise it is difficult to compute the n in copy_n
73+ std::memcpy (vec_i16.data (), source,
74+ vec_i16.size () * sizeof (decltype (vec_i16)::value_type));
75+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
76+ }
77+
78+ void sequenceOfBytesEx () {
79+ // the check should support memcpy conversion for the following types:
80+ // T[]
81+ // std::vector<T>
82+ // std::span<T>
83+ // std::deque<T>
84+ // std::array<T, _>
85+ // std::string
86+ // std::string_view
87+ // where T is byte-like
88+
89+ char source[] = " once upon a daydream..." , dest[4 ];
90+ std::memcpy (dest, source, sizeof dest);
91+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
92+ // CHECK-FIXES: std::copy_n(std::begin(source), std::size(dest), std::begin(dest));
93+
94+ // __jm__ warn on global call as well
95+ memcpy (dest, source, sizeof dest);
96+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: prefer std::copy_n to memcpy
97+ // CHECK-FIXES: std::copy_n(std::begin(source), std::size(dest), std::begin(dest));
98+
99+ std::vector<char > vec_i8 (4 );
100+ std::memcpy (vec_i8.data (), source, vec_i8.size ());
101+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
102+ // CHECK-FIXES: std::copy_n(std::begin(source), std::size(vec_i8), std::begin(vec_i8));
103+
104+ // __jm__ make configurable whether stl containers should use members or free fns.
105+ // __jm__ for now use free fns. only
106+
107+ std::memcpy (dest, vec_i8.data (), vec_i8.size ());
108+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
109+ // CHECK-FIXES: std::copy_n(std::begin(vec_i8), std::size(vec_i8), std::begin(dest));
110+ std::memcpy (dest, vec_i8.data (), sizeof (dest));
111+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
112+ // CHECK-FIXES: std::copy_n(vec_i8.data(), std::size(dest), std::begin(dest));
113+ std::memcpy (dest, vec_i8.data (), std::size (dest));
114+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
115+ // CHECK-FIXES: std::copy_n(std::begin(source), std::size(vec_i8), std::begin(vec_i8));
116+
117+ std::memcpy (dest, vec_i8.data (), 1 + vec_i8.size () / 2 );
118+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
119+ // CHECK-FIXES: std::copy_n(std::begin(vec_i8), 1 + std::size(vec_i8) / 2, std::begin(dest));
120+ std::memcpy (dest, vec_i8.data (), 1 + sizeof (dest) / 2 );
121+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
122+ // CHECK-FIXES: std::copy_n(vec_i8.data(), 1 + std::size(dest) / 2, std::begin(dest));
123+ std::memcpy (dest, vec_i8.data (), 1 + std::size (dest) / 2 );
124+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: prefer std::copy_n to memcpy
125+ // CHECK-FIXES: std::copy_n(std::begin(source), 1 + std::size(dest) / 2, std::begin(vec_i8));
126+ }
127+
128+ // void uninitialized_copy_ex() {
129+ // std::vector<std::string> v = {"This", "is", "an", "example"};
130+
131+ // std::string* p;
132+ // std::size_t sz;
133+ // std::tie(p, sz) = std::get_temporary_buffer<std::string>(v.size());
134+ // sz = std::min(sz, v.size());
135+
136+ // std::uninitialized_copy_n(v.begin(), sz, p);
137+
138+ // for (std::string* i = p; i != p + sz; ++i)
139+ // {
140+ // std::cout << *i << ' ';
141+ // i->~basic_string<char>();
142+ // }
143+ // std::cout << '\n';
144+
145+ // std::return_temporary_buffer(p);
146+ // }
0 commit comments