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