1 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ 2 // RUN: -fsafe-buffer-usage-suggestions \ 3 // RUN: -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s 4 5 void basic(int * x) { 6 int tmp; 7 int *p1 = new int[10]; // no fix 8 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 9 int *p2 = new int[10]; 10 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p2" 11 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{" 12 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}" 13 #pragma clang unsafe_buffer_usage begin 14 tmp = p1[5]; 15 #pragma clang unsafe_buffer_usage end 16 tmp = p2[5]; 17 } 18 19 void withDiagnosticWarning() { 20 int tmp; 21 int *p1 = new int[10]; // no fix 22 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 23 int *p2 = new int[10]; 24 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p2" 25 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{" 26 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}" 27 28 // diagnostics in opt-out region 29 #pragma clang unsafe_buffer_usage begin 30 tmp = p1[5]; // not to warn 31 tmp = p2[5]; // not to warn 32 #pragma clang diagnostic push 33 #pragma clang diagnostic warning "-Wunsafe-buffer-usage" 34 tmp = p1[5]; // not to warn 35 tmp = p2[5]; // not to warn 36 #pragma clang diagnostic warning "-Weverything" 37 tmp = p1[5]; // not to warn 38 tmp = p2[5]; // not to warn 39 #pragma clang diagnostic pop 40 #pragma clang unsafe_buffer_usage end 41 42 // opt-out region under diagnostic warning 43 #pragma clang diagnostic push 44 #pragma clang diagnostic warning "-Wunsafe-buffer-usage" 45 #pragma clang unsafe_buffer_usage begin 46 tmp = p1[5]; // not to warn 47 tmp = p2[5]; // not to warn 48 #pragma clang unsafe_buffer_usage end 49 #pragma clang diagnostic pop 50 51 tmp = p2[5]; 52 } 53 54 55 void withDiagnosticIgnore() { 56 int tmp; 57 int *p1 = new int[10]; 58 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 59 int *p2 = new int[10]; 60 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p2" 61 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{" 62 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}" 63 int *p3 = new int[10]; 64 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p3" 65 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{" 66 // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}" 67 68 #pragma clang unsafe_buffer_usage begin 69 tmp = p1[5]; // not to warn 70 tmp = p2[5]; // not to warn 71 #pragma clang diagnostic push 72 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 73 tmp = p1[5]; // not to warn 74 tmp = p2[5]; // not to warn 75 #pragma clang diagnostic ignored "-Weverything" 76 tmp = p1[5]; // not to warn 77 tmp = p2[5]; // not to warn 78 #pragma clang diagnostic pop 79 #pragma clang unsafe_buffer_usage end 80 81 #pragma clang diagnostic push 82 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 83 #pragma clang unsafe_buffer_usage begin 84 tmp = p1[5]; // not to warn 85 tmp = p2[5]; // not to warn 86 #pragma clang unsafe_buffer_usage end 87 #pragma clang diagnostic pop 88 89 tmp = p2[5]; 90 91 #pragma clang diagnostic push 92 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 93 #pragma clang unsafe_buffer_usage begin 94 tmp = p1[5]; // not to warn 95 tmp = p2[5]; // not to warn 96 #pragma clang unsafe_buffer_usage end 97 tmp = p3[5]; // expected-note{{used in buffer access here}} 98 #pragma clang diagnostic pop 99 } 100 101 void noteGoesWithVarDeclWarning() { 102 #pragma clang diagnostic push 103 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 104 int *p = new int[10]; // not to warn 105 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 106 #pragma clang diagnostic pop 107 108 p[5]; // not to note since the associated warning is suppressed 109 } 110 111 112 // Test suppressing interacts with variable grouping: 113 114 // The implication edges are: `a` -> `b` -> `c`. 115 // If the unsafe operation on `a` is supressed, none of the variables 116 // will be fixed. 117 void suppressedVarInGroup() { 118 int * a; 119 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 120 int * b; 121 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 122 int * c; 123 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 124 125 #pragma clang unsafe_buffer_usage begin 126 a[5] = 5; 127 #pragma clang unsafe_buffer_usage end 128 a = b; 129 b = c; 130 } 131 132 // To show that if `a[5]` is not suppressed in the 133 // `suppressedVarInGroup` function above, all variables will be fixed. 134 void suppressedVarInGroup_control() { 135 int * a; 136 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> a" 137 int * b; 138 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> b" 139 int * c; 140 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c" 141 142 a[5] = 5; 143 a = b; 144 b = c; 145 } 146 147 // The implication edges are: `a` -> `b` -> `c`. 148 // The unsafe operation on `b` is supressed, while the unsafe 149 // operation on `a` is not suppressed. Variable `b` will still be 150 // fixed when fixing `a`. 151 void suppressedVarInGroup2() { 152 int * a; 153 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> a" 154 int * b; 155 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> b" 156 int * c; 157 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c" 158 159 a[5] = 5; 160 #pragma clang unsafe_buffer_usage begin 161 b[5] = 5; 162 #pragma clang unsafe_buffer_usage end 163 a = b; 164 b = c; 165 } 166 167 // The implication edges are: `a` -> `b` -> `c`. 168 // The unsafe operation on `b` is supressed, while the unsafe 169 // operation on `c` is not suppressed. Only variable `c` will be fixed 170 // then. 171 void suppressedVarInGroup3() { 172 int * a; 173 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 174 int * b; 175 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 176 int * c; 177 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c" 178 179 c[5] = 5; 180 #pragma clang unsafe_buffer_usage begin 181 b[5] = 5; 182 #pragma clang unsafe_buffer_usage end 183 a = b; 184 b = c; 185 } 186 187 // The implication edges are: `a` -> `b` -> `c` -> `a`. 188 // The unsafe operation on `b` is supressed, while the unsafe 189 // operation on `c` is not suppressed. Since the implication graph 190 // forms a cycle, all variables will be fixed. 191 void suppressedVarInGroup4() { 192 int * a; 193 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> a" 194 int * b; 195 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> b" 196 int * c; 197 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c" 198 199 c[5] = 5; 200 #pragma clang unsafe_buffer_usage begin 201 b[5] = 5; 202 #pragma clang unsafe_buffer_usage end 203 a = b; 204 b = c; 205 c = a; 206 } 207 208 // There are two groups: `a` -> `b` -> `c` and `d` -> `e` -> `f`. 209 // Suppressing unsafe operations on variables in one group does not 210 // affect other groups. 211 void suppressedVarInGroup5() { 212 int * a; 213 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 214 int * b; 215 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 216 int * c; 217 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]: 218 int * d; 219 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> d" 220 int * e; 221 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> e" 222 int * f; 223 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> f" 224 225 #pragma clang unsafe_buffer_usage begin 226 a[5] = 5; 227 #pragma clang unsafe_buffer_usage end 228 a = b; 229 b = c; 230 231 d[5] = 5; 232 d = e; 233 e = f; 234 } 235