1 // RUN: %check_clang_tidy %s readability-simplify-subscript-expr %t \
2 // RUN: -config="{CheckOptions: \
3 // RUN: [{key: readability-simplify-subscript-expr.Types, \
4 // RUN:   value: '::std::basic_string;::std::basic_string_view;MyVector'}]}" --
5 
6 namespace std {
7 
8 template <class T>
9 class basic_string {
10  public:
11    using size_type = unsigned;
12    using value_type = T;
13    using reference = value_type&;
14    using const_reference = const value_type&;
15 
16    reference operator[](size_type);
17    const_reference operator[](size_type) const;
18    T* data();
19    const T* data() const;
20 };
21 
22 using string = basic_string<char>;
23 
24 template <class T>
25 class basic_string_view {
26  public:
27   using size_type = unsigned;
28   using const_reference = const T&;
29   using const_pointer = const T*;
30 
31   constexpr const_reference operator[](size_type) const;
32   constexpr const_pointer data() const noexcept;
33 };
34 
35 using string_view = basic_string_view<char>;
36 
37 }
38 
39 template <class T>
40 class MyVector {
41  public:
42   using size_type = unsigned;
43   using const_reference = const T&;
44   using const_pointer = const T*;
45 
46   const_reference operator[](size_type) const;
47   const T* data() const noexcept;
48 };
49 
50 #define DO(x) do { x; } while (false)
51 #define ACCESS(x) (x)
52 #define GET(x, i) (x).data()[i]
53 
54 template <class T>
55 class Foo {
56  public:
bar(int i)57   char bar(int i) {
58     return x.data()[i];
59   }
60  private:
61   T x;
62 };
63 
f(int i)64 void f(int i) {
65   MyVector<int> v;
66   int x = v.data()[i];
67   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: accessing an element of the container does not require a call to 'data()'; did you mean to use 'operator[]'? [readability-simplify-subscript-expr]
68   // CHECK-FIXES: int x = v[i];
69 
70   std::string s;
71   char c1 = s.data()[i];
72   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: accessing an element
73   // CHECK-FIXES: char c1 = s[i];
74 
75   std::string_view sv;
76   char c2 = sv.data()[i];
77   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: accessing an element
78   // CHECK-FIXES: char c2 = sv[i];
79 
80   std::string* ps = &s;
81   char c3 = ps->data()[i];
82   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: accessing an element
83   // CHECK-FIXES: char c3 = (*ps)[i];
84 
85   char c4 = (*ps).data()[i];
86   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: accessing an element
87   // CHECK-FIXES: char c4 = (*ps)[i];
88 
89   DO(char c5 = s.data()[i]);
90   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: accessing an element
91   // CHECK-FIXES: DO(char c5 = s[i]);
92 
93   char c6 = ACCESS(s).data()[i];
94   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: accessing an element
95   // CHECK-FIXES: char c6 = ACCESS(s)[i];
96 
97   char c7 = ACCESS(s.data())[i];
98   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
99   // CHECK-FIXES: char c7 = ACCESS(s)[i];
100 
101   char c8 = ACCESS(s.data()[i]);
102   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
103   // CHECK-FIXES: char c8 = ACCESS(s[i]);
104 
105   char c9 = GET(s, i);
106 
107   char c10 = Foo<std::string>{}.bar(i);
108 }
109