xref: /llvm-project/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-multi-parm-span.cpp (revision fde4b80cb772897a8cf0b3d022f3041e10b6e816)
133f6161dSZiqing Luo // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -fblocks -fsafe-buffer-usage-suggestions -verify %s
233f6161dSZiqing Luo // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -fblocks -fsafe-buffer-usage-suggestions \
333f6161dSZiqing Luo // RUN:            %s 2>&1 | FileCheck %s
433f6161dSZiqing Luo 
533f6161dSZiqing Luo // FIXME: what about possible diagnostic message non-determinism?
633f6161dSZiqing Luo 
733f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
parmsNoFix(int * p,int * q)833f6161dSZiqing Luo void parmsNoFix(int *p, int *q) {
933f6161dSZiqing Luo   int * a = new int[10];
1033f6161dSZiqing Luo   int * b = new int[10]; //expected-warning{{'b' is an unsafe pointer used for buffer access}} \
1133f6161dSZiqing Luo 			   expected-note{{change type of 'b' to 'std::span' to preserve bounds information}}
1233f6161dSZiqing Luo 
1333f6161dSZiqing Luo   a = p;
1433f6161dSZiqing Luo   a = q;
1533f6161dSZiqing Luo   b[5] = 5; // expected-note{{used in buffer access here}}
1633f6161dSZiqing Luo }
1733f6161dSZiqing Luo 
1833f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:21-[[@LINE+2]]:27}:"std::span<int> p"
1933f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+14]]:2-[[@LINE+14]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void parmsSingleton(int *p) {return parmsSingleton(std::span<int>(p, <# size #>));}\n"
parmsSingleton(int * p)2033f6161dSZiqing Luo void parmsSingleton(int *p) { //expected-warning{{'p' is an unsafe pointer used for buffer access}} \
2133f6161dSZiqing Luo 			        expected-note{{change type of 'p' to 'std::span' to preserve bounds information}}
22*fde4b80cSjkorous-apple   // CHECK: fix-it:{{.*}}:{[[@LINE+3]]:3-[[@LINE+3]]:8}:"std::span<int>"
2333f6161dSZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:13-[[@LINE+2]]:13}:"{"
2433f6161dSZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:24-[[@LINE+1]]:24}:", 10}"
2533f6161dSZiqing Luo   int * a = new int[10];
26*fde4b80cSjkorous-apple   // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
2733f6161dSZiqing Luo   int * b; //expected-warning{{'b' is an unsafe pointer used for buffer access}} \
2833f6161dSZiqing Luo 	     expected-note{{change type of 'b' to 'std::span' to preserve bounds information, and change 'a' to 'std::span' to propagate bounds information between them}}
2933f6161dSZiqing Luo 
3033f6161dSZiqing Luo   b = a;
3133f6161dSZiqing Luo   b[5] = 5; // expected-note{{used in buffer access here}}
3233f6161dSZiqing Luo   p[5] = 5; // expected-note{{used in buffer access here}}
3333f6161dSZiqing Luo }
3433f6161dSZiqing Luo 
3533f6161dSZiqing Luo 
3633f6161dSZiqing Luo // Parameters other than `r` all will be fixed
3733f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+15]]:24-[[@LINE+15]]:30}:"std::span<int> p"
3833f6161dSZiqing Luo // CHECK  fix-it:{{.*}}:{[[@LINE+14]]:32-[[@LINE+14]]:39}:"std::span<int *> q"
3933f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+13]]:41-[[@LINE+13]]:48}:"std::span<int> a"
4033f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+23]]:2-[[@LINE+23]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void * multiParmAllFix(int *p, int **q, int a[], int * r) {return multiParmAllFix(std::span<int>(p, <# size #>), std::span<int *>(q, <# size #>), std::span<int>(a, <# size #>), r);}\n"
4133f6161dSZiqing Luo 
4233f6161dSZiqing Luo // repeat 2 more times as each of the 3 fixing parameters generates the set of fix-its above.
4333f6161dSZiqing Luo 
4433f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+8]]:24-[[@LINE+8]]:30}:"std::span<int> p"
4533f6161dSZiqing Luo // CHECK  fix-it:{{.*}}:{[[@LINE+7]]:32-[[@LINE+7]]:39}:"std::span<int *> q"
4633f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+6]]:41-[[@LINE+6]]:48}:"std::span<int> a"
4733f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+16]]:2-[[@LINE+16]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void * multiParmAllFix(int *p, int **q, int a[], int * r) {return multiParmAllFix(std::span<int>(p, <# size #>), std::span<int *>(q, <# size #>), std::span<int>(a, <# size #>), r);}\n"
4833f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+4]]:24-[[@LINE+4]]:30}:"std::span<int> p"
4933f6161dSZiqing Luo // CHECK  fix-it:{{.*}}:{[[@LINE+3]]:32-[[@LINE+3]]:39}:"std::span<int *> q"
5033f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:41-[[@LINE+2]]:48}:"std::span<int> a"
5133f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+12]]:2-[[@LINE+12]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void * multiParmAllFix(int *p, int **q, int a[], int * r) {return multiParmAllFix(std::span<int>(p, <# size #>), std::span<int *>(q, <# size #>), std::span<int>(a, <# size #>), r);}\n"
multiParmAllFix(int * p,int ** q,int a[],int * r)5233f6161dSZiqing Luo void * multiParmAllFix(int *p, int **q, int a[], int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}   expected-warning{{'q' is an unsafe pointer used for buffer access}} \
5333f6161dSZiqing Luo    expected-warning{{'a' is an unsafe pointer used for buffer access}} \
5433f6161dSZiqing Luo    expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'q' and 'a' to safe types to make function 'multiParmAllFix' bounds-safe}} \
5533f6161dSZiqing Luo    expected-note{{change type of 'q' to 'std::span' to preserve bounds information, and change 'p' and 'a' to safe types to make function 'multiParmAllFix' bounds-safe}} \
5633f6161dSZiqing Luo    expected-note{{change type of 'a' to 'std::span' to preserve bounds information, and change 'p' and 'q' to safe types to make function 'multiParmAllFix' bounds-safe}}
5733f6161dSZiqing Luo   int tmp;
5833f6161dSZiqing Luo 
5933f6161dSZiqing Luo   tmp = p[5]; // expected-note{{used in buffer access here}}
6033f6161dSZiqing Luo   tmp = a[5]; // expected-note{{used in buffer access here}}
6133f6161dSZiqing Luo   if (++q) {} // expected-note{{used in pointer arithmetic here}}
6233f6161dSZiqing Luo   return r;
6333f6161dSZiqing Luo }
6433f6161dSZiqing Luo 
6533f6161dSZiqing Luo void * multiParmAllFix(int *p, int **q, int a[], int * r);
6633f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
6733f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:58-[[@LINE-2]]:58}:";\nvoid * multiParmAllFix(std::span<int> p, std::span<int *> q, std::span<int> a, int * r)"
6833f6161dSZiqing Luo 
6933f6161dSZiqing Luo // Fixing local variables implicates fixing parameters
multiParmLocalAllFix(int * p,int * r)7033f6161dSZiqing Luo void  multiParmLocalAllFix(int *p, int * r) {
71700baeb7SZiqing Luo   // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
72700baeb7SZiqing Luo   // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
73700baeb7SZiqing Luo   int * x; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
74700baeb7SZiqing Luo   // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
75700baeb7SZiqing Luo   int * z; // expected-warning{{'z' is an unsafe pointer used for buffer access}}
7633f6161dSZiqing Luo   int * y;
7733f6161dSZiqing Luo 
7833f6161dSZiqing Luo   x = p;
79700baeb7SZiqing Luo   y = x; // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
8033f6161dSZiqing Luo   // `x` needs to be fixed so does the pointer assigned to `x`, i.e.,`p`
8133f6161dSZiqing Luo   x[5] = 5; // expected-note{{used in buffer access here}}
8233f6161dSZiqing Luo   z = r;
8333f6161dSZiqing Luo   // `z` needs to be fixed so does the pointer assigned to `z`, i.e.,`r`
8433f6161dSZiqing Luo   z[5] = 5; // expected-note{{used in buffer access here}}
8533f6161dSZiqing Luo   // Since `p` and `r` are parameters need to be fixed together,
8633f6161dSZiqing Luo   // fixing `x` involves fixing all `p`, `r` and `z`. Similar for
8733f6161dSZiqing Luo   // fixing `z`.
8833f6161dSZiqing Luo }
89700baeb7SZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
9033f6161dSZiqing Luo 
9133f6161dSZiqing Luo 
9233f6161dSZiqing Luo // Fixing parameters implicates fixing local variables
93700baeb7SZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
multiParmLocalAllFix2(int * p,int * r)9433f6161dSZiqing Luo void  multiParmLocalAllFix2(int *p, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
95700baeb7SZiqing Luo                                                   expected-warning{{'r' is an unsafe pointer used for buffer access}}
9633f6161dSZiqing Luo   int * x = new int[10];
97700baeb7SZiqing Luo   // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
9833f6161dSZiqing Luo   int * z = new int[10];
99700baeb7SZiqing Luo   // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
10033f6161dSZiqing Luo   int * y;
10133f6161dSZiqing Luo 
10233f6161dSZiqing Luo   p = x;
103700baeb7SZiqing Luo   y = x;    // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
10433f6161dSZiqing Luo   p[5] = 5; // expected-note{{used in buffer access here}}
10533f6161dSZiqing Luo   r = z;
10633f6161dSZiqing Luo   r[5] = 5; // expected-note{{used in buffer access here}}
10733f6161dSZiqing Luo }
108700baeb7SZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
10933f6161dSZiqing Luo 
11033f6161dSZiqing Luo 
11133f6161dSZiqing Luo // No fix emitted for any of the parameter since parameter `r` cannot be fixed
11233f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
noneParmFix(int * p,int * q,int * r)11333f6161dSZiqing Luo void noneParmFix(int * p, int * q, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
11433f6161dSZiqing Luo 					         expected-warning{{'q' is an unsafe pointer used for buffer access}} \
11533f6161dSZiqing Luo 					         expected-warning{{'r' is an unsafe pointer used for buffer access}}
11633f6161dSZiqing Luo   int tmp = p[5]; // expected-note{{used in buffer access here}}
11733f6161dSZiqing Luo   tmp = q[5];     // expected-note{{used in buffer access here}}
11833f6161dSZiqing Luo   r++;            // expected-note{{used in pointer arithmetic here}}
11933f6161dSZiqing Luo   tmp = r[5];     // expected-note{{used in buffer access here}}
12033f6161dSZiqing Luo }
12133f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
12233f6161dSZiqing Luo 
12333f6161dSZiqing Luo // To show what if the `r` in `noneParmFix` can be fixed:
noneParmFix_control(int * p,int * q,int * r)12433f6161dSZiqing Luo void noneParmFix_control(int * p, int * q, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
12533f6161dSZiqing Luo 						         expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'q' and 'r' to safe types to make function 'noneParmFix_control' bounds-safe}} \
12633f6161dSZiqing Luo 					                 expected-warning{{'q' is an unsafe pointer used for buffer access}} \
12733f6161dSZiqing Luo 						         expected-note{{change type of 'q' to 'std::span' to preserve bounds information, and change 'p' and 'r' to safe types to make function 'noneParmFix_control' bounds-safe}} \
12833f6161dSZiqing Luo 					                 expected-warning{{'r' is an unsafe pointer used for buffer access}} \
12933f6161dSZiqing Luo 						         expected-note{{change type of 'r' to 'std::span' to preserve bounds information, and change 'p' and 'q' to safe types to make function 'noneParmFix_control' bounds-safe}}
13033f6161dSZiqing Luo   int tmp = p[5]; // expected-note{{used in buffer access here}}
13133f6161dSZiqing Luo   tmp = q[5];     // expected-note{{used in buffer access here}}
13233f6161dSZiqing Luo   if (++r) {}     // expected-note{{used in pointer arithmetic here}}
13333f6161dSZiqing Luo   tmp = r[5];     // expected-note{{used in buffer access here}}
13433f6161dSZiqing Luo }
13533f6161dSZiqing Luo 
13633f6161dSZiqing Luo 
13733f6161dSZiqing Luo // No fix emitted for any of the parameter since local variable `l` cannot be fixed.
13833f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
noneParmOrLocalFix(int * p,int * q,int * r)13933f6161dSZiqing Luo void noneParmOrLocalFix(int * p, int * q, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
14033f6161dSZiqing Luo 						        expected-warning{{'q' is an unsafe pointer used for buffer access}} \
14133f6161dSZiqing Luo 						        expected-warning{{'r' is an unsafe pointer used for buffer access}}
14233f6161dSZiqing Luo   int tmp = p[5];  // expected-note{{used in buffer access here}}
14333f6161dSZiqing Luo   tmp = q[5];      // expected-note{{used in buffer access here}}
14433f6161dSZiqing Luo   tmp = r[5];      // expected-note{{used in buffer access here}}
14533f6161dSZiqing Luo   // `l` and `r` must be fixed together while all parameters must be fixed together as well:
14633f6161dSZiqing Luo   int * l; l = r;     // expected-warning{{'l' is an unsafe pointer used for buffer access}}
14733f6161dSZiqing Luo 
14833f6161dSZiqing Luo   l++;             // expected-note{{used in pointer arithmetic here}}
14933f6161dSZiqing Luo }
15033f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
15133f6161dSZiqing Luo 
15233f6161dSZiqing Luo // To show what if the `l` can be fixed in `noneParmOrLocalFix`:
noneParmOrLocalFix_control(int * p,int * q,int * r)15333f6161dSZiqing Luo void noneParmOrLocalFix_control(int * p, int * q, int * r) {// \
15433f6161dSZiqing Luo   expected-warning{{'p' is an unsafe pointer used for buffer access}} \
15533f6161dSZiqing Luo   expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'q', 'r', and 'l' to safe types to make function 'noneParmOrLocalFix_control' bounds-safe}} \
15633f6161dSZiqing Luo   expected-warning{{'q' is an unsafe pointer used for buffer access}} \
15733f6161dSZiqing Luo   expected-note{{change type of 'q' to 'std::span' to preserve bounds information, and change 'p', 'r', and 'l' to safe types to make function 'noneParmOrLocalFix_control' bounds-safe}} \
15833f6161dSZiqing Luo   expected-warning{{'r' is an unsafe pointer used for buffer access}} \
15933f6161dSZiqing Luo   expected-note{{change type of 'r' to 'std::span' to preserve bounds information, and change 'p', 'q', and 'l' to safe types to make function 'noneParmOrLocalFix_control' bounds-safe}}
16033f6161dSZiqing Luo   int tmp = p[5];  // expected-note{{used in buffer access here}}
16133f6161dSZiqing Luo   tmp = q[5];      // expected-note{{used in buffer access here}}
16233f6161dSZiqing Luo   tmp = r[5];      // expected-note{{used in buffer access here}}
16333f6161dSZiqing Luo   int * l;         // expected-warning{{'l' is an unsafe pointer used for buffer access}} \
16433f6161dSZiqing Luo 		      expected-note{{change type of 'l' to 'std::span' to preserve bounds information, and change 'p', 'q', and 'r' to safe types to make function 'noneParmOrLocalFix_control' bounds-safe}}
16533f6161dSZiqing Luo   l = r;
16633f6161dSZiqing Luo   if (++l){};         // expected-note{{used in pointer arithmetic here}}
16733f6161dSZiqing Luo }
16833f6161dSZiqing Luo 
16933f6161dSZiqing Luo 
17033f6161dSZiqing Luo // No fix emitted for any of the parameter since local variable `l` cannot be fixed.
17133f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
noneParmOrLocalFix2(int * p,int * q,int * r)17233f6161dSZiqing Luo void noneParmOrLocalFix2(int * p, int * q, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
17333f6161dSZiqing Luo 						         expected-warning{{'q' is an unsafe pointer used for buffer access}} \
17433f6161dSZiqing Luo 						         expected-warning{{'r' is an unsafe pointer used for buffer access}}
17533f6161dSZiqing Luo   int tmp = p[5]; // expected-note{{used in buffer access here}}
17633f6161dSZiqing Luo   tmp = q[5];     // expected-note{{used in buffer access here}}
17733f6161dSZiqing Luo   tmp = r[5];     // expected-note{{used in buffer access here}}
17833f6161dSZiqing Luo 
17933f6161dSZiqing Luo   int * a; a = r;
18033f6161dSZiqing Luo   int * b; b = a;
18133f6161dSZiqing Luo   int * l; l = b;    // expected-warning{{'l' is an unsafe pointer used for buffer access}}
18233f6161dSZiqing Luo 
18333f6161dSZiqing Luo   // `a, b, l` and parameters must be fixed together but `l` can't be fixed:
18433f6161dSZiqing Luo   l++;               // expected-note{{used in pointer arithmetic here}}
18533f6161dSZiqing Luo }
18633f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
18733f6161dSZiqing Luo 
18833f6161dSZiqing Luo // To show what if the `l` can be fixed in `noneParmOrLocalFix2`:
noneParmOrLocalFix2_control(int * p,int * q,int * r)18933f6161dSZiqing Luo void noneParmOrLocalFix2_control(int * p, int * q, int * r) { // \
19033f6161dSZiqing Luo   expected-warning{{'p' is an unsafe pointer used for buffer access}} \
19133f6161dSZiqing Luo   expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'q', 'r', 'l', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix2_control' bounds-safe}}                 \
19233f6161dSZiqing Luo   expected-warning{{'q' is an unsafe pointer used for buffer access}} \
19333f6161dSZiqing Luo   expected-note{{change type of 'q' to 'std::span' to preserve bounds information, and change 'p', 'r', 'l', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix2_control' bounds-safe}}                 \
19433f6161dSZiqing Luo   expected-warning{{'r' is an unsafe pointer used for buffer access}} \
19533f6161dSZiqing Luo   expected-note{{change type of 'r' to 'std::span' to preserve bounds information, and change 'p', 'q', 'l', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix2_control' bounds-safe}}
19633f6161dSZiqing Luo   int tmp = p[5]; // expected-note{{used in buffer access here}}
19733f6161dSZiqing Luo   tmp = q[5];     // expected-note{{used in buffer access here}}
19833f6161dSZiqing Luo   tmp = r[5];     // expected-note{{used in buffer access here}}
19933f6161dSZiqing Luo 
20033f6161dSZiqing Luo   int * a; a = r;
20133f6161dSZiqing Luo   int * b; b = a;
20233f6161dSZiqing Luo   int * l;  // expected-warning{{'l' is an unsafe pointer used for buffer access}} \
20333f6161dSZiqing Luo 	       expected-note{{change type of 'l' to 'std::span' to preserve bounds information, and change 'p', 'q', 'r', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix2_control' bounds-safe}}
20433f6161dSZiqing Luo 
20533f6161dSZiqing Luo   l = b;
20633f6161dSZiqing Luo   if(++l){} // expected-note{{used in pointer arithmetic here}}
20733f6161dSZiqing Luo }
20833f6161dSZiqing Luo 
20933f6161dSZiqing Luo // No fix emitted for any of the parameter since local variable `l` cannot be fixed
21033f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
noneParmOrLocalFix3(int * p,int * q,int * r)21133f6161dSZiqing Luo void noneParmOrLocalFix3(int * p, int * q, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
21233f6161dSZiqing Luo 						         expected-warning{{'q' is an unsafe pointer used for buffer access}} \
21333f6161dSZiqing Luo 						         expected-warning{{'r' is an unsafe pointer used for buffer access}}
21433f6161dSZiqing Luo   int tmp = p[5];  // expected-note{{used in buffer access here}}
21533f6161dSZiqing Luo   tmp = q[5];      // expected-note{{used in buffer access here}}
21633f6161dSZiqing Luo   tmp = r[5];      // expected-note{{used in buffer access here}}
21733f6161dSZiqing Luo 
21833f6161dSZiqing Luo   int * a; a = r;
21933f6161dSZiqing Luo   int * b; b = a;
22033f6161dSZiqing Luo   int * l; l = b;     // expected-warning{{'l' is an unsafe pointer used for buffer access}}
22133f6161dSZiqing Luo 
22233f6161dSZiqing Luo   l++;             // expected-note{{used in pointer arithmetic here}}
22333f6161dSZiqing Luo 
22433f6161dSZiqing Luo   int * x; x = p; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
22533f6161dSZiqing Luo   tmp = x[5];  // expected-note{{used in buffer access here}}
22633f6161dSZiqing Luo }
22733f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
22833f6161dSZiqing Luo 
noneParmOrLocalFix3_control(int * p,int * q,int * r)22933f6161dSZiqing Luo void noneParmOrLocalFix3_control(int * p, int * q, int * r) { // \
23033f6161dSZiqing Luo      expected-warning{{'p' is an unsafe pointer used for buffer access}} \
23133f6161dSZiqing Luo      expected-note{{change type of 'p' to 'std::span' to preserve bounds information, and change 'x', 'q', 'r', 'l', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix3_control' bounds-safe}}            \
23233f6161dSZiqing Luo      expected-warning{{'q' is an unsafe pointer used for buffer access}} \
23333f6161dSZiqing Luo      expected-note{{change type of 'q' to 'std::span' to preserve bounds information, and change 'p', 'x', 'r', 'l', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix3_control' bounds-safe}}            \
23433f6161dSZiqing Luo      expected-warning{{'r' is an unsafe pointer used for buffer access}} \
23533f6161dSZiqing Luo      expected-note{{change type of 'r' to 'std::span' to preserve bounds information, and change 'p', 'x', 'q', 'l', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix3_control' bounds-safe}}
23633f6161dSZiqing Luo   int tmp = p[5];  // expected-note{{used in buffer access here}}
23733f6161dSZiqing Luo   tmp = q[5];      // expected-note{{used in buffer access here}}
23833f6161dSZiqing Luo   tmp = r[5];      // expected-note{{used in buffer access here}}
23933f6161dSZiqing Luo 
24033f6161dSZiqing Luo   int * a; a = r;
24133f6161dSZiqing Luo   int * b; b = a;
24233f6161dSZiqing Luo   int * l;         // expected-warning{{'l' is an unsafe pointer used for buffer access}}   \
24333f6161dSZiqing Luo 		      expected-note{{change type of 'l' to 'std::span' to preserve bounds information, and change 'p', 'x', 'q', 'r', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix3_control' bounds-safe}}
24433f6161dSZiqing Luo 
24533f6161dSZiqing Luo   l = b;
24633f6161dSZiqing Luo   if (++l){};         // expected-note{{used in pointer arithmetic here}}
24733f6161dSZiqing Luo 
24833f6161dSZiqing Luo   int * x;            // expected-warning{{'x' is an unsafe pointer used for buffer access}} \
24933f6161dSZiqing Luo 		         expected-note{{change type of 'x' to 'std::span' to preserve bounds information, and change 'p', 'q', 'r', 'l', 'b', and 'a' to safe types to make function 'noneParmOrLocalFix3_control' bounds-safe}}
25033f6161dSZiqing Luo   x = p;
25133f6161dSZiqing Luo   tmp = x[5];  // expected-note{{used in buffer access here}}
25233f6161dSZiqing Luo }
25333f6161dSZiqing Luo 
25433f6161dSZiqing Luo 
25533f6161dSZiqing Luo // No fix emitted for any of the parameter but some local variables will get fixed
25633f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
noneParmSomeLocalFix(int * p,int * q,int * r)25733f6161dSZiqing Luo void noneParmSomeLocalFix(int * p, int * q, int * r) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
25833f6161dSZiqing Luo 						          expected-warning{{'q' is an unsafe pointer used for buffer access}} \
25933f6161dSZiqing Luo 						          expected-warning{{'r' is an unsafe pointer used for buffer access}}
26033f6161dSZiqing Luo   int tmp = p[5];  // expected-note{{used in buffer access here}}
26133f6161dSZiqing Luo   tmp = q[5];      // expected-note{{used in buffer access here}}
26233f6161dSZiqing Luo   tmp = r[5];      // expected-note{{used in buffer access here}}
26333f6161dSZiqing Luo 
26433f6161dSZiqing Luo   int * a; a = r;
26533f6161dSZiqing Luo   int * b; b = a;
26633f6161dSZiqing Luo   int * l; l = b; // expected-warning{{'l' is an unsafe pointer used for buffer access}}
26733f6161dSZiqing Luo 
26833f6161dSZiqing Luo   l++; // expected-note{{used in pointer arithmetic here}}
26933f6161dSZiqing Luo 
27033f6161dSZiqing Luo   //`x` and `y` can be fixed
27133f6161dSZiqing Luo   int * x = new int[10];
272*fde4b80cSjkorous-apple   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
27333f6161dSZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
27433f6161dSZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
275*fde4b80cSjkorous-apple   // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
27633f6161dSZiqing Luo   int * y;   // expected-warning{{'y' is an unsafe pointer used for buffer access}} \
27733f6161dSZiqing Luo 	        expected-note{{change type of 'y' to 'std::span' to preserve bounds information, and change 'x' to 'std::span' to propagate bounds information between them}}
27833f6161dSZiqing Luo   y = x;
27933f6161dSZiqing Luo   tmp = y[5];  // expected-note{{used in buffer access here}}
28033f6161dSZiqing Luo }
28133f6161dSZiqing Luo // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
28233f6161dSZiqing Luo 
28333f6161dSZiqing Luo // Test that other parameters of (lambdas and blocks) do not interfere
28433f6161dSZiqing Luo // the grouping of variables of the function.
28533f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+3]]:30-[[@LINE+3]]:37}:"std::span<int> p"
28633f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:39-[[@LINE+2]]:46}:"std::span<int> q"
28733f6161dSZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE+20]]:2-[[@LINE+20]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void parmsFromLambdaAndBlock(int * p, int * q) {return parmsFromLambdaAndBlock(std::span<int>(p, <# size #>), std::span<int>(q, <# size #>));}\n"
parmsFromLambdaAndBlock(int * p,int * q)28833f6161dSZiqing Luo void parmsFromLambdaAndBlock(int * p, int * q) {
289*fde4b80cSjkorous-apple   // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
29033f6161dSZiqing Luo   int * a; // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
29133f6161dSZiqing Luo 	      expected-note{{change type of 'a' to 'std::span' to preserve bounds information, and change 'p', 'b', and 'q' to safe types to make function 'parmsFromLambdaAndBlock' bounds-safe}}
292*fde4b80cSjkorous-apple   // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
29333f6161dSZiqing Luo   int * b; // expected-warning{{'b' is an unsafe pointer used for buffer access}} \
29433f6161dSZiqing Luo               expected-note{{change type of 'b' to 'std::span' to preserve bounds information, and change 'a', 'p', and 'q' to safe types to make function 'parmsFromLambdaAndBlock' bounds-safe}}
29533f6161dSZiqing Luo   auto Lamb = [](int * x) -> void { // expected-warning{{'x' is an unsafe pointer used for buffer access}}
29633f6161dSZiqing Luo     x[5] = 5;                       // expected-note{{used in buffer access here}}
29733f6161dSZiqing Luo   };
29833f6161dSZiqing Luo 
29933f6161dSZiqing Luo   void (^Blk)(int*) = ^(int * y) {  // expected-warning{{'y' is an unsafe pointer used for buffer access}}
30033f6161dSZiqing Luo     y[5] = 5;                       // expected-note{{used in buffer access here}}
30133f6161dSZiqing Luo   };
30233f6161dSZiqing Luo 
30333f6161dSZiqing Luo   a = p;
30433f6161dSZiqing Luo   b = q;
30533f6161dSZiqing Luo   a[5] = 5; // expected-note{{used in buffer access here}}
30633f6161dSZiqing Luo   b[5] = 5; // expected-note{{used in buffer access here}}
30733f6161dSZiqing Luo }
308