xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp (revision 1af159e98c23a293c103e1f548866488126ed6f6)
190bbe970SFelix // RUN: %check_clang_tidy -check-suffixes=,CLASSIC %s readability-container-data-pointer %t -- -- -isystem %clang_tidy_headers -fno-delayed-template-parsing
2*1af159e9SPiotr Zegar // RUN: %check_clang_tidy -check-suffixes=,WITH-CONFIG %s readability-container-data-pointer %t -- -config="{CheckOptions: {readability-container-data-pointer.IgnoredContainers: '::std::basic_string'}}" -- -isystem %clang_tidy_headers -fno-delayed-template-parsing
390bbe970SFelix 
4efda335bSMike Crowe #include <string>
589a1d03eSRichard 
689a1d03eSRichard typedef __SIZE_TYPE__ size_t;
789a1d03eSRichard 
889a1d03eSRichard namespace std {
989a1d03eSRichard template <typename T>
1089a1d03eSRichard struct vector {
1189a1d03eSRichard   using size_type = size_t;
1289a1d03eSRichard 
1389a1d03eSRichard   vector();
1489a1d03eSRichard   explicit vector(size_type);
1589a1d03eSRichard 
1689a1d03eSRichard   T *data();
1789a1d03eSRichard   const T *data() const;
1889a1d03eSRichard 
1989a1d03eSRichard   T &operator[](size_type);
2089a1d03eSRichard   const T &operator[](size_type) const;
2189a1d03eSRichard };
2289a1d03eSRichard 
2389a1d03eSRichard template <typename T>
2489a1d03eSRichard struct is_integral;
2589a1d03eSRichard 
2689a1d03eSRichard template <>
2789a1d03eSRichard struct is_integral<size_t> {
2889a1d03eSRichard   static const bool value = true;
2989a1d03eSRichard };
3089a1d03eSRichard 
3189a1d03eSRichard template <bool, typename T = void>
3289a1d03eSRichard struct enable_if { };
3389a1d03eSRichard 
3489a1d03eSRichard template <typename T>
3589a1d03eSRichard struct enable_if<true, T> {
3689a1d03eSRichard   typedef T type;
3789a1d03eSRichard };
3889a1d03eSRichard }
3989a1d03eSRichard 
4089a1d03eSRichard template <typename T>
4189a1d03eSRichard void f(const T *);
4289a1d03eSRichard 
4389a1d03eSRichard #define z (0)
4489a1d03eSRichard 
g(size_t s)4589a1d03eSRichard void g(size_t s) {
4689a1d03eSRichard   std::vector<unsigned char> b(s);
4789a1d03eSRichard   f(&((b)[(z)]));
4889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
4989a1d03eSRichard   // CHECK-FIXES: {{^  }}f(b.data());{{$}}
5089a1d03eSRichard }
5189a1d03eSRichard 
h()5289a1d03eSRichard void h() {
5389a1d03eSRichard   std::string s;
5489a1d03eSRichard   f(&((s).operator[]((z))));
5590bbe970SFelix   // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
5690bbe970SFelix   // CHECK-FIXES-CLASSIC: {{^  }}f(s.data());{{$}}
5790bbe970SFelix   // CHECK-MESSAGES-WITH-CONFIG-NOT: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
5889a1d03eSRichard 
5989a1d03eSRichard   std::wstring w;
6089a1d03eSRichard   f(&((&(w))->operator[]((z))));
6190bbe970SFelix   // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
6290bbe970SFelix   // CHECK-FIXES-CLASSIC: {{^  }}f(w.data());{{$}}
6390bbe970SFelix   // CHECK-MESSAGES-WITH-CONFIG-NOT: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
6489a1d03eSRichard }
6589a1d03eSRichard 
6689a1d03eSRichard template <typename T, typename U,
6789a1d03eSRichard           typename = typename std::enable_if<std::is_integral<U>::value>::type>
i(U s)6889a1d03eSRichard void i(U s) {
6989a1d03eSRichard   std::vector<T> b(s);
7089a1d03eSRichard   f(&b[0]);
7189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
7289a1d03eSRichard   // CHECK-FIXES: {{^  }}f(b.data());{{$}}
7389a1d03eSRichard }
7489a1d03eSRichard 
7589a1d03eSRichard template void i<unsigned char, size_t>(size_t);
7689a1d03eSRichard 
j(std::vector<unsigned char> * const v)7789a1d03eSRichard void j(std::vector<unsigned char> * const v) {
7889a1d03eSRichard   f(&(*v)[0]);
7989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
8089a1d03eSRichard   // CHECK-FIXES: {{^  }}f(v->data());{{$}}
8189a1d03eSRichard }
8289a1d03eSRichard 
k(const std::vector<unsigned char> & v)8389a1d03eSRichard void k(const std::vector<unsigned char> &v) {
8489a1d03eSRichard   f(&v[0]);
8589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
8689a1d03eSRichard   // CHECK-FIXES: {{^  }}f(v.data());{{$}}
8789a1d03eSRichard }
8889a1d03eSRichard 
l()8989a1d03eSRichard void l() {
9089a1d03eSRichard   unsigned char b[32];
9189a1d03eSRichard   f(&b[0]);
9289a1d03eSRichard   // CHECK-MESSAGES-NOT: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
9389a1d03eSRichard }
9489a1d03eSRichard 
9589a1d03eSRichard template <typename T>
m(const std::vector<T> & v)9689a1d03eSRichard void m(const std::vector<T> &v) {
9789a1d03eSRichard   return &v[0];
9889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
9989a1d03eSRichard   // CHECK-FIXES: {{^  }}return v.data();{{$}}
10089a1d03eSRichard }
10189a1d03eSRichard 
10289a1d03eSRichard template <typename T>
10389a1d03eSRichard struct container_without_data {
10489a1d03eSRichard   using size_type = size_t;
10589a1d03eSRichard   T &operator[](size_type);
10689a1d03eSRichard   const T &operator[](size_type) const;
10789a1d03eSRichard };
10889a1d03eSRichard 
10989a1d03eSRichard template <typename T>
n(const container_without_data<T> & c)11089a1d03eSRichard const T *n(const container_without_data<T> &c) {
11189a1d03eSRichard   // c has no "data" member function, so there should not be a warning here:
11289a1d03eSRichard   return &c[0];
11389a1d03eSRichard }
11489a1d03eSRichard 
o(const std::vector<std::vector<std::vector<int>>> & v,const size_t idx1,const size_t idx2)11589a1d03eSRichard const int *o(const std::vector<std::vector<std::vector<int>>> &v, const size_t idx1, const size_t idx2) {
11689a1d03eSRichard   return &v[idx1][idx2][0];
11789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
11889a1d03eSRichard   // CHECK-FIXES: {{^  }}return v[idx1][idx2].data();{{$}}
11989a1d03eSRichard }
12089a1d03eSRichard 
select(std::vector<int> & u,std::vector<int> & v)12189a1d03eSRichard std::vector<int> &select(std::vector<int> &u, std::vector<int> &v) {
12289a1d03eSRichard   return v;
12389a1d03eSRichard }
12489a1d03eSRichard 
p(std::vector<int> & v1,std::vector<int> & v2)12589a1d03eSRichard int *p(std::vector<int> &v1, std::vector<int> &v2) {
12689a1d03eSRichard   return &select(*&v1, v2)[0];
12789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
12889a1d03eSRichard   // CHECK-FIXES: {{^  }}return select(*&v1, v2).data();{{$}}
12989a1d03eSRichard }
13089a1d03eSRichard 
q(std::vector<int> *** v)13189a1d03eSRichard int *q(std::vector<int> ***v) {
13289a1d03eSRichard   return &(***v)[0];
13389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
13489a1d03eSRichard   // CHECK-FIXES: {{^  }}return (**v)->data();{{$}}
13589a1d03eSRichard }
1360734c02bSDanny Mösch 
1370734c02bSDanny Mösch struct VectorHolder {
1380734c02bSDanny Mösch   std::vector<int> v;
1390734c02bSDanny Mösch };
1400734c02bSDanny Mösch 
r()1410734c02bSDanny Mösch int *r() {
1420734c02bSDanny Mösch   VectorHolder holder;
1430734c02bSDanny Mösch   return &holder.v[0];
1440734c02bSDanny Mösch   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
1450734c02bSDanny Mösch   // CHECK-FIXES: {{^  }}return holder.v.data();{{$}}
1460734c02bSDanny Mösch }
147