19816863dSZiqing Luo // RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage-in-container -verify %s 29816863dSZiqing Luo 39816863dSZiqing Luo namespace std { 49816863dSZiqing Luo template <class T> class span { 59816863dSZiqing Luo public: 69816863dSZiqing Luo constexpr span(T *, unsigned){} 79816863dSZiqing Luo 89816863dSZiqing Luo template<class Begin, class End> 99816863dSZiqing Luo constexpr span(Begin first, End last){} 109816863dSZiqing Luo 119816863dSZiqing Luo T * data(); 129816863dSZiqing Luo 139816863dSZiqing Luo constexpr span() {}; 149816863dSZiqing Luo 159816863dSZiqing Luo constexpr span(const std::span<T> &span) {}; 169816863dSZiqing Luo 179816863dSZiqing Luo template<class R> 189816863dSZiqing Luo constexpr span(R && range){}; 199816863dSZiqing Luo }; 209816863dSZiqing Luo 219816863dSZiqing Luo 229816863dSZiqing Luo template< class T > 239816863dSZiqing Luo T&& move( T&& t ) noexcept; 249816863dSZiqing Luo } 259816863dSZiqing Luo 269816863dSZiqing Luo namespace irrelevant_constructors { 279816863dSZiqing Luo void non_two_param_constructors() { 289816863dSZiqing Luo class Array { 299816863dSZiqing Luo } a; 309816863dSZiqing Luo std::span<int> S; // no warn 319816863dSZiqing Luo std::span<int> S1{}; // no warn 329816863dSZiqing Luo std::span<int> S2{std::move(a)}; // no warn 339816863dSZiqing Luo std::span<int> S3{S2}; // no warn 349816863dSZiqing Luo } 359816863dSZiqing Luo } // irrelevant_constructors 369816863dSZiqing Luo 379816863dSZiqing Luo namespace construct_wt_ptr_size { 389816863dSZiqing Luo std::span<int> warnVarInit(int *p) { 399816863dSZiqing Luo 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}} 409816863dSZiqing Luo 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}} 419816863dSZiqing Luo 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}} 429816863dSZiqing Luo 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}} 439816863dSZiqing Luo 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}} 449816863dSZiqing Luo 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}} 459816863dSZiqing Luo 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}} 469816863dSZiqing Luo 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}} 479816863dSZiqing Luo 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}} 489816863dSZiqing Luo 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}} 499816863dSZiqing Luo 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}} 509816863dSZiqing Luo 519816863dSZiqing Luo #define Ten 10 529816863dSZiqing Luo 539816863dSZiqing Luo 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}} 549816863dSZiqing Luo 559816863dSZiqing Luo 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}} 569816863dSZiqing Luo } 579816863dSZiqing Luo 589816863dSZiqing Luo auto X = warnVarInit(p); // function return is fine 599816863dSZiqing Luo return S; 609816863dSZiqing Luo } 619816863dSZiqing Luo 629816863dSZiqing Luo template<typename T> 639816863dSZiqing Luo void foo(const T &, const T &&, T); 649816863dSZiqing Luo 659816863dSZiqing Luo std::span<int> warnTemp(int *p) { 669816863dSZiqing Luo 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}} 679816863dSZiqing Luo 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}} 689816863dSZiqing Luo 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}} 699816863dSZiqing Luo 709816863dSZiqing Luo 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}} 719816863dSZiqing Luo 729816863dSZiqing Luo 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}} 739816863dSZiqing Luo } 749816863dSZiqing Luo 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}} 759816863dSZiqing Luo } 769816863dSZiqing Luo 779816863dSZiqing Luo void notWarnSafeCases(unsigned n, int *p) { 789816863dSZiqing Luo int X; 799816863dSZiqing Luo unsigned Y = 10; 809816863dSZiqing Luo std::span<int> S = std::span{&X, 1}; // no-warning 819816863dSZiqing Luo int Arr[10]; 82*9aa3b53aSZiqing Luo typedef int TenInts_t[10]; 83*9aa3b53aSZiqing Luo TenInts_t Arr2; 849816863dSZiqing Luo 859816863dSZiqing Luo 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}} 869816863dSZiqing Luo S = std::span{new int[10], 10}; // no-warning 879816863dSZiqing Luo S = std::span{new int[n], n}; // no-warning 889816863dSZiqing Luo S = std::span{new int, 1}; // no-warning 899816863dSZiqing Luo 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}} 909816863dSZiqing Luo 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}} 919816863dSZiqing Luo 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}} 929816863dSZiqing Luo 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 939816863dSZiqing Luo 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 949816863dSZiqing Luo S = std::span{Arr, 10}; // no-warning 95*9aa3b53aSZiqing Luo S = std::span{Arr2, 10}; // no-warning 969816863dSZiqing Luo 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 979816863dSZiqing Luo S = std::span{p, 0}; // no-warning 989816863dSZiqing Luo } 999816863dSZiqing Luo } // namespace construct_wt_ptr_size 1009816863dSZiqing Luo 1019816863dSZiqing Luo namespace construct_wt_begin_end { 1029816863dSZiqing Luo class It {}; 1039816863dSZiqing Luo 1049816863dSZiqing Luo std::span<int> warnVarInit(It &First, It &Last) { 1059816863dSZiqing Luo 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}} 1069816863dSZiqing Luo 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}} 1079816863dSZiqing Luo 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}} 1089816863dSZiqing Luo 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}} 1099816863dSZiqing Luo 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}} 1109816863dSZiqing Luo 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}} 1119816863dSZiqing Luo 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}} 1129816863dSZiqing Luo 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}} 1139816863dSZiqing Luo 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}} 1149816863dSZiqing Luo 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}} 1159816863dSZiqing Luo 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}} 1169816863dSZiqing Luo 1179816863dSZiqing Luo 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}} 1189816863dSZiqing Luo } 1199816863dSZiqing Luo 1209816863dSZiqing Luo auto X = warnVarInit(First, Last); // function return is fine 1219816863dSZiqing Luo return S; 1229816863dSZiqing Luo } 1239816863dSZiqing Luo 1249816863dSZiqing Luo template<typename T> 1259816863dSZiqing Luo void foo(const T &, const T &&, T); 1269816863dSZiqing Luo 1279816863dSZiqing Luo std::span<int> warnTemp(It &First, It &Last) { 1289816863dSZiqing Luo 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}} 1299816863dSZiqing Luo 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}} 1309816863dSZiqing Luo 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}} 1319816863dSZiqing Luo 1329816863dSZiqing Luo 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}} 1339816863dSZiqing Luo 1349816863dSZiqing Luo 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}} 1359816863dSZiqing Luo } 1369816863dSZiqing Luo 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}} 1379816863dSZiqing Luo } 1389816863dSZiqing Luo } // namespace construct_wt_begin_end 1399816863dSZiqing Luo 1409816863dSZiqing Luo namespace test_flag { 1419816863dSZiqing Luo void f(int *p) { 1429816863dSZiqing Luo #pragma clang diagnostic push 1439816863dSZiqing Luo #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // this flag turns off every unsafe-buffer warning 1449816863dSZiqing Luo std::span<int> S{p, 10}; // no-warning 1459816863dSZiqing Luo p++; // no-warning 1469816863dSZiqing Luo #pragma clang diagnostic pop 1479816863dSZiqing Luo 1489816863dSZiqing Luo #pragma clang diagnostic push 1499816863dSZiqing Luo #pragma clang diagnostic warning "-Wunsafe-buffer-usage" 1509816863dSZiqing Luo #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" 1519816863dSZiqing Luo // turn on all unsafe-buffer warnings except for the ones under `-Wunsafe-buffer-usage-in-container` 1529816863dSZiqing Luo std::span<int> S2{p, 10}; // no-warning 1539816863dSZiqing Luo 1549816863dSZiqing Luo p++; // expected-warning{{unsafe pointer arithmetic}}\ 1559816863dSZiqing Luo expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} 1569816863dSZiqing Luo #pragma clang diagnostic pop 1579816863dSZiqing Luo 1589816863dSZiqing Luo } 1599816863dSZiqing Luo } //namespace test_flag 160