236 lines · cpp
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 %s4 5void basic(int * x) {6 int tmp;7 int *p1 = new int[10]; // no fix8 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:9 int *p2 = new int[10];10 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "11 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"12 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"13#pragma clang unsafe_buffer_usage begin14 tmp = p1[5];15#pragma clang unsafe_buffer_usage end16 tmp = p2[5];17}18 19void withDiagnosticWarning() {20 int tmp;21 int *p1 = new int[10]; // no fix22 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:23 int *p2 = new int[10];24 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "25 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"26 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"27 28 // diagnostics in opt-out region29#pragma clang unsafe_buffer_usage begin30 tmp = p1[5]; // not to warn31 tmp = p2[5]; // not to warn32#pragma clang diagnostic push33#pragma clang diagnostic warning "-Wunsafe-buffer-usage"34 tmp = p1[5]; // not to warn35 tmp = p2[5]; // not to warn36#pragma clang diagnostic warning "-Weverything"37 tmp = p1[5]; // not to warn38 tmp = p2[5]; // not to warn39#pragma clang diagnostic pop40#pragma clang unsafe_buffer_usage end41 42 // opt-out region under diagnostic warning43#pragma clang diagnostic push44#pragma clang diagnostic warning "-Wunsafe-buffer-usage"45#pragma clang unsafe_buffer_usage begin46 tmp = p1[5]; // not to warn47 tmp = p2[5]; // not to warn48#pragma clang unsafe_buffer_usage end49#pragma clang diagnostic pop50 51 tmp = p2[5];52}53 54 55void 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: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "61 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"62 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"63 int *p3 = new int[10];64 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "65 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"66 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"67 68#pragma clang unsafe_buffer_usage begin69 tmp = p1[5]; // not to warn70 tmp = p2[5]; // not to warn71#pragma clang diagnostic push72#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"73 tmp = p1[5]; // not to warn74 tmp = p2[5]; // not to warn75#pragma clang diagnostic ignored "-Weverything"76 tmp = p1[5]; // not to warn77 tmp = p2[5]; // not to warn78#pragma clang diagnostic pop79#pragma clang unsafe_buffer_usage end80 81#pragma clang diagnostic push82#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"83#pragma clang unsafe_buffer_usage begin84 tmp = p1[5]; // not to warn85 tmp = p2[5]; // not to warn86#pragma clang unsafe_buffer_usage end87#pragma clang diagnostic pop88 89 tmp = p2[5];90 91#pragma clang diagnostic push92#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"93#pragma clang unsafe_buffer_usage begin94 tmp = p1[5]; // not to warn95 tmp = p2[5]; // not to warn96#pragma clang unsafe_buffer_usage end97 tmp = p3[5]; // expected-note{{used in buffer access here}}98#pragma clang diagnostic pop99}100 101void noteGoesWithVarDeclWarning() {102#pragma clang diagnostic push103#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"104 int *p = new int[10]; // not to warn105 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:106#pragma clang diagnostic pop107 108 p[5]; // not to note since the associated warning is suppressed109}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 variables116// will be fixed.117void 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 begin126 a[5] = 5;127#pragma clang unsafe_buffer_usage end128 a = b;129 b = c;130}131 132// To show that if `a[5]` is not suppressed in the133// `suppressedVarInGroup` function above, all variables will be fixed.134void suppressedVarInGroup_control() {135 int * a;136 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"137 int * b;138 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"139 int * c;140 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"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 unsafe149// operation on `a` is not suppressed. Variable `b` will still be150// fixed when fixing `a`.151void suppressedVarInGroup2() {152 int * a;153 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"154 int * b;155 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"156 int * c;157 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"158 159 a[5] = 5;160#pragma clang unsafe_buffer_usage begin161 b[5] = 5;162#pragma clang unsafe_buffer_usage end163 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 unsafe169// operation on `c` is not suppressed. Only variable `c` will be fixed170// then.171void 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-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:178 179 c[5] = 5;180#pragma clang unsafe_buffer_usage begin181 b[5] = 5;182#pragma clang unsafe_buffer_usage end183 a = b;184 b = c;185// FIXME: we do not fix `a = b` and `b = c` because the `.data()` fix-it is not generally correct.186}187 188// The implication edges are: `a` -> `b` -> `c` -> `a`.189// The unsafe operation on `b` is supressed, while the unsafe190// operation on `c` is not suppressed. Since the implication graph191// forms a cycle, all variables will be fixed.192void suppressedVarInGroup4() {193 int * a;194 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"195 int * b;196 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"197 int * c;198 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"199 200 c[5] = 5;201#pragma clang unsafe_buffer_usage begin202 b[5] = 5;203#pragma clang unsafe_buffer_usage end204 a = b;205 b = c;206 c = a;207}208 209// There are two groups: `a` -> `b` -> `c` and `d` -> `e` -> `f`.210// Suppressing unsafe operations on variables in one group does not211// affect other groups.212void suppressedVarInGroup5() {213 int * a;214 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:215 int * b;216 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:217 int * c;218 // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:219 int * d;220 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"221 int * e;222 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"223 int * f;224 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"225 226#pragma clang unsafe_buffer_usage begin227 a[5] = 5;228#pragma clang unsafe_buffer_usage end229 a = b;230 b = c;231 232 d[5] = 5;233 d = e;234 e = f;235}236