xref: /llvm-project/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp (revision de8b2f0c69c8bc13a248691ef9ad9a1c10d81392)
1*de8b2f0cSziqingluo-90 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -fsafe-buffer-usage-suggestions %s 2>&1 | FileCheck %s
21e270be0Sziqingluo-90 
31e270be0Sziqingluo-90 // TODO test if there's not a single character in the file after a decl or def
41e270be0Sziqingluo-90 
5*de8b2f0cSziqingluo-90 #include "warn-unsafe-buffer-usage-fixits-parm-span.h"
61e270be0Sziqingluo-90 
71e270be0Sziqingluo-90 void simple(int *);
8*de8b2f0cSziqingluo-90 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
9*de8b2f0cSziqingluo-90 // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:19-[[@LINE-2]]:19}:";\nvoid simple(std::span<int>)"
101e270be0Sziqingluo-90 
simple(int * p)111e270be0Sziqingluo-90 void simple(int *p) {
12*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:13-[[@LINE-1]]:19}:"std::span<int> p"
131e270be0Sziqingluo-90   int tmp;
141e270be0Sziqingluo-90   tmp = p[5];
151e270be0Sziqingluo-90 }
16*de8b2f0cSziqingluo-90 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void simple(int *p) {return simple(std::span<int>(p, <# size #>));}\n"
17*de8b2f0cSziqingluo-90 
18*de8b2f0cSziqingluo-90 // CHECK: fix-it:"{{.*}}warn-unsafe-buffer-usage-fixits-parm-span.h":{1:1-1:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
19*de8b2f0cSziqingluo-90 // CHECK: fix-it:"{{.*}}warn-unsafe-buffer-usage-fixits-parm-span.h":{1:20-1:20}:";\nvoid simple(std::span<int> p)"
201e270be0Sziqingluo-90 
211e270be0Sziqingluo-90 
twoParms(int * p,int * q)221e270be0Sziqingluo-90 void twoParms(int *p, int * q) {
23*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:15-[[@LINE-1]]:21}:"std::span<int> p"
24*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:23-[[@LINE-2]]:30}:"std::span<int> q"
251e270be0Sziqingluo-90   int tmp;
261e270be0Sziqingluo-90   tmp = p[5] + q[5];
271e270be0Sziqingluo-90 }
28*de8b2f0cSziqingluo-90 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void twoParms(int *p, int * q) {return twoParms(std::span<int>(p, <# size #>), std::span<int>(q, <# size #>));}\n"
291e270be0Sziqingluo-90 
ptrToConst(const int * x)301e270be0Sziqingluo-90 void ptrToConst(const int * x) {
31*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:17-[[@LINE-1]]:30}:"std::span<int const> x"
321e270be0Sziqingluo-90   int tmp = x[5];
331e270be0Sziqingluo-90 }
34*de8b2f0cSziqingluo-90 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void ptrToConst(const int * x) {return ptrToConst(std::span<int const>(x, <# size #>));}\n"
351e270be0Sziqingluo-90 
361e270be0Sziqingluo-90 // The followings test cases where multiple FileIDs maybe involved
371e270be0Sziqingluo-90 // when the analyzer loads characters from source files.
381e270be0Sziqingluo-90 
391e270be0Sziqingluo-90 #define FUN_NAME(x) _##x##_
401e270be0Sziqingluo-90 
411e270be0Sziqingluo-90 // The analyzer reads `void FUNNAME(macro_defined_name)(` from the
421e270be0Sziqingluo-90 // source file.  The MACRO and this source file have different
431e270be0Sziqingluo-90 // FileIDs.
FUN_NAME(macro_defined_name)441e270be0Sziqingluo-90 void FUN_NAME(macro_defined_name)(int * x) {
45*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:35-[[@LINE-1]]:42}:"std::span<int> x"
461e270be0Sziqingluo-90   int tmp = x[5];
471e270be0Sziqingluo-90 }
48*de8b2f0cSziqingluo-90 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void FUN_NAME(macro_defined_name)(int * x) {return FUN_NAME(macro_defined_name)(std::span<int>(x, <# size #>));}\n"
491e270be0Sziqingluo-90 
501e270be0Sziqingluo-90 
511e270be0Sziqingluo-90 // The followings test various type specifiers
521e270be0Sziqingluo-90 namespace {
simpleSpecifier(unsigned long long int * p)531e270be0Sziqingluo-90   void simpleSpecifier(unsigned long long int *p) {
54*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:24-[[@LINE-1]]:49}:"std::span<unsigned long long int> p"
551e270be0Sziqingluo-90     auto tmp = p[5];
561e270be0Sziqingluo-90   }
57*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void simpleSpecifier(unsigned long long int *p) {return simpleSpecifier(std::span<unsigned long long int>(p, <# size #>));}\n"
581e270be0Sziqingluo-90 
attrParm(int * p)591e270be0Sziqingluo-90   void attrParm([[maybe_unused]] int * p) {
60*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:34-[[@LINE-1]]:41}:"std::span<int> p"
611e270be0Sziqingluo-90     int tmp = p[5];
621e270be0Sziqingluo-90   }
63*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void attrParm({{\[}}{{\[}}maybe_unused{{\]}}{{\]}} int * p) {return attrParm(std::span<int>(p, <# size #>));}\n"
641e270be0Sziqingluo-90 
651e270be0Sziqingluo-90   using T = unsigned long long int;
661e270be0Sziqingluo-90 
usingTypenameSpecifier(T * p)671e270be0Sziqingluo-90   void usingTypenameSpecifier(T * p) {
68*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:31-[[@LINE-1]]:36}:"std::span<T> p"
691e270be0Sziqingluo-90     int tmp = p[5];
701e270be0Sziqingluo-90   }
71*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void usingTypenameSpecifier(T * p) {return usingTypenameSpecifier(std::span<T>(p, <# size #>));}\n"
721e270be0Sziqingluo-90 
731e270be0Sziqingluo-90   typedef unsigned long long int T2;
741e270be0Sziqingluo-90 
typedefSpecifier(T2 * p)751e270be0Sziqingluo-90   void typedefSpecifier(T2 * p) {
76*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:31}:"std::span<T2> p"
771e270be0Sziqingluo-90     int tmp = p[5];
781e270be0Sziqingluo-90   }
79*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void typedefSpecifier(T2 * p) {return typedefSpecifier(std::span<T2>(p, <# size #>));}\n"
801e270be0Sziqingluo-90 
811e270be0Sziqingluo-90   class SomeClass {
821e270be0Sziqingluo-90   } C;
831e270be0Sziqingluo-90 
classTypeSpecifier(const class SomeClass * p)841e270be0Sziqingluo-90   void classTypeSpecifier(const class SomeClass * p) {
85*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:27-[[@LINE-1]]:52}:"std::span<class SomeClass const> p"
861e270be0Sziqingluo-90     if (++p) {}
871e270be0Sziqingluo-90   }
88*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void classTypeSpecifier(const class SomeClass * p) {return classTypeSpecifier(std::span<class SomeClass const>(p, <# size #>));}\n"
891e270be0Sziqingluo-90 
901e270be0Sziqingluo-90   struct {
911e270be0Sziqingluo-90     // anon
921e270be0Sziqingluo-90   } ANON_S;
931e270be0Sziqingluo-90 
941e270be0Sziqingluo-90   struct MyStruct {
951e270be0Sziqingluo-90     // namned
961e270be0Sziqingluo-90   } NAMED_S;
971e270be0Sziqingluo-90 
9833f6161dSZiqing Luo 
991e270be0Sziqingluo-90   // FIXME: `decltype(ANON_S)` represents an unnamed type but it can
1001e270be0Sziqingluo-90   // be referred as "`decltype(ANON_S)`", so the analysis should
1011e270be0Sziqingluo-90   // fix-it.
10233f6161dSZiqing Luo   // As parameter `q` cannot be fixed, fixes to parameters are all being given up.
decltypeSpecifierAnon(decltype(C) * p,decltype(ANON_S) * q,decltype(NAMED_S) * r,decltype(NAMED_S) ** rr)10333f6161dSZiqing Luo   void decltypeSpecifierAnon(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,
1041e270be0Sziqingluo-90                              decltype(NAMED_S) ** rr) {
10533f6161dSZiqing Luo     // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:30-[[@LINE-2]]:45}:"std::span<decltype(C)> p"
10633f6161dSZiqing Luo     // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:47-[[@LINE-3]]:67}:"std::span<decltype(ANON_S)> q"
10733f6161dSZiqing Luo     // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:69-[[@LINE-4]]:90}:"std::span<decltype(NAMED_S)> r"
10833f6161dSZiqing Luo     // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:53}:"std::span<decltype(NAMED_S) *> rr"
1091e270be0Sziqingluo-90     if (++p) {}
1101e270be0Sziqingluo-90     if (++q) {}
1111e270be0Sziqingluo-90     if (++r) {}
1121e270be0Sziqingluo-90     if (++rr) {}
1131e270be0Sziqingluo-90   }
114*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decltypeSpecifierAnon(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,\n decltype(NAMED_S) ** rr) {return decltypeSpecifierAnon(std::span<decltype(C)>(p, <# size #>), std::span<decltype(ANON_S)>(q, <# size #>), std::span<decltype(NAMED_S)>(r, <# size #>), std::span<decltype(NAMED_S) *>(rr, <# size #>));}\n
11533f6161dSZiqing Luo 
decltypeSpecifier(decltype(C) * p,decltype(NAMED_S) * r,decltype(NAMED_S) ** rr)11633f6161dSZiqing Luo   void decltypeSpecifier(decltype(C) * p, decltype(NAMED_S) * r, decltype(NAMED_S) ** rr) {
117*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:26-[[@LINE-1]]:41}:"std::span<decltype(C)> p"
118*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:43-[[@LINE-2]]:64}:"std::span<decltype(NAMED_S)> r"
119*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:66-[[@LINE-3]]:89}:"std::span<decltype(NAMED_S) *> rr"
12033f6161dSZiqing Luo     if (++p) {}
12133f6161dSZiqing Luo     if (++r) {}
12233f6161dSZiqing Luo     if (++rr) {}
12333f6161dSZiqing Luo   }
124*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decltypeSpecifier(decltype(C) * p, decltype(NAMED_S) * r, decltype(NAMED_S) ** rr) {return decltypeSpecifier(std::span<decltype(C)>(p, <# size #>), std::span<decltype(NAMED_S)>(r, <# size #>), std::span<decltype(NAMED_S) *>(rr, <# size #>));}\n
1251e270be0Sziqingluo-90 
1261e270be0Sziqingluo-90 #define MACRO_TYPE(T) long T
1271e270be0Sziqingluo-90 
macroType(unsigned MACRO_TYPE (int)* p,unsigned MACRO_TYPE (long)* q)1281e270be0Sziqingluo-90   void macroType(unsigned MACRO_TYPE(int) * p, unsigned MACRO_TYPE(long) * q) {
129*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:18-[[@LINE-1]]:46}:"std::span<unsigned MACRO_TYPE(int)> p"
130*de8b2f0cSziqingluo-90     // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:48-[[@LINE-2]]:77}:"std::span<unsigned MACRO_TYPE(long)> q"
1311e270be0Sziqingluo-90     int tmp = p[5];
1321e270be0Sziqingluo-90     tmp = q[5];
1331e270be0Sziqingluo-90   }
134*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void macroType(unsigned MACRO_TYPE(int) * p, unsigned MACRO_TYPE(long) * q) {return macroType(std::span<unsigned MACRO_TYPE(int)>(p, <# size #>), std::span<unsigned MACRO_TYPE(long)>(q, <# size #>));}\n"
1351e270be0Sziqingluo-90 }
1361e270be0Sziqingluo-90 
1371e270be0Sziqingluo-90 // The followings test various declarators:
decayedArray(int a[])1381e270be0Sziqingluo-90 void decayedArray(int a[]) {
139*de8b2f0cSziqingluo-90   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:19-[[@LINE-1]]:26}:"std::span<int> a"
1401e270be0Sziqingluo-90   int tmp;
1411e270be0Sziqingluo-90   tmp = a[5];
1421e270be0Sziqingluo-90 }
143*de8b2f0cSziqingluo-90 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decayedArray(int a[]) {return decayedArray(std::span<int>(a, <# size #>));}\n"
1441e270be0Sziqingluo-90 
decayedArrayOfArray(int a[10][10])1451e270be0Sziqingluo-90 void decayedArrayOfArray(int a[10][10]) {
1461e270be0Sziqingluo-90   // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
1471e270be0Sziqingluo-90   if (++a){}
1481e270be0Sziqingluo-90 }
1491e270be0Sziqingluo-90 
complexDeclarator(int * (* a[10])[10])1501e270be0Sziqingluo-90 void complexDeclarator(int * (*a[10])[10]) {
1511e270be0Sziqingluo-90   // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
1521e270be0Sziqingluo-90   if (++a){}
1531e270be0Sziqingluo-90 }
1541e270be0Sziqingluo-90 
15541279e87SZiqing Luo // Tests parameters with cv-qualifiers
1561e270be0Sziqingluo-90 
const_ptr(int * const x)15741279e87SZiqing Luo void const_ptr(int * const x) { // expected-warning{{'x' is an unsafe pointer used for buffer access}} expected-note{{change type of 'x' to 'std::span' to preserve bounds information}}
15841279e87SZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:16-[[@LINE-1]]:29}:"std::span<int> const x"
15941279e87SZiqing Luo   int tmp = x[5]; // expected-note{{used in buffer access here}}
1601e270be0Sziqingluo-90 }
16141279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void const_ptr(int * const x) {return const_ptr(std::span<int>(x, <# size #>));}\n"
1621e270be0Sziqingluo-90 
const_ptr_to_const(const int * const x)16341279e87SZiqing Luo void const_ptr_to_const(const int * const x) {// expected-warning{{'x' is an unsafe pointer used for buffer access}} expected-note{{change type of 'x' to 'std::span' to preserve bounds information}}
16441279e87SZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:44}:"std::span<int const> const x"
16541279e87SZiqing Luo   int tmp = x[5]; // expected-note{{used in buffer access here}}
16641279e87SZiqing Luo }
16741279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void const_ptr_to_const(const int * const x) {return const_ptr_to_const(std::span<int const>(x, <# size #>));}\n"
16841279e87SZiqing Luo 
const_volatile_ptr(int * const volatile x)16941279e87SZiqing Luo void const_volatile_ptr(int * const volatile x) { // expected-warning{{'x' is an unsafe pointer used for buffer access}} expected-note{{change type of 'x' to 'std::span' to preserve bounds information}}
17041279e87SZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:47}:"std::span<int> const volatile x"
17141279e87SZiqing Luo   int tmp = x[5]; // expected-note{{used in buffer access here}}
17241279e87SZiqing Luo }
17341279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void const_volatile_ptr(int * const volatile x) {return const_volatile_ptr(std::span<int>(x, <# size #>));}\n"
17441279e87SZiqing Luo 
volatile_const_ptr(int * volatile const x)17541279e87SZiqing Luo void volatile_const_ptr(int * volatile const x) { // expected-warning{{'x' is an unsafe pointer used for buffer access}} expected-note{{change type of 'x' to 'std::span' to preserve bounds information}}
17641279e87SZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:47}:"std::span<int> const volatile x"
17741279e87SZiqing Luo   int tmp = x[5]; // expected-note{{used in buffer access here}}
17841279e87SZiqing Luo }
17941279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void volatile_const_ptr(int * volatile const x) {return volatile_const_ptr(std::span<int>(x, <# size #>));}\n"
18041279e87SZiqing Luo 
const_volatile_ptr_to_const_volatile(const volatile int * const volatile x)18141279e87SZiqing Luo void const_volatile_ptr_to_const_volatile(const volatile int * const volatile x) {// expected-warning{{'x' is an unsafe pointer used for buffer access}} expected-note{{change type of 'x' to 'std::span' to preserve bounds information}}
18241279e87SZiqing Luo   // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:43-[[@LINE-1]]:80}:"std::span<int const volatile> const volatile x"
18341279e87SZiqing Luo   int tmp = x[5]; // expected-note{{used in buffer access here}}
18441279e87SZiqing Luo }
18541279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void const_volatile_ptr_to_const_volatile(const volatile int * const volatile x) {return const_volatile_ptr_to_const_volatile(std::span<int const volatile>(x, <# size #>));}\n"
18641279e87SZiqing Luo 
18741279e87SZiqing Luo 
18841279e87SZiqing Luo // Test if function declaration specifiers are handled correctly:
18941279e87SZiqing Luo 
static_f(int * p)19041279e87SZiqing Luo static void static_f(int *p) {
1914b5f17e0SZiqing Luo   p[5] = 5;
1924b5f17e0SZiqing Luo }
19341279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} static void static_f(int *p) {return static_f(std::span<int>(p, <# size #>));}\n"
19441279e87SZiqing Luo 
static_inline_f(int * p)19541279e87SZiqing Luo static inline void static_inline_f(int *p) {
19641279e87SZiqing Luo   p[5] = 5;
19741279e87SZiqing Luo }
19841279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} static inline void static_inline_f(int *p) {return static_inline_f(std::span<int>(p, <# size #>));}\n"
19941279e87SZiqing Luo 
static_inline_f2(int * p)20041279e87SZiqing Luo inline void static static_inline_f2(int *p) {
20141279e87SZiqing Luo   p[5] = 5;
20241279e87SZiqing Luo }
20341279e87SZiqing Luo // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} inline void static static_inline_f2(int *p) {return static_inline_f2(std::span<int>(p, <# size #>));}\n"
20441279e87SZiqing Luo 
20541279e87SZiqing Luo 
20641279e87SZiqing Luo // Test when unnamed types are involved:
20741279e87SZiqing Luo 
20841279e87SZiqing Luo typedef struct {int x;} UNNAMED_STRUCT;
20941279e87SZiqing Luo struct {int x;} VarOfUnnamedType;
21041279e87SZiqing Luo 
useUnnamedType(UNNAMED_STRUCT * p)21141279e87SZiqing Luo void useUnnamedType(UNNAMED_STRUCT * p) {  // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
21241279e87SZiqing Luo                                               expected-note{{change type of 'p' to 'std::span' to preserve bounds information}}
21341279e87SZiqing Luo   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:21-[[@LINE-2]]:39}:"std::span<UNNAMED_STRUCT> p"
21441279e87SZiqing Luo   if (++p) {  // expected-note{{used in pointer arithmetic here}}
21541279e87SZiqing Luo     // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:10}:"(p = p.subspan(1)).data()"
21641279e87SZiqing Luo   }
21741279e87SZiqing Luo }
21841279e87SZiqing Luo // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void useUnnamedType(UNNAMED_STRUCT * p) {return useUnnamedType(std::span<UNNAMED_STRUCT>(p, <# size #>));}\n"
21941279e87SZiqing Luo 
useUnnamedType2(decltype(VarOfUnnamedType) * p)22041279e87SZiqing Luo void useUnnamedType2(decltype(VarOfUnnamedType) * p) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
22141279e87SZiqing Luo 						          expected-note{{change type of 'p' to 'std::span' to preserve bounds information}}
22241279e87SZiqing Luo   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:22-[[@LINE-2]]:52}:"std::span<decltype(VarOfUnnamedType)> p"
22341279e87SZiqing Luo   if (++p) {  // expected-note{{used in pointer arithmetic here}}
22441279e87SZiqing Luo     // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:10}:"(p = p.subspan(1)).data()"
22541279e87SZiqing Luo   }
22641279e87SZiqing Luo }
22741279e87SZiqing Luo // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void useUnnamedType2(decltype(VarOfUnnamedType) * p) {return useUnnamedType2(std::span<decltype(VarOfUnnamedType)>(p, <# size #>));}\n"
2284b5f17e0SZiqing Luo 
229