brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.9 KiB · 292e89c Raw
316 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 %s4typedef int * Int_ptr_t;5typedef int Int_t;6 7void local_array_subscript_simple() {8  int tmp;9  int *p = new int[10];10  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "11  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"12  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"13  const int *q = new int[10];14  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<int const> "15  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:"{"16  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:29-[[@LINE-3]]:29}:", 10}"17  tmp = p[5];18  tmp = q[5];19 20  // We do not fix the following declaration. Because if the21  // definition of `Int_ptr_t` gets changed, the fixed code becomes22  // incorrect and may NOT be noticed.23  // FIXME: Fix with std::span<std::remove_pointer_t<Int_ptr_t>>?24  Int_ptr_t x = new int[10];25  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]26  Int_t * z = new int[10];27  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<Int_t>"28  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"{"29  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:26-[[@LINE-3]]:26}:", 10}"30  Int_t * w = new Int_t[10];31  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<Int_t>"32  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"{"33  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:28-[[@LINE-3]]:28}:", 10}"34 35  tmp = x[5];36  tmp = z[5];37  tmp = w[5];38}39 40void local_array_subscript_auto() {41  int tmp;42  // We do not fix the following declaration because43  // that'd cause us to hardcode the element type.44  // FIXME: Can we use the C++17 class template argument deduction45  // to avoid spelling out the element type?46  auto p = new int[10];47  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]48  tmp = p[5];49}50 51void local_variable_qualifiers_specifiers() {52  int a[10];53  const int * p = a;54  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<int const>"55  const int * const q = a;56  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<int const>"57  int tmp;58  tmp = p[5];59  tmp = q[5];60 61  [[deprecated]] const int * x = a;62  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:18-[[@LINE-1]]:29}:"std::span<int const>"63  const int * y [[deprecated]];64  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:14}:"std::span<int const>"65  tmp = x[5];66  tmp = y[5];67}68 69void local_variable_unsupported_specifiers() {70  int a[10];71  const int * p [[deprecated]] = a; //  not supported because the attribute overlaps the source range of the declaration72  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:73 74  static const int * q = a; //  storage specifier not supported yet75  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:76 77  extern int * x; //  storage specifier not supported yet78  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:79 80  constexpr int * y = 0; //  `constexpr` specifier not supported yet81  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:82 83  int tmp;84 85  tmp = p[5];86  tmp = q[5];87  tmp = x[5];88  tmp = y[5];89}90 91void local_array_subscript_variable_extent() {92  int n = 10;93  int tmp;94  int *p = new int[n];95  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "96  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"97  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:22-[[@LINE-3]]:22}:", n}"98  // If the extent expression does not have a constant value, we cannot fill the extent for users...99  int *q = new int[n++];100  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "101  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"102  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", <# placeholder #>}"103  tmp = p[5];104  tmp = q[5];105}106 107 108void local_ptr_to_array() {109  int tmp;110  int n = 10;111  int a[10];112  int b[n];  // If the extent expression does not have a constant value, we cannot fill the extent for users...113  int *p = a;114  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "115  int *q = b;116  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "117  // No way to know if `n` is ever mutated since `int b[n];`, so no way to figure out the extent118  tmp = p[5];119  tmp = q[5];120}121 122void local_ptr_addrof_init() {123  int var;124  int * q = &var;125  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"126  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"127  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:17}:", 1}"128  // This expression involves unsafe buffer accesses, which will crash129  // at runtime after applying the fix-it,130  var = q[5];131}132 133void decl_without_init() {134  int tmp;135  int * p;136  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"137  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{^3}}138  Int_t * q;139  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<Int_t>"140  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{^3}}141  tmp = p[5];142  tmp = q[5];143}144 145// Explicit casts are required in the following cases. No way to146// figure out span extent for them automatically.147void explict_cast() {148  int tmp;149  int * p = (int*) new int[10][10];150  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"151  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"152  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:35-[[@LINE-3]]:35}:", <# placeholder #>}"153  tmp = p[5];154 155  int a;156  char * q = (char *)&a;157  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span<char>"158  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:14-[[@LINE-2]]:14}:"{"159  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", <# placeholder #>}"160  tmp = (int) q[5];161 162  void * r = &a;163  char * s = (char *) r;164  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span<char>"165  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:14-[[@LINE-2]]:14}:"{"166  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", <# placeholder #>}"167  tmp = (int) s[5];168}169 170void null_init() {171#define NULL 0172  int tmp;173  int * my_null = 0;174  int * p = 0;175  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"176  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{^3}}177  int * g = NULL; // cannot handle fix-its involving macros for now178  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:179  int * f = nullptr;180  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"181  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:{{^3}}182 183  // In case of value dependencies, we give up184  int * q = my_null;185  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"186  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"187  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:20}:", <# placeholder #>}"188  int * r = my_null + 0;189  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"190  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"191  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", <# placeholder #>}"192 193  tmp = p[5]; // `p[5]` will cause crash after `p` being transformed to be a `std::span`194  tmp = q[5]; // Similar for the rests.195  tmp = r[5];196  tmp = g[5];197  tmp = f[5];198#undef NULL199}200 201 202void unsupported_multi_decl(int * x) {203  int * p = x, * q = new int[10];204  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]205  *p = q[5];206}207 208void macroVariableIdentifier() {209#define MY_NAME p210#define MY_NAME_ARG(x) q211 212  // Although fix-its include macros, the macros do not overlap with213  // the bounds of the source range of these fix-its. So these fix-its214  // are valid.215 216  int * MY_NAME = new int[10];217  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"218  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:19}:"{"219  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:30-[[@LINE-3]]:30}:", 10}"220  int * MY_NAME_ARG( 'x' ) = new int[10];221  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"222  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:30-[[@LINE-2]]:30}:"{"223  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:41-[[@LINE-3]]:41}:", 10}"224  p[5] = 5;225  q[5] = 5;226#undef MY_NAME227#undef MY_NAME_ARG228}229 230void unsupported_fixit_overlapping_macro(int * x) {231  int tmp;232  // In the case below, a tentative fix-it replaces `MY_INT * p =` with `std::span<MY_INT> p `.233  // The bounds of the source range of the fix-it overlap with the use of the macro234  // `MY_INT`.  The fix-it is discarded then.235 236  // FIXME: we do not have to discard a fix-it if its begin location237  // overlaps with the begin location of a macro. Similar for end238  // locations.239 240#define MY_INT int241  MY_INT * p = new int[10];242  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]243  tmp = p[5];244 245#define MY_VAR(name) int * name246  MY_VAR(q) = new int[10];247  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]248  tmp = q[5];249 250  // In cases where fix-its do not change the original code where251  // macros are used, those fix-its will be emitted.  For example,252  // fixits are inserted before and after `new MY_INT[MY_TEN]` below.253#define MY_TEN 10254  int * g = new MY_INT[MY_TEN];255  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"256  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"257  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:31-[[@LINE-3]]:31}:", MY_TEN}"258  tmp = g[5];259 260#undef MY_INT261#undef MY_VAR262#undef MY_TEN263}264 265void unsupported_subscript_negative(int i, unsigned j, unsigned long k) {266  int tmp;267  int * p = new int[10];268  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]269 270  tmp = p[-1]; // If `p` is made a span, this `[]` operation is wrong,271         // so no fix-it emitted.272 273  int * q = new int[10];274  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]275 276  tmp = q[5];277  tmp = q[i];  // If `q` is made a span, this `[]` operation may be278         // wrong as we do not know if `i` is non-negative, so279         // no fix-it emitted.280 281  int * r = new int[10];282  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"283  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"284  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"285 286  tmp = r[j] + r[k]; // both `j` and `k` are unsigned so they must be non-negative287  tmp = r[(unsigned int)-1]; // a cast-to-unsigned-expression is also non-negative288}289 290#define DEFINE_PTR(X) int* ptr = (X);291 292void all_vars_in_macro() {293  int* local;294  DEFINE_PTR(local)295  ptr[1] = 0;296}297 298void few_vars_in_macro() {299  int* local;300  DEFINE_PTR(local)301  ptr[1] = 0;302  int tmp;303  ptr[2] = 30;304  int * p = new int[10];305  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"306  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"307  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"308  tmp = p[5];309  int val = *p;310  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:14}:""311  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"[0]"312  val = *p + 30;313  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:10}:""314  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:11}:"[0]"315}316