xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-subscript-expr.cpp (revision e8a3ddafe063c970df9c23e803812369abde4c82)
189a1d03eSRichard // RUN: %check_clang_tidy %s readability-simplify-subscript-expr %t \
289a1d03eSRichard // RUN: -config="{CheckOptions: \
3*e8a3ddafSNathan James // RUN: {readability-simplify-subscript-expr.Types: \
4*e8a3ddafSNathan James // RUN:    '::std::basic_string;::std::basic_string_view;MyVector'}}" --
589a1d03eSRichard 
689a1d03eSRichard namespace std {
789a1d03eSRichard 
889a1d03eSRichard template <class T>
989a1d03eSRichard class basic_string {
1089a1d03eSRichard  public:
1189a1d03eSRichard    using size_type = unsigned;
1289a1d03eSRichard    using value_type = T;
1389a1d03eSRichard    using reference = value_type&;
1489a1d03eSRichard    using const_reference = const value_type&;
1589a1d03eSRichard 
1689a1d03eSRichard    reference operator[](size_type);
1789a1d03eSRichard    const_reference operator[](size_type) const;
1889a1d03eSRichard    T* data();
1989a1d03eSRichard    const T* data() const;
2089a1d03eSRichard };
2189a1d03eSRichard 
2289a1d03eSRichard using string = basic_string<char>;
2389a1d03eSRichard 
2489a1d03eSRichard template <class T>
2589a1d03eSRichard class basic_string_view {
2689a1d03eSRichard  public:
2789a1d03eSRichard   using size_type = unsigned;
2889a1d03eSRichard   using const_reference = const T&;
2989a1d03eSRichard   using const_pointer = const T*;
3089a1d03eSRichard 
3189a1d03eSRichard   constexpr const_reference operator[](size_type) const;
3289a1d03eSRichard   constexpr const_pointer data() const noexcept;
3389a1d03eSRichard };
3489a1d03eSRichard 
3589a1d03eSRichard using string_view = basic_string_view<char>;
3689a1d03eSRichard 
3789a1d03eSRichard }
3889a1d03eSRichard 
3989a1d03eSRichard template <class T>
4089a1d03eSRichard class MyVector {
4189a1d03eSRichard  public:
4289a1d03eSRichard   using size_type = unsigned;
4389a1d03eSRichard   using const_reference = const T&;
4489a1d03eSRichard   using const_pointer = const T*;
4589a1d03eSRichard 
4689a1d03eSRichard   const_reference operator[](size_type) const;
4789a1d03eSRichard   const T* data() const noexcept;
4889a1d03eSRichard };
4989a1d03eSRichard 
5089a1d03eSRichard #define DO(x) do { x; } while (false)
5189a1d03eSRichard #define ACCESS(x) (x)
5289a1d03eSRichard #define GET(x, i) (x).data()[i]
5389a1d03eSRichard 
5489a1d03eSRichard template <class T>
5589a1d03eSRichard class Foo {
5689a1d03eSRichard  public:
bar(int i)5789a1d03eSRichard   char bar(int i) {
5889a1d03eSRichard     return x.data()[i];
5989a1d03eSRichard   }
6089a1d03eSRichard  private:
6189a1d03eSRichard   T x;
6289a1d03eSRichard };
6389a1d03eSRichard 
f(int i)6489a1d03eSRichard void f(int i) {
6589a1d03eSRichard   MyVector<int> v;
6689a1d03eSRichard   int x = v.data()[i];
6789a1d03eSRichard   // 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]
6889a1d03eSRichard   // CHECK-FIXES: int x = v[i];
6989a1d03eSRichard 
7089a1d03eSRichard   std::string s;
7189a1d03eSRichard   char c1 = s.data()[i];
7289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: accessing an element
7389a1d03eSRichard   // CHECK-FIXES: char c1 = s[i];
7489a1d03eSRichard 
7589a1d03eSRichard   std::string_view sv;
7689a1d03eSRichard   char c2 = sv.data()[i];
7789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: accessing an element
7889a1d03eSRichard   // CHECK-FIXES: char c2 = sv[i];
7989a1d03eSRichard 
8089a1d03eSRichard   std::string* ps = &s;
8189a1d03eSRichard   char c3 = ps->data()[i];
8289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: accessing an element
8389a1d03eSRichard   // CHECK-FIXES: char c3 = (*ps)[i];
8489a1d03eSRichard 
8589a1d03eSRichard   char c4 = (*ps).data()[i];
8689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: accessing an element
8789a1d03eSRichard   // CHECK-FIXES: char c4 = (*ps)[i];
8889a1d03eSRichard 
8989a1d03eSRichard   DO(char c5 = s.data()[i]);
9089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: accessing an element
9189a1d03eSRichard   // CHECK-FIXES: DO(char c5 = s[i]);
9289a1d03eSRichard 
9389a1d03eSRichard   char c6 = ACCESS(s).data()[i];
9489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: accessing an element
9589a1d03eSRichard   // CHECK-FIXES: char c6 = ACCESS(s)[i];
9689a1d03eSRichard 
9789a1d03eSRichard   char c7 = ACCESS(s.data())[i];
9889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
9989a1d03eSRichard   // CHECK-FIXES: char c7 = ACCESS(s)[i];
10089a1d03eSRichard 
10189a1d03eSRichard   char c8 = ACCESS(s.data()[i]);
10289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: accessing an element
10389a1d03eSRichard   // CHECK-FIXES: char c8 = ACCESS(s[i]);
10489a1d03eSRichard 
10589a1d03eSRichard   char c9 = GET(s, i);
10689a1d03eSRichard 
10789a1d03eSRichard   char c10 = Foo<std::string>{}.bar(i);
10889a1d03eSRichard }
109