@@ -18,7 +18,9 @@ void foo2(unsigned idx) {
1818
1919struct Foo {
2020 int member_buffer[10 ];
21+ int x;
2122};
23+
2224void foo2 (Foo& f, unsigned idx) {
2325 f.member_buffer [idx] = 0 ; // expected-warning{{unsafe buffer access}}
2426}
@@ -33,6 +35,37 @@ void constant_idx_safe0(unsigned idx) {
3335 buffer[0 ] = 0 ;
3436}
3537
38+ int array[10 ]; // expected-warning {{'array' is an unsafe buffer that does not perform bounds checks}}
39+
40+ void masked_idx1 (unsigned long long idx, Foo f) {
41+ // Bitwise and operation
42+ array[idx & 5 ] = 10 ; // no-warning
43+ array[5 &idx] = 12 ; // no-warning
44+ array[idx & 11 & 5 ] = 3 ; // no warning
45+ array[idx & 11 ] = 20 ; // expected-note{{used in buffer access here}}
46+ array[idx &=5 ]; // expected-note{{used in buffer access here}}
47+ array[f.x & 5 ]; // no-warning
48+ array[5 & f.x ]; // no-warning
49+ array[f.x & (-5 )]; // expected-note{{used in buffer access here}}
50+ }
51+
52+ typedef unsigned long long uint64_t ;
53+ typedef unsigned int uint32_t ;
54+ typedef unsigned char uint8_t ;
55+
56+ void type_conversions (uint64_t idx1, uint32_t idx2, uint8_t idx3) {
57+ array[(uint32_t )idx1 & 3 ];
58+ array[idx2 & 3 ];
59+ array[idx3 & 3 ];
60+ }
61+
62+ int array2[5 ]; // expected-warning {{'array2' is an unsafe buffer that does not perform bounds checks}}
63+
64+ void masked_idx_safe (unsigned long long idx) {
65+ array2[6 & 5 ]; // no warning
66+ array2[6 & idx & (idx + 1 ) & 5 ]; // expected-note{{used in buffer access here}}
67+ }
68+
3669void constant_idx_unsafe (unsigned idx) {
3770 int buffer[10 ]; // expected-warning{{'buffer' is an unsafe buffer that does not perform bounds checks}}
3871 // expected-note@-1{{change type of 'buffer' to 'std::array' to label it for hardening}}
0 commit comments