brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.9 KiB · 1e78555 Raw
295 lines · cpp
1// RUN: %clang_cc1 -std=c++20  -Wno-all  -Wunsafe-buffer-usage-in-container -verify %s2 3typedef unsigned int size_t;4 5namespace std {6  template <class T> class span {7  public:8    constexpr span(T *, unsigned){}9 10    template<class Begin, class End>11    constexpr span(Begin first, End last){}12 13    T * data();14 15    constexpr span() {};16 17    constexpr span(const std::span<T> &span) {};18 19    template<class R>20    constexpr span(R && range){};21 22    T* begin() noexcept;23    T* end() noexcept;24  };25 26 27  template< class T >28  T&& move( T&& t ) noexcept;29 30  template <class _Tp>31  _Tp* addressof(_Tp& __x) {32    return &__x;33  }34 35  template <typename T, size_t N>36  struct array {37    T* begin() noexcept;38    const T* begin() const noexcept;39    T* end() noexcept;40    const T* end() const noexcept;41    size_t size() const noexcept;42    T * data() const noexcept;43    T& operator[](size_t n);44  };45 46  template<class T>47  class initializer_list {48  public:49    size_t size() const noexcept;50    const T* begin() const noexcept;51    const T* end() const noexcept;52    T * data() const noexcept;53  };54 55  template<typename T>56  struct basic_string {57    T *c_str() const noexcept;58    T *data()  const noexcept;59    unsigned size();60    const T* begin() const noexcept;61    const T* end() const noexcept;62  };63 64  typedef basic_string<char> string;65  typedef basic_string<wchar_t> wstring;66}67 68namespace irrelevant_constructors {69  void non_two_param_constructors() {70    class Array {71    } a;72    std::span<int> S;      // no warn73    std::span<int> S1{};   // no warn74    std::span<int> S2{std::move(a)};  // no warn75    std::span<int> S3{S2};  // no warn76  }77} // irrelevant_constructors78 79namespace construct_wt_ptr_size {80  std::span<int> warnVarInit(int *p) {81    std::span<int> S{p, 10};                     // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}82    std::span<int> S1(p, 10);                    // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}83    std::span<int> S2 = std::span{p, 10};        // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}84    std::span<int> S3 = std::span(p, 10);        // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}85    std::span<int> S4 = std::span<int>{p, 10};   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}86    std::span<int> S5 = std::span<int>(p, 10);   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}87    std::span<int> S6 = {p, 10};                 // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}88    auto S7 = std::span<int>{p, 10};             // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}89    auto S8 = std::span<int>(p, 10);             // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}90    const auto &S9 = std::span<int>{p, 10};      // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}91    auto &&S10 = std::span<int>(p, 10);          // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}92 93#define Ten 1094 95    std::span S11 = std::span<int>{p, Ten};      // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}96 97    if (auto X = std::span<int>{p, Ten}; S10.data()) { // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}98    }99 100    auto X = warnVarInit(p); // function return is fine101    return S;102  }103 104  template<typename T>105  void foo(const T &, const T &&, T);106 107  std::span<int> warnTemp(int *p) {108    foo(std::span<int>{p, 10},                       // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}109	std::move(std::span<int>{p, 10}),            // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}110	std::span<int>{p, 10});                      // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}111 112    std::span<int> Arr[1] = {std::span<int>{p, 10}}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}113 114    if (std::span<int>{p, 10}.data()) {              // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}115    }116    return std::span<int>{p, 10};                    // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}117  }118 119  // addressof method defined outside std namespace.120  template <class _Tp>121  _Tp* addressof(_Tp& __x) {122    return &__x;123  }124 125  void notWarnSafeCases(unsigned n, int *p) {126    int X;127    unsigned Y = 10;128    std::span<int> S = std::span{&X, 1}; // no-warning129    S = std::span{std::addressof(X), 1}; // no-warning130    int Arr[10];131    typedef int TenInts_t[10];132    TenInts_t Arr2;133 134    S = std::span{&X, 2};                // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}135    S = std::span{std::addressof(X), 2}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}136    // Warn when a non std method also named addressof137    S = std::span{addressof(X), 1}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}138 139    S = std::span{new int[10], 10};      // no-warning140    S = std::span{new int[n], n};        // no-warning141    S = std::span{new int, 1};           // no-warning142    S = std::span{new int, X};           // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}143    S = std::span{new int[n--], n--};    // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}144    S = std::span{new int[10], 11};      // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}145    S = std::span{new int[10], 9};       // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}  // not smart enough to tell its safe146    S = std::span{new int[10], Y};       // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}  // not smart enough to tell its safe147    S = std::span{Arr, 10};              // no-warning148    S = std::span{Arr2, 10};             // no-warning149    S = std::span{Arr, Y};               // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}  // not smart enough to tell its safe150    S = std::span{p, 0};                 // no-warning151  }152} // namespace construct_wt_ptr_size153 154namespace construct_wt_begin_end {155  class It {};156 157  std::span<int> warnVarInit(It &First, It &Last) {158    std::span<int> S{First, Last};                     // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}159    std::span<int> S1(First, Last);                    // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}160    std::span<int> S2 = std::span<int>{First, Last};   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}161    std::span<int> S3 = std::span<int>(First, Last);   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}162    std::span<int> S4 = std::span<int>{First, Last};   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}163    std::span<int> S5 = std::span<int>(First, Last);   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}164    std::span<int> S6 = {First, Last};                 // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}165    auto S7 = std::span<int>{First, Last};             // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}166    auto S8 = std::span<int>(First, Last);             // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}167    const auto &S9 = std::span<int>{First, Last};      // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}168    auto &&S10 = std::span<int>(First, Last);          // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}169 170    if (auto X = std::span<int>{First, Last}; S10.data()) { // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}171    }172 173    auto X = warnVarInit(First, Last); // function return is fine174    return S;175  }176 177  template<typename T>178  void foo(const T &, const T &&, T);179 180  std::span<int> warnTemp(It &First, It &Last) {181    foo(std::span<int>{First, Last},                       // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}182	std::move(std::span<int>{First, Last}),            // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}183	std::span<int>{First, Last});                      // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}184 185    std::span<int> Arr[1] = {std::span<int>{First, Last}}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}186 187    if (std::span<int>{First, Last}.data()) {              // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}188    }189    return std::span<int>{First, Last};                    // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}190  }191} // namespace construct_wt_begin_end192 193namespace test_alloc_size_attr {194  void * my_alloc(unsigned size) __attribute__((alloc_size(1)));195  void * my_alloc2(unsigned count, unsigned size) __attribute__((alloc_size(1,2)));196 197  void safe(int x, unsigned y) {198    std::span<char>{(char *)my_alloc(10), 10};199    std::span<char>{(char *)my_alloc(x), x};200    std::span<char>{(char *)my_alloc(x * y), x * y};201    std::span<char>{(char *)my_alloc(x * y), y * x};202    std::span<char>{(char *)my_alloc(x * y + x), x * y + x};203    std::span<char>{(char *)my_alloc(x * y + x), x + y * x};204 205    std::span<char>{(char *)my_alloc2(x, y), x * y};206    std::span<char>{(char *)my_alloc2(x, y), y * x};207    //foo(std::span<char>{(char *)my_alloc2(x, sizeof(char)), x}); // lets not worry about this case for now208    std::span<char>{(char *)my_alloc2(x, sizeof(char)), x * sizeof(char)};209    //foo(std::span<char>{(char *)my_alloc2(10, sizeof(char)), 10});210    std::span<char>{(char *)my_alloc2(10, sizeof(char)), 10 * sizeof(char)};211  }212 213  void unsafe(int x, int y) {214    std::span<char>{(char *)my_alloc(10), 11};       // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}215    std::span<char>{(char *)my_alloc(x * y), x + y}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}216    std::span<int>{(int *)my_alloc(x), x};           // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}217    std::span<char>{(char *)my_alloc2(x, y), x + y}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}218  }219 220  void unsupport(int x, int y, int z) {221    // Casting to `T*` where sizeof(T) > 1 is not supported yet:222    std::span<int>{(int *)my_alloc2(x, y),  x * y};  // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}223    std::span<long>{(long *)my_alloc(10 * sizeof(long)), 10}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}224    std::span<long>{(long *)my_alloc2(x, sizeof(long)), x};   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}225    std::span<long>{(long *)my_alloc2(x, sizeof(long)), x};   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}226    // The expression is too complicated:227    std::span<char>{(char *)my_alloc(x + y + z), z + y + x};   // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}228  }229}230 231namespace test_flag {232  void f(int *p) {233#pragma clang diagnostic push234#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"  // this flag turns off every unsafe-buffer warning235    std::span<int> S{p, 10};   // no-warning236    p++;                       // no-warning237#pragma clang diagnostic pop238 239#pragma clang diagnostic push240#pragma clang diagnostic warning "-Wunsafe-buffer-usage"241#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"242    // turn on all unsafe-buffer warnings except for the ones under `-Wunsafe-buffer-usage-in-container`243    std::span<int> S2{p, 10};   // no-warning244 245    p++; // expected-warning{{unsafe pointer arithmetic}}\246	    expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}247#pragma clang diagnostic pop248 249  }250} //namespace test_flag251 252struct HoldsStdSpanAndInitializedInCtor {253  char* Ptr;254  unsigned Size;255  std::span<char> Span{Ptr, Size};  // no-warning (this code is unreachable)256 257  HoldsStdSpanAndInitializedInCtor(char* P, unsigned S)258      : Span(P, S)  // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}259  {}260};261 262struct HoldsStdSpanAndNotInitializedInCtor {263  char* Ptr;264  unsigned Size;265  std::span<char> Span{Ptr, Size}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}266 267  HoldsStdSpanAndNotInitializedInCtor(char* P, unsigned S)268      : Ptr(P), Size(S)269  {}270};271 272namespace test_begin_end {273  struct Object {274    int * begin();275    int * end();276  };277  void safe_cases(std::span<int> Sp, std::array<int, 10> Arr, std::string Str, std::initializer_list<Object> Il) {278    std::span<int>{Sp.begin(), Sp.end()};279    std::span<int>{Arr.begin(), Arr.end()};280    std::span<char>{Str.begin(), Str.end()};281    std::span<Object>{Il.begin(), Il.end()};282  }283 284  void unsafe_cases(std::span<int> Sp, std::array<int, 10> Arr, std::string Str, std::initializer_list<Object> Il,285		    Object Obj) {286    std::span<int>{Obj.begin(), Obj.end()}; // expected-warning {{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}287    std::span<int>{Sp.end(), Sp.begin()};   // expected-warning {{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}288    std::span<int>{Sp.begin(), Arr.end()};   // expected-warning {{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}289  }290 291  void unsupport_cases(std::array<Object, 10> Arr) {292    std::span<int>{Arr[0].begin(), Arr[0].end()}; // expected-warning {{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}293  }294}295