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 26 namespace irrelevant_constructors { 27 void non_two_param_constructors() { 28 class Array { 29 } a; 30 std::span<int> S; // no warn 31 std::span<int> S1{}; // no warn 32 std::span<int> S2{std::move(a)}; // no warn 33 std::span<int> S3{S2}; // no warn 34 } 35 } // irrelevant_constructors 36 37 namespace construct_wt_ptr_size { 38 std::span<int> warnVarInit(int *p) { 39 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}} 40 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}} 41 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}} 42 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}} 43 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}} 44 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}} 45 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}} 46 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}} 47 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}} 48 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}} 49 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}} 50 51 #define Ten 10 52 53 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}} 54 55 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}} 56 } 57 58 auto X = warnVarInit(p); // function return is fine 59 return S; 60 } 61 62 template<typename T> 63 void foo(const T &, const T &&, T); 64 65 std::span<int> warnTemp(int *p) { 66 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}} 67 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}} 68 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}} 69 70 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}} 71 72 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}} 73 } 74 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}} 75 } 76 77 void notWarnSafeCases(unsigned n, int *p) { 78 int X; 79 unsigned Y = 10; 80 std::span<int> S = std::span{&X, 1}; // no-warning 81 int Arr[10]; 82 typedef int TenInts_t[10]; 83 TenInts_t Arr2; 84 85 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}} 86 S = std::span{new int[10], 10}; // no-warning 87 S = std::span{new int[n], n}; // no-warning 88 S = std::span{new int, 1}; // no-warning 89 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}} 90 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}} 91 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}} 92 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 93 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 94 S = std::span{Arr, 10}; // no-warning 95 S = std::span{Arr2, 10}; // no-warning 96 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 97 S = std::span{p, 0}; // no-warning 98 } 99 } // namespace construct_wt_ptr_size 100 101 namespace construct_wt_begin_end { 102 class It {}; 103 104 std::span<int> warnVarInit(It &First, It &Last) { 105 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}} 106 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}} 107 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}} 108 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}} 109 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}} 110 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}} 111 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}} 112 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}} 113 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}} 114 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}} 115 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}} 116 117 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}} 118 } 119 120 auto X = warnVarInit(First, Last); // function return is fine 121 return S; 122 } 123 124 template<typename T> 125 void foo(const T &, const T &&, T); 126 127 std::span<int> warnTemp(It &First, It &Last) { 128 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}} 129 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}} 130 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 132 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}} 133 134 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}} 135 } 136 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}} 137 } 138 } // namespace construct_wt_begin_end 139 140 namespace test_flag { 141 void f(int *p) { 142 #pragma clang diagnostic push 143 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // this flag turns off every unsafe-buffer warning 144 std::span<int> S{p, 10}; // no-warning 145 p++; // no-warning 146 #pragma clang diagnostic pop 147 148 #pragma clang diagnostic push 149 #pragma clang diagnostic warning "-Wunsafe-buffer-usage" 150 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" 151 // turn on all unsafe-buffer warnings except for the ones under `-Wunsafe-buffer-usage-in-container` 152 std::span<int> S2{p, 10}; // no-warning 153 154 p++; // expected-warning{{unsafe pointer arithmetic}}\ 155 expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} 156 #pragma clang diagnostic pop 157 158 } 159 } //namespace test_flag 160 161 struct HoldsStdSpanAndInitializedInCtor { 162 char* Ptr; 163 unsigned Size; 164 std::span<char> Span{Ptr, Size}; // no-warning (this code is unreachable) 165 166 HoldsStdSpanAndInitializedInCtor(char* P, unsigned S) 167 : 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}} 168 {} 169 }; 170 171 struct HoldsStdSpanAndNotInitializedInCtor { 172 char* Ptr; 173 unsigned Size; 174 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}} 175 176 HoldsStdSpanAndNotInitializedInCtor(char* P, unsigned S) 177 : Ptr(P), Size(S) 178 {} 179 }; 180