// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage-in-container -verify %s namespace std { template class span { public: constexpr span(T *, unsigned){} template constexpr span(Begin first, End last){} T * data(); constexpr span() {}; constexpr span(const std::span &span) {}; template constexpr span(R && range){}; }; template< class T > T&& move( T&& t ) noexcept; template _Tp* addressof(_Tp& __x) { return &__x; } } namespace irrelevant_constructors { void non_two_param_constructors() { class Array { } a; std::span S; // no warn std::span S1{}; // no warn std::span S2{std::move(a)}; // no warn std::span S3{S2}; // no warn } } // irrelevant_constructors namespace construct_wt_ptr_size { std::span warnVarInit(int *p) { std::span 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}} std::span 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}} std::span 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}} std::span 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}} std::span S4 = 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}} std::span S5 = 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}} std::span 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}} auto S7 = 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}} auto S8 = 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}} const auto &S9 = 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}} auto &&S10 = 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}} #define Ten 10 std::span S11 = std::span{p, Ten}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} if (auto X = std::span{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}} } auto X = warnVarInit(p); // function return is fine return S; } template void foo(const T &, const T &&, T); std::span warnTemp(int *p) { foo(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}} std::move(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}} 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}} std::span Arr[1] = {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}} if (std::span{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}} } return 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}} } // addressof method defined outside std namespace. template _Tp* addressof(_Tp& __x) { return &__x; } void notWarnSafeCases(unsigned n, int *p) { int X; unsigned Y = 10; std::span S = std::span{&X, 1}; // no-warning S = std::span{std::addressof(X), 1}; // no-warning int Arr[10]; typedef int TenInts_t[10]; TenInts_t Arr2; 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}} 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}} // Warn when a non std method also named addressof 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}} S = std::span{new int[10], 10}; // no-warning S = std::span{new int[n], n}; // no-warning S = std::span{new int, 1}; // no-warning 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}} 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}} 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}} 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 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 S = std::span{Arr, 10}; // no-warning S = std::span{Arr2, 10}; // no-warning 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 S = std::span{p, 0}; // no-warning } } // namespace construct_wt_ptr_size namespace construct_wt_begin_end { class It {}; std::span warnVarInit(It &First, It &Last) { std::span 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}} std::span 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}} std::span S2 = std::span{First, Last}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} std::span S3 = std::span(First, Last); // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} std::span S4 = std::span{First, Last}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} std::span S5 = std::span(First, Last); // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} std::span 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}} auto S7 = std::span{First, Last}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} auto S8 = std::span(First, Last); // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} const auto &S9 = std::span{First, Last}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} auto &&S10 = std::span(First, Last); // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} if (auto X = std::span{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}} } auto X = warnVarInit(First, Last); // function return is fine return S; } template void foo(const T &, const T &&, T); std::span warnTemp(It &First, It &Last) { foo(std::span{First, Last}, // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} std::move(std::span{First, Last}), // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} std::span{First, Last}); // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} std::span Arr[1] = {std::span{First, Last}}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} if (std::span{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}} } return std::span{First, Last}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} } } // namespace construct_wt_begin_end namespace test_flag { void f(int *p) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // this flag turns off every unsafe-buffer warning std::span S{p, 10}; // no-warning p++; // no-warning #pragma clang diagnostic pop #pragma clang diagnostic push #pragma clang diagnostic warning "-Wunsafe-buffer-usage" #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container" // turn on all unsafe-buffer warnings except for the ones under `-Wunsafe-buffer-usage-in-container` std::span S2{p, 10}; // no-warning p++; // expected-warning{{unsafe pointer arithmetic}}\ expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} #pragma clang diagnostic pop } } //namespace test_flag struct HoldsStdSpanAndInitializedInCtor { char* Ptr; unsigned Size; std::span Span{Ptr, Size}; // no-warning (this code is unreachable) HoldsStdSpanAndInitializedInCtor(char* P, unsigned S) : 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}} {} }; struct HoldsStdSpanAndNotInitializedInCtor { char* Ptr; unsigned Size; std::span 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}} HoldsStdSpanAndNotInitializedInCtor(char* P, unsigned S) : Ptr(P), Size(S) {} };