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; 240dcb0acfSMalavika Samak 250dcb0acfSMalavika Samak template <class _Tp> 260dcb0acfSMalavika Samak _Tp* addressof(_Tp& __x) { 270dcb0acfSMalavika Samak return &__x; 280dcb0acfSMalavika Samak } 290dcb0acfSMalavika Samak 309816863dSZiqing Luo } 319816863dSZiqing Luo 329816863dSZiqing Luo namespace irrelevant_constructors { 339816863dSZiqing Luo void non_two_param_constructors() { 349816863dSZiqing Luo class Array { 359816863dSZiqing Luo } a; 369816863dSZiqing Luo std::span<int> S; // no warn 379816863dSZiqing Luo std::span<int> S1{}; // no warn 389816863dSZiqing Luo std::span<int> S2{std::move(a)}; // no warn 399816863dSZiqing Luo std::span<int> S3{S2}; // no warn 409816863dSZiqing Luo } 419816863dSZiqing Luo } // irrelevant_constructors 429816863dSZiqing Luo 439816863dSZiqing Luo namespace construct_wt_ptr_size { 449816863dSZiqing Luo std::span<int> warnVarInit(int *p) { 459816863dSZiqing 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}} 469816863dSZiqing 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}} 479816863dSZiqing 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}} 489816863dSZiqing 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}} 499816863dSZiqing 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}} 509816863dSZiqing 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}} 519816863dSZiqing 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}} 529816863dSZiqing 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}} 539816863dSZiqing 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}} 549816863dSZiqing 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}} 559816863dSZiqing 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}} 569816863dSZiqing Luo 579816863dSZiqing Luo #define Ten 10 589816863dSZiqing Luo 599816863dSZiqing 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}} 609816863dSZiqing Luo 619816863dSZiqing 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}} 629816863dSZiqing Luo } 639816863dSZiqing Luo 649816863dSZiqing Luo auto X = warnVarInit(p); // function return is fine 659816863dSZiqing Luo return S; 669816863dSZiqing Luo } 679816863dSZiqing Luo 689816863dSZiqing Luo template<typename T> 699816863dSZiqing Luo void foo(const T &, const T &&, T); 709816863dSZiqing Luo 719816863dSZiqing Luo std::span<int> warnTemp(int *p) { 729816863dSZiqing 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}} 739816863dSZiqing 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}} 749816863dSZiqing 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}} 759816863dSZiqing Luo 769816863dSZiqing 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}} 779816863dSZiqing Luo 789816863dSZiqing 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}} 799816863dSZiqing Luo } 809816863dSZiqing 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}} 819816863dSZiqing Luo } 829816863dSZiqing Luo 830dcb0acfSMalavika Samak // addressof method defined outside std namespace. 840dcb0acfSMalavika Samak template <class _Tp> 850dcb0acfSMalavika Samak _Tp* addressof(_Tp& __x) { 860dcb0acfSMalavika Samak return &__x; 870dcb0acfSMalavika Samak } 880dcb0acfSMalavika Samak 899816863dSZiqing Luo void notWarnSafeCases(unsigned n, int *p) { 909816863dSZiqing Luo int X; 919816863dSZiqing Luo unsigned Y = 10; 929816863dSZiqing Luo std::span<int> S = std::span{&X, 1}; // no-warning 930dcb0acfSMalavika Samak S = std::span{std::addressof(X), 1}; // no-warning 949816863dSZiqing Luo int Arr[10]; 959aa3b53aSZiqing Luo typedef int TenInts_t[10]; 969aa3b53aSZiqing Luo TenInts_t Arr2; 979816863dSZiqing Luo 989816863dSZiqing 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}} 990dcb0acfSMalavika Samak 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}} 1000dcb0acfSMalavika Samak // Warn when a non std method also named addressof 1010dcb0acfSMalavika Samak 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}} 1020dcb0acfSMalavika Samak 1039816863dSZiqing Luo S = std::span{new int[10], 10}; // no-warning 1049816863dSZiqing Luo S = std::span{new int[n], n}; // no-warning 1059816863dSZiqing Luo S = std::span{new int, 1}; // no-warning 1069816863dSZiqing 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}} 1079816863dSZiqing 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}} 1089816863dSZiqing 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}} 1099816863dSZiqing 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 1109816863dSZiqing 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 1119816863dSZiqing Luo S = std::span{Arr, 10}; // no-warning 1129aa3b53aSZiqing Luo S = std::span{Arr2, 10}; // no-warning 1139816863dSZiqing 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 1149816863dSZiqing Luo S = std::span{p, 0}; // no-warning 1159816863dSZiqing Luo } 1169816863dSZiqing Luo } // namespace construct_wt_ptr_size 1179816863dSZiqing Luo 1189816863dSZiqing Luo namespace construct_wt_begin_end { 1199816863dSZiqing Luo class It {}; 1209816863dSZiqing Luo 1219816863dSZiqing Luo std::span<int> warnVarInit(It &First, It &Last) { 1229816863dSZiqing 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}} 1239816863dSZiqing 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}} 1249816863dSZiqing 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}} 1259816863dSZiqing 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}} 1269816863dSZiqing 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}} 1279816863dSZiqing 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}} 1289816863dSZiqing 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}} 1299816863dSZiqing 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}} 1309816863dSZiqing 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}} 1319816863dSZiqing 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}} 1329816863dSZiqing 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}} 1339816863dSZiqing Luo 1349816863dSZiqing 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}} 1359816863dSZiqing Luo } 1369816863dSZiqing Luo 1379816863dSZiqing Luo auto X = warnVarInit(First, Last); // function return is fine 1389816863dSZiqing Luo return S; 1399816863dSZiqing Luo } 1409816863dSZiqing Luo 1419816863dSZiqing Luo template<typename T> 1429816863dSZiqing Luo void foo(const T &, const T &&, T); 1439816863dSZiqing Luo 1449816863dSZiqing Luo std::span<int> warnTemp(It &First, It &Last) { 1459816863dSZiqing 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}} 1469816863dSZiqing 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}} 1479816863dSZiqing 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}} 1489816863dSZiqing Luo 1499816863dSZiqing 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}} 1509816863dSZiqing Luo 1519816863dSZiqing 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}} 1529816863dSZiqing Luo } 1539816863dSZiqing 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}} 1549816863dSZiqing Luo } 1559816863dSZiqing Luo } // namespace construct_wt_begin_end 1569816863dSZiqing Luo 1579816863dSZiqing Luo namespace test_flag { 1589816863dSZiqing Luo void f(int *p) { 1599816863dSZiqing Luo #pragma clang diagnostic push 1609816863dSZiqing Luo #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // this flag turns off every unsafe-buffer warning 1619816863dSZiqing Luo std::span<int> S{p, 10}; // no-warning 1629816863dSZiqing Luo p++; // no-warning 1639816863dSZiqing Luo #pragma clang diagnostic pop 1649816863dSZiqing Luo 1659816863dSZiqing Luo #pragma clang diagnostic push 1669816863dSZiqing Luo #pragma clang diagnostic warning "-Wunsafe-buffer-usage" 1679816863dSZiqing Luo #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" 1689816863dSZiqing Luo // turn on all unsafe-buffer warnings except for the ones under `-Wunsafe-buffer-usage-in-container` 1699816863dSZiqing Luo std::span<int> S2{p, 10}; // no-warning 1709816863dSZiqing Luo 1719816863dSZiqing Luo p++; // expected-warning{{unsafe pointer arithmetic}}\ 1729816863dSZiqing Luo expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} 1739816863dSZiqing Luo #pragma clang diagnostic pop 1749816863dSZiqing Luo 1759816863dSZiqing Luo } 1769816863dSZiqing Luo } //namespace test_flag 177*c60b055dSZequan Wu 178*c60b055dSZequan Wu struct HoldsStdSpanAndInitializedInCtor { 179*c60b055dSZequan Wu char* Ptr; 180*c60b055dSZequan Wu unsigned Size; 181*c60b055dSZequan Wu std::span<char> Span{Ptr, Size}; // no-warning (this code is unreachable) 182*c60b055dSZequan Wu 183*c60b055dSZequan Wu HoldsStdSpanAndInitializedInCtor(char* P, unsigned S) 184*c60b055dSZequan Wu : 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*c60b055dSZequan Wu {} 186*c60b055dSZequan Wu }; 187*c60b055dSZequan Wu 188*c60b055dSZequan Wu struct HoldsStdSpanAndNotInitializedInCtor { 189*c60b055dSZequan Wu char* Ptr; 190*c60b055dSZequan Wu unsigned Size; 191*c60b055dSZequan Wu 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*c60b055dSZequan Wu 193*c60b055dSZequan Wu HoldsStdSpanAndNotInitializedInCtor(char* P, unsigned S) 194*c60b055dSZequan Wu : Ptr(P), Size(S) 195*c60b055dSZequan Wu {} 196*c60b055dSZequan Wu }; 197