Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaCXX / warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp
blob71350098613d19a77642bff667f76f609f1bc06d
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;
5 #define MACRO_PTR int*
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
30 // case.
31 // CHECK-NOT: fix-it:
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:
46 // CHECK-NOT: fix-it:
47 class A {
48 // constructor & descructor
49 A(int * p) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
50 int tmp;
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}}
56 int tmp;
57 tmp = p[5]; // expected-note{{used in buffer access here}}
60 // overload operator
61 int operator+(int * p) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
62 int tmp;
63 tmp = p[5]; // expected-note{{used in buffer access here}}
64 return tmp;
68 // lambdas
69 void foo() {
70 auto Lamb = [&](int *p) // expected-warning{{'p' is an unsafe pointer used for buffer access}}
71 -> int {
72 int tmp;
73 tmp = p[5]; // expected-note{{used in buffer access here}}
74 return tmp;
78 // template
79 template<typename T>
80 void template_foo(T * p) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
81 T tmp;
82 tmp = p[5]; // expected-note{{used in buffer access here}}
85 void instantiate_template_foo() {
86 int * p;
87 template_foo(p); // FIXME expected note {{in instantiation of function template specialization 'template_foo<int>' requested here}}
90 // variadic function
91 void vararg_foo(int * p...) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
92 int tmp;
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}}
103 try {
104 int tmp;
106 if (p == nullptr)
107 throw 42;
108 tmp = p[5]; // expected-note{{used in buffer access here}}
110 catch (int) {
111 *p = 0;
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}}
119 int tmp;
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}}
127 int tmp;
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}}
135 int tmp;
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}}