1 // RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage-in-container -verify %s 2 3 namespace std { 4 template <class T> class span { 5 public: 6 constexpr span(T *, unsigned){} 7 8 template<class Begin, class End> 9 constexpr span(Begin first, End last){} 10 11 T * data(); 12 13 constexpr span() {}; 14 15 constexpr span(const std::span<T> &span) {}; 16 17 template<class R> 18 constexpr span(R && range){}; 19 }; 20 21 22 template< class T > 23 T&& move( T&& t ) noexcept; 24 25 template <class _Tp> 26 _Tp* addressof(_Tp& __x) { 27 return &__x; 28 } 29 30 } 31 32 namespace irrelevant_constructors { 33 void non_two_param_constructors() { 34 class Array { 35 } a; 36 std::span<int> S; // no warn 37 std::span<int> S1{}; // no warn 38 std::span<int> S2{std::move(a)}; // no warn 39 std::span<int> S3{S2}; // no warn 40 } 41 } // irrelevant_constructors 42 43 namespace construct_wt_ptr_size { 44 std::span<int> warnVarInit(int *p) { 45 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}} 46 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}} 47 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}} 48 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}} 49 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}} 50 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}} 51 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}} 52 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}} 53 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}} 54 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}} 55 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}} 56 57 #define Ten 10 58 59 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}} 60 61 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}} 62 } 63 64 auto X = warnVarInit(p); // function return is fine 65 return S; 66 } 67 68 template<typename T> 69 void foo(const T &, const T &&, T); 70 71 std::span<int> warnTemp(int *p) { 72 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}} 73 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}} 74 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}} 75 76 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}} 77 78 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}} 79 } 80 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}} 81 } 82 83 // addressof method defined outside std namespace. 84 template <class _Tp> 85 _Tp* addressof(_Tp& __x) { 86 return &__x; 87 } 88 89 void notWarnSafeCases(unsigned n, int *p) { 90 int X; 91 unsigned Y = 10; 92 std::span<int> S = std::span{&X, 1}; // no-warning 93 S = std::span{std::addressof(X), 1}; // no-warning 94 int Arr[10]; 95 typedef int TenInts_t[10]; 96 TenInts_t Arr2; 97 98 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}} 99 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}} 100 // Warn when a non std method also named addressof 101 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}} 102 103 S = std::span{new int[10], 10}; // no-warning 104 S = std::span{new int[n], n}; // no-warning 105 S = std::span{new int, 1}; // no-warning 106 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}} 107 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}} 108 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}} 109 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 safe 110 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 safe 111 S = std::span{Arr, 10}; // no-warning 112 S = std::span{Arr2, 10}; // no-warning 113 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 safe 114 S = std::span{p, 0}; // no-warning 115 } 116 } // namespace construct_wt_ptr_size 117 118 namespace construct_wt_begin_end { 119 class It {}; 120 121 std::span<int> warnVarInit(It &First, It &Last) { 122 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}} 123 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}} 124 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}} 125 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}} 126 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}} 127 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}} 128 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}} 129 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}} 130 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}} 131 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}} 132 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}} 133 134 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}} 135 } 136 137 auto X = warnVarInit(First, Last); // function return is fine 138 return S; 139 } 140 141 template<typename T> 142 void foo(const T &, const T &&, T); 143 144 std::span<int> warnTemp(It &First, It &Last) { 145 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}} 146 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}} 147 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}} 148 149 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}} 150 151 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}} 152 } 153 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}} 154 } 155 } // namespace construct_wt_begin_end 156 157 namespace test_flag { 158 void f(int *p) { 159 #pragma clang diagnostic push 160 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // this flag turns off every unsafe-buffer warning 161 std::span<int> S{p, 10}; // no-warning 162 p++; // no-warning 163 #pragma clang diagnostic pop 164 165 #pragma clang diagnostic push 166 #pragma clang diagnostic warning "-Wunsafe-buffer-usage" 167 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" 168 // turn on all unsafe-buffer warnings except for the ones under `-Wunsafe-buffer-usage-in-container` 169 std::span<int> S2{p, 10}; // no-warning 170 171 p++; // expected-warning{{unsafe pointer arithmetic}}\ 172 expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} 173 #pragma clang diagnostic pop 174 175 } 176 } //namespace test_flag 177 178 struct HoldsStdSpanAndInitializedInCtor { 179 char* Ptr; 180 unsigned Size; 181 std::span<char> Span{Ptr, Size}; // no-warning (this code is unreachable) 182 183 HoldsStdSpanAndInitializedInCtor(char* P, unsigned S) 184 : 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}} 185 {} 186 }; 187 188 struct HoldsStdSpanAndNotInitializedInCtor { 189 char* Ptr; 190 unsigned Size; 191 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}} 192 193 HoldsStdSpanAndNotInitializedInCtor(char* P, unsigned S) 194 : Ptr(P), Size(S) 195 {} 196 }; 197