xref: /llvm-project/clang/test/SemaCXX/warn-unsafe-buffer-usage-in-container-span-construct.cpp (revision 9aa3b53ac52167aba6253a52805874948ce40c8f)
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