Index: clang/lib/Analysis/UnsafeBufferUsage.cpp =================================================================== --- clang/lib/Analysis/UnsafeBufferUsage.cpp +++ clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -27,9 +27,16 @@ // Because we're dealing with raw pointers, let's define what we mean by that. static auto hasPointerType() { - return anyOf(hasType(pointerType()), - hasType(autoType(hasDeducedType( - hasUnqualifiedDesugaredType(pointerType()))))); + return anyOf( + hasType(pointerType()), + hasType(autoType( + hasDeducedType(hasUnqualifiedDesugaredType(pointerType())))), + // DecayedType, e.g., array type in formal parameter decl + hasType(decayedType(hasDecayedType(pointerType()))), + // ElaboratedType, e.g., typedef + hasType(elaboratedType(hasUnqualifiedDesugaredType(pointerType()))), + // template instantiated types + hasType(substTemplateTypeParmType(hasReplacementType(pointerType())))); } namespace { Index: clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp @@ -1,4 +1,22 @@ -// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -verify %s +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -include %s -verify %s +#ifndef INCLUDED +#define INCLUDED +#pragma clang system_header + +// no spanification warnings for system headers +void foo(...); +void testAsSystemHeader(char *p) { + ++p; + + auto ap1 = p; + auto ap2 = &p; + + foo(p[1], + ap1[1], + ap2[2][3]); +} + +#else void testIncrement(char *p) { ++p; // expected-warning{{unchecked operation on raw buffer in expression}} @@ -7,8 +25,6 @@ p--; // expected-warning{{unchecked operation on raw buffer in expression}} } -void foo(...); - void * bar(void); char * baz(void); @@ -33,7 +49,7 @@ int a[10], b[10][10]; - // not to warn subscripts on arrays + // Not to warn subscripts on arrays foo(a[0], a[1], 0[a], 1[a], b[3][4], @@ -54,9 +70,90 @@ auto ap3 = pp; - foo(pp[0][0]); // expected-warning2{{unchecked operation on raw buffer in expression}} + foo(ap3[0][0]); // expected-warning2{{unchecked operation on raw buffer in expression}} auto ap4 = *pp; foo(ap4[0]); // expected-warning{{unchecked operation on raw buffer in expression}} } + +void testQualifiedParameters(const int * p, const int * const q, + const int a[10], const int b[10][10]) { + foo(p[1], 1[p], p[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} + q[1], 1[q], q[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} + a[1], // expected-warning{{unchecked operation on raw buffer in expression}} `a` is of pointer type + b[1][2] // expected-warning{{unchecked operation on raw buffer in expression}} `b[1]` is of array type + ); +} + +struct T { + int a[10]; + int * b; + struct { + int a[10]; + int * b; + } c; +}; + +typedef struct T T_t; + +T_t funRetT(); +T_t * funRetTStar(); + +void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) { + foo(sp->a[1], + sp->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + sp->c.a[1], + sp->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + s.a[1], + s.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + s.c.a[1], + s.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + sp2->a[1], + sp2->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + sp2->c.a[1], + sp2->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + s2.a[1], + s2.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + s2.c.a[1], + s2.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + funRetT().a[1], + funRetT().b[1], // expected-warning{{unchecked operation on raw buffer in expression}} + funRetTStar()->a[1], + funRetTStar()->b[1] // expected-warning{{unchecked operation on raw buffer in expression}} + ); +} + +int garray[10]; +int * gp = garray; +int gvar = gp[1]; // TODO: this is not warned + +void testLambdaCaptureAndGlobal(int * p) { + int a[10]; + + auto Lam = [p, a]() { + return p[1] // expected-warning2{{unchecked operation on raw buffer in expression}} + + a[1] + garray[1] + + gp[1]; // expected-warning2{{unchecked operation on raw buffer in expression}} + }; +} + +typedef T_t * T_ptr_t; + +void testTypedefs(T_ptr_t p) { + foo(p[1], // expected-warning{{unchecked operation on raw buffer in expression}} + p[1].a[1], // expected-warning{{unchecked operation on raw buffer in expression}} + p[1].b[1] // expected-warning2{{unchecked operation on raw buffer in expression}} + ); +} + +template T f(T t) { + return &t[1]; // expected-warning{{unchecked operation on raw buffer in expression}} +} + +void testTemplate(int * p) { + foo(f(p)[1]); // expected-warning{{unchecked operation on raw buffer in expression}}, \ + expected-note{{in instantiation of function template specialization 'f' requested here}} +} + +#endif