1 // RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage -fcxx-exceptions -fsafe-buffer-usage-suggestions -verify %s
2 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fcxx-exceptions -fdiagnostics-parseable-fixits -fsafe-buffer-usage-suggestions %s 2>&1 | FileCheck %s
4 typedef int * TYPEDEF_PTR
;
7 // We CANNOT fix a pointer whose type is defined in a typedef or a
8 // macro. Because if the typedef is changed after the fix, the fix
9 // becomes incorrect and may not be noticed.
11 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE+1]]
12 void typedefPointer(TYPEDEF_PTR p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
13 if (++p
) { // expected-note{{used in pointer arithmetic here}}
17 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE+1]]
18 void macroPointer(MACRO_PTR p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
19 if (++p
) { // expected-note{{used in pointer arithmetic here}}
23 // The analysis requires accurate source location informations from
24 // `TypeLoc`s of types of variable (parameter) declarations in order
25 // to generate fix-its for them. But those information is not always
26 // available (probably due to some bugs in clang but it is irrelevant
27 // to the safe-buffer project). The following is an example. When
28 // `_Atomic` is used, we cannot get valid source locations of the
29 // pointee type of `unsigned *`. The analysis gives up in such a
32 void typeLocSourceLocationInvalid(_Atomic
unsigned *map
) { // expected-warning{{'map' is an unsafe pointer used for buffer access}}
33 map
[5] = 5; // expected-note{{used in buffer access here}}
36 // CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:33-[[@LINE+1]]:46}:"std::span<unsigned> map"
37 void typeLocSourceLocationValid(unsigned *map
) { // expected-warning{{'map' is an unsafe pointer used for buffer access}} \
38 expected
-note
{{change type of
'map' to
'std::span' to preserve bounds information
}}
39 map
[5] = 5; // expected-note{{used in buffer access here}}
41 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void typeLocSourceLocationValid(unsigned *map) {return typeLocSourceLocationValid(std::span<unsigned>(map, <# size #>));}\n"
43 // We do not fix parameters participating unsafe operations for the
44 // following functions/methods or function-like expressions:
48 // constructor & descructor
49 A(int * p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
51 tmp
= p
[5]; // expected-note{{used in buffer access here}}
54 // class member methods
55 void foo(int *p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
57 tmp
= p
[5]; // expected-note{{used in buffer access here}}
61 int operator+(int * p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
63 tmp
= p
[5]; // expected-note{{used in buffer access here}}
70 auto Lamb
= [&](int *p
) // expected-warning{{'p' is an unsafe pointer used for buffer access}}
73 tmp
= p
[5]; // expected-note{{used in buffer access here}}
80 void template_foo(T
* p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
82 tmp
= p
[5]; // expected-note{{used in buffer access here}}
85 void instantiate_template_foo() {
87 template_foo(p
); // FIXME expected note {{in instantiation of function template specialization 'template_foo<int>' requested here}}
91 void vararg_foo(int * p
...) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
93 tmp
= p
[5]; // expected-note{{used in buffer access here}}
96 // constexpr functions
97 constexpr int constexpr_foo(int * p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
98 return p
[5]; // expected-note{{used in buffer access here}}
101 // function body is a try-block
102 void fn_with_try_block(int* p
) // expected-warning{{'p' is an unsafe pointer used for buffer access}}
108 tmp
= p
[5]; // expected-note{{used in buffer access here}}
114 // The following two unsupported cases are not specific to
115 // parm-fixits. Adding them here in case they get forgotten.
116 void isArrayDecayToPointerUPC(int a
[][10], int (*b
)[10]) {
117 // expected-warning@-1{{'a' is an unsafe pointer used for buffer access}}
118 // expected-warning@-2{{'b' is an unsafe pointer used for buffer access}}
121 tmp
= a
[5][5] + b
[5][5]; // expected-warning2{{unsafe buffer access}} expected-note2{{used in buffer access here}}
124 // parameter having default values:
125 void parmWithDefaultValue(int * x
= 0) {
126 // expected-warning@-1{{'x' is an unsafe pointer used for buffer access}}
128 tmp
= x
[5]; // expected-note{{used in buffer access here}}
131 void parmWithDefaultValueDecl(int * x
= 0);
133 void parmWithDefaultValueDecl(int * x
) {
134 // expected-warning@-1{{'x' is an unsafe pointer used for buffer access}}
136 tmp
= x
[5]; // expected-note{{used in buffer access here}}
139 #define MACRO_NAME MyName
141 // The fix-it ends with a macro. It will be discarded due to overlap with macros.
142 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
143 void macroIdentifier(int * MACRO_NAME
) { // expected-warning{{'MyName' is an unsafe pointer used for buffer access}}
144 if (++MyName
){} // expected-note{{used in pointer arithmetic here}}
147 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
148 void parmHasNoName(int *p
, int *) { // cannot fix the function because there is one parameter has no name. \
149 expected
-warning
{{'p' is an unsafe pointer used
for buffer access
}}
150 p
[5] = 5; // expected-note{{used in buffer access here}}