[clang] 237ca43 - [-Wunsafe-buffer-usage] Group diagnostics by variable
Jan Korous via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 18 15:01:57 PST 2023
Author: Jan Korous
Date: 2023-01-18T15:00:22-08:00
New Revision: 237ca436adf48c72821afd9fa6e031ec1d4a0420
URL: https://github.com/llvm/llvm-project/commit/237ca436adf48c72821afd9fa6e031ec1d4a0420
DIFF: https://github.com/llvm/llvm-project/commit/237ca436adf48c72821afd9fa6e031ec1d4a0420.diff
LOG: [-Wunsafe-buffer-usage] Group diagnostics by variable
Differential Revision: https://reviews.llvm.org/D141356
Added:
clang/test/SemaCXX/unsafe-buffer-usage-diag-type.cpp
Modified:
clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Analysis/UnsafeBufferUsage.cpp
clang/lib/Sema/AnalysisBasedWarnings.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage-source-ranges.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
index 6a4930f40bdff..e3f87cd0f3660 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
@@ -31,7 +31,8 @@ class UnsafeBufferUsageHandler {
using FixItList = llvm::SmallVectorImpl<FixItHint>;
/// Invoked when an unsafe operation over raw pointers is found.
- virtual void handleUnsafeOperation(const Stmt *Operation) = 0;
+ virtual void handleUnsafeOperation(const Stmt *Operation,
+ bool IsRelatedToDecl) = 0;
/// Invoked when a fix is suggested against a variable.
virtual void handleFixableVariable(const VarDecl *Variable,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 02a6c2c4214e8..2ba52728e9485 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11778,12 +11778,16 @@ def err_loongarch_builtin_requires_la64 : Error<
"this builtin requires target: loongarch64">;
// Unsafe buffer usage diagnostics.
-def warn_unsafe_buffer_expression : Warning<
- "unchecked operation on raw buffer in expression">,
- InGroup<UnsafeBufferUsage>, DefaultIgnore;
def warn_unsafe_buffer_variable : Warning<
- "variable %0 participates in unchecked buffer operations">,
+ "%0 is an %select{unsafe pointer used for buffer access|unsafe buffer that "
+ "does not perform bounds checks}1">,
+ InGroup<UnsafeBufferUsage>, DefaultIgnore;
+def warn_unsafe_buffer_operation : Warning<
+ "%select{unsafe pointer operation|unsafe pointer arithmetic|"
+ "unsafe buffer access}0">,
InGroup<UnsafeBufferUsage>, DefaultIgnore;
+def note_unsafe_buffer_operation : Note<
+ "used%select{| in pointer arithmetic| in buffer access}0 here">;
def err_loongarch_builtin_requires_la32 : Error<
"this builtin requires target: loongarch32">;
} // end of sema component.
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index c75eaba820c42..ec2a09e89989b 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -680,17 +680,16 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
// FIXME Detect overlapping FixIts.
for (const auto &G : UnsafeOps.noVar) {
- Handler.handleUnsafeOperation(G->getBaseStmt());
+ Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false);
}
for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar) {
auto FixItsIt = FixItsForVariable.find(VD);
- if (FixItsIt != FixItsForVariable.end()) {
- Handler.handleFixableVariable(VD, std::move(FixItsIt->second));
- } else {
- for (const auto &G : WarningGadgets) {
- Handler.handleUnsafeOperation(G->getBaseStmt());
- }
+ Handler.handleFixableVariable(VD, FixItsIt != FixItsForVariable.end()
+ ? std::move(FixItsIt->second)
+ : FixItList{});
+ for (const auto &G : WarningGadgets) {
+ Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/true);
}
}
}
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 08cf45e5865c0..4530154ac9447 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2153,12 +2153,15 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
public:
UnsafeBufferUsageReporter(Sema &S) : S(S) {}
- void handleUnsafeOperation(const Stmt *Operation) override {
+ void handleUnsafeOperation(const Stmt *Operation,
+ bool IsRelatedToDecl) override {
SourceLocation Loc;
SourceRange Range;
+ unsigned MsgParam = 0;
if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Operation)) {
Loc = ASE->getBase()->getExprLoc();
Range = ASE->getBase()->getSourceRange();
+ MsgParam = 2;
} else if (const auto *BO = dyn_cast<BinaryOperator>(Operation)) {
BinaryOperator::Opcode Op = BO->getOpcode();
if (Op == BO_Add || Op == BO_AddAssign || Op == BO_Sub ||
@@ -2170,6 +2173,7 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
Loc = BO->getRHS()->getExprLoc();
Range = BO->getRHS()->getSourceRange();
}
+ MsgParam = 1;
}
} else if (const auto *UO = dyn_cast<UnaryOperator>(Operation)) {
UnaryOperator::Opcode Op = UO->getOpcode();
@@ -2177,20 +2181,27 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
Op == UO_PostDec) {
Loc = UO->getSubExpr()->getExprLoc();
Range = UO->getSubExpr()->getSourceRange();
+ MsgParam = 1;
}
} else {
Loc = Operation->getBeginLoc();
Range = Operation->getSourceRange();
}
- S.Diag(Loc, diag::warn_unsafe_buffer_expression) << Range;
+ if (IsRelatedToDecl)
+ S.Diag(Loc, diag::note_unsafe_buffer_operation) << MsgParam << Range;
+ else
+ S.Diag(Loc, diag::warn_unsafe_buffer_operation) << MsgParam << Range;
}
+ // FIXME: rename to handleUnsafeVariable
void handleFixableVariable(const VarDecl *Variable,
FixItList &&Fixes) override {
const auto &D =
- S.Diag(Variable->getBeginLoc(), diag::warn_unsafe_buffer_variable);
- D << Variable << Variable->getSourceRange();
- for (const auto &F: Fixes)
+ S.Diag(Variable->getLocation(), diag::warn_unsafe_buffer_variable);
+ D << Variable;
+ D << (Variable->getType()->isPointerType() ? 0 : 1);
+ D << Variable->getSourceRange();
+ for (const auto &F : Fixes)
D << F;
}
};
@@ -2489,7 +2500,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
checkThrowInNonThrowingFunc(S, FD, AC);
// Emit unsafe buffer usage warnings and fixits.
- if (!Diags.isIgnored(diag::warn_unsafe_buffer_expression, D->getBeginLoc()) ||
+ if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, D->getBeginLoc()) ||
!Diags.isIgnored(diag::warn_unsafe_buffer_variable, D->getBeginLoc())) {
UnsafeBufferUsageReporter R(S);
checkUnsafeBufferUsage(D, R);
diff --git a/clang/test/SemaCXX/unsafe-buffer-usage-diag-type.cpp b/clang/test/SemaCXX/unsafe-buffer-usage-diag-type.cpp
new file mode 100644
index 0000000000000..bf798c4970e1b
--- /dev/null
+++ b/clang/test/SemaCXX/unsafe-buffer-usage-diag-type.cpp
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage -verify %s
+
+namespace localVar {
+void testRefersPtrLocalVarDecl(int i) {
+ int * ptr; // expected-warning{{'ptr' is an unsafe pointer used for buffer access}}
+ ptr + i; // expected-note{{used in pointer arithmetic here}}
+ ptr[i]; // expected-note{{used in buffer access here}}
+}
+
+void testRefersArrayLocalVarDecl(int i) {
+ int array[i]; // expected-warning{{'array' is an unsafe buffer that does not perform bounds}}
+ array[i/2]; // expected-note{{used in buffer access here}}
+}
+}
+
+namespace globalVar {
+int * ptr; // expected-warning{{'ptr' is an unsafe pointer used for buffer access}}
+void testRefersPtrGlobalVarDecl(int i) {
+ ptr + i; // expected-note{{used in pointer arithmetic here}}
+ ptr[i]; // expected-note{{used in buffer access here}}
+}
+
+int array[10]; // expected-warning{{'array' is an unsafe buffer that does not perform bounds}}
+void testRefersArrayGlobalVarDecl(int i) {
+ array[i/2]; // expected-note{{used in buffer access here}}
+}
+}
+
+namespace functionParm {
+void testRefersPtrParmVarDecl(int * ptr) {
+ // expected-warning at -1{{'ptr' is an unsafe pointer used for buffer access}}
+ ptr + 5; // expected-note{{used in pointer arithmetic here}}
+ ptr[5]; // expected-note{{used in buffer access here}}
+}
+
+// FIXME: shall we explain the array to pointer decay to make the warning more understandable?
+void testRefersArrayParmVarDecl(int array[10]) {
+ // expected-warning at -1{{'array' is an unsafe pointer used for buffer access}}
+ array[2]; // expected-note{{used in buffer access here}}
+}
+}
+
+namespace structField {
+struct Struct1 {
+ int * ptr; // FIXME: per-declaration warning aggregated at the struct definition?
+};
+
+void testRefersPtrStructFieldDecl(int i) {
+ Struct1 s1;
+ s1.ptr + i; // expected-warning{{unsafe pointer arithmetic}}
+ s1.ptr[i]; // expected-warning{{unsafe buffer access}}
+}
+
+struct Struct2 {
+ int array[10]; // FIXME: per-declaration warning aggregated at the struct definition?
+};
+
+void testRefersArrayStructFieldDecl(int i) {
+ Struct2 s2;
+ s2.array[i/2]; // expected-warning{{unsafe buffer access}}
+}
+}
+
+namespace structFieldFromMethod {
+struct Struct1 {
+ int * ptr; // FIXME: per-declaration warning aggregated at the struct definition
+
+ void testRefersPtrStructFieldDecl(int i) {
+ ptr + i; // expected-warning{{unsafe pointer arithmetic}}
+ ptr[i]; // expected-warning{{unsafe buffer access}}
+ }
+};
+
+struct Struct2 {
+ int array[10]; // FIXME: per-declaration warning aggregated at the struct definition
+
+ void testRefersArrayStructFieldDecl(int i) {
+ Struct2 s2;
+ s2.array[i/2]; // expected-warning{{unsafe buffer access}}
+ }
+};
+}
+
+namespace staticStructField {
+struct Struct1 {
+ static int * ptr; // expected-warning{{'ptr' is an unsafe pointer used for buffer access}}
+};
+
+void testRefersPtrStructFieldDecl(int i) {
+ Struct1::ptr + i; // expected-note{{used in pointer arithmetic here}}
+ Struct1::ptr[i]; // expected-note{{used in buffer access here}}
+}
+
+struct Struct2 {
+ static int array[10]; // expected-warning{{'array' is an unsafe buffer that does not perform bounds}}
+};
+
+void testRefersArrayStructFieldDecl(int i) {
+ Struct2::array[i/2]; // expected-note{{used in buffer access here}}
+}
+}
+
+int * return_ptr();
+
+void testNoDeclRef(int i) {
+ return_ptr() + i; // expected-warning{{unsafe pointer arithmetic}}
+ return_ptr()[i]; // expected-warning{{unsafe buffer access}}
+}
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-source-ranges.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-source-ranges.cpp
index 35928cc6890ba..61b30b7f576c4 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-source-ranges.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-source-ranges.cpp
@@ -3,47 +3,46 @@
void foo(int i) {
int * ptr;
-
ptr++;
- // CHECK-DAG: {7:3-7:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
ptr--;
- // CHECK-DAG: {9:3-9:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
++ptr;
- // CHECK-DAG: {11:5-11:8}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:5-[[@LINE-1]]:8}
--ptr;
- // CHECK-DAG: {13:5-13:8}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:5-[[@LINE-1]]:8}
ptr + 1;
- // CHECK-DAG: {17:3-17:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
2 + ptr;
- // CHECK-DAG: {19:7-19:10}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:7-[[@LINE-1]]:10}
ptr + i;
- // CHECK-DAG: {21:3-21:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
i + ptr;
- // CHECK-DAG: {23:7-23:10}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:7-[[@LINE-1]]:10}
ptr - 3;
- // CHECK-DAG: {27:3-27:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
ptr - i;
- // CHECK-DAG: {29:3-29:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
ptr += 4;
- // CHECK-DAG: {33:3-33:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
ptr += i;
- // CHECK-DAG: {35:3-35:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
ptr -= 5;
- // CHECK-DAG: {39:3-39:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
ptr -= i;
- // CHECK-DAG: {41:3-41:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
ptr[5];
- // CHECK-DAG: {45:3-45:6}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:3-[[@LINE-1]]:6}
5[ptr];
- // CHECK-DAG: {47:5-47:8}{{.*}}[-Wunsafe-buffer-usage]
+ // CHECK-DAG: {[[@LINE-1]]:5-[[@LINE-1]]:8}
}
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
index 87831334746aa..a8ee6f58d140a 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
@@ -1,4 +1,10 @@
-// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fblocks -include %s -verify %s
+// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage -fblocks -include %s -verify %s
+
+// RUN: %clang -x c++ -fsyntax-only -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
+// RUN: %clang_cc1 -std=c++11 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
+// RUN: %clang_cc1 -std=c++20 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
+// CHECK-NOT: [-Wunsafe-buffer-usage]
+
#ifndef INCLUDED
#define INCLUDED
#pragma clang system_header
@@ -18,41 +24,50 @@ void testAsSystemHeader(char *p) {
#else
-void testIncrement(char *p) {
- ++p; // expected-warning{{unchecked operation on raw buffer in expression}}
- p++; // expected-warning{{unchecked operation on raw buffer in expression}}
- --p; // expected-warning{{unchecked operation on raw buffer in expression}}
- p--; // expected-warning{{unchecked operation on raw buffer in expression}}
+void testIncrement(char *p) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
+ ++p; // expected-note{{used in pointer arithmetic here}}
+ p++; // expected-note{{used in pointer arithmetic here}}
+ --p; // expected-note{{used in pointer arithmetic here}}
+ p--; // expected-note{{used in pointer arithmetic here}}
}
void * voidPtrCall(void);
char * charPtrCall(void);
void testArraySubscripts(int *p, int **pp) {
- foo(p[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- pp[1][1], // expected-warning2{{unchecked operation on raw buffer in expression}}
- 1[1[pp]], // expected-warning2{{unchecked operation on raw buffer in expression}}
- 1[pp][1] // expected-warning2{{unchecked operation on raw buffer in expression}}
+// expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+// expected-warning at -2{{'pp' is an unsafe pointer used for buffer access}}
+ foo(p[1], // expected-note{{used in buffer access here}}
+ pp[1][1], // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
+ 1[1[pp]], // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
+ 1[pp][1] // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
);
- if (p[3]) { // expected-warning{{unchecked operation on raw buffer in expression}}
+ if (p[3]) { // expected-note{{used in buffer access here}}
void * q = p;
- foo(((int*)q)[10]); // expected-warning{{unchecked operation on raw buffer in expression}}
+ foo(((int*)q)[10]); // expected-warning{{unsafe buffer access}}
}
- foo(((int*)voidPtrCall())[3], // expected-warning{{unchecked operation on raw buffer in expression}}
- 3[(int*)voidPtrCall()], // expected-warning{{unchecked operation on raw buffer in expression}}
- charPtrCall()[3], // expected-warning{{unchecked operation on raw buffer in expression}}
- 3[charPtrCall()] // expected-warning{{unchecked operation on raw buffer in expression}}
+ foo(((int*)voidPtrCall())[3], // expected-warning{{unsafe buffer access}}
+ 3[(int*)voidPtrCall()], // expected-warning{{unsafe buffer access}}
+ charPtrCall()[3], // expected-warning{{unsafe buffer access}}
+ 3[charPtrCall()] // expected-warning{{unsafe buffer access}}
);
- int a[10], b[10][10];
+ int a[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
+ int b[10][10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
- foo(a[1], 1[a], // expected-warning2{{unchecked operation on raw buffer in expression}}
- b[3][4], // expected-warning2{{unchecked operation on raw buffer in expression}}
- 4[b][3], // expected-warning2{{unchecked operation on raw buffer in expression}}
- 4[3[b]]); // expected-warning2{{unchecked operation on raw buffer in expression}}
+ foo(a[1], 1[a], // expected-note2{{used in buffer access here}}
+ b[3][4], // expected-warning{{unsafe buffer access}}
+ // expected-note at -1{{used in buffer access here}}
+ 4[b][3], // expected-warning{{unsafe buffer access}}
+ // expected-note at -1{{used in buffer access here}}
+ 4[3[b]]); // expected-warning{{unsafe buffer access}}
+ // expected-note at -1{{used in buffer access here}}
// Not to warn when index is zero
foo(p[0], pp[0][0], 0[0[pp]], 0[pp][0],
@@ -65,37 +80,41 @@ void testArraySubscripts(int *p, int **pp) {
void testArraySubscriptsWithAuto(int *p, int **pp) {
int a[10];
+ auto ap1 = a; // expected-warning{{'ap1' is an unsafe pointer used for buffer access}}
- auto ap1 = a;
+ foo(ap1[1]); // expected-note{{used in buffer access here}}
- foo(ap1[1]); // expected-warning{{unchecked operation on raw buffer in expression}}
+ auto ap2 = p; // expected-warning{{'ap2' is an unsafe pointer used for buffer access}}
- auto ap2 = p;
+ foo(ap2[1]); // expected-note{{used in buffer access here}}
- foo(ap2[1]); // expected-warning{{unchecked operation on raw buffer in expression}}
+ auto ap3 = pp; // expected-warning{{'ap3' is an unsafe pointer used for buffer access}}
- auto ap3 = pp;
+ foo(ap3[1][1]); // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
- foo(ap3[1][1]); // expected-warning2{{unchecked operation on raw buffer in expression}}
+ auto ap4 = *pp; // expected-warning{{'ap4' is an unsafe pointer used for buffer access}}
- auto ap4 = *pp;
-
- foo(ap4[1]); // expected-warning{{unchecked operation on raw buffer in expression}}
+ foo(ap4[1]); // expected-note{{used in buffer access here}}
}
-void testUnevaluatedContext(int * p) {
- //TODO: do not warn for unevaluated context
- foo(sizeof(p[1]), // expected-warning{{unchecked operation on raw buffer in expression}}
- sizeof(decltype(p[1]))); // expected-warning{{unchecked operation on raw buffer in expression}}
+//TODO: do not warn for unevaluated context
+void testUnevaluatedContext(int * p) {// expected-warning{{'p' is an unsafe pointer used for buffer access}}
+ foo(sizeof(p[1]), // expected-note{{used in buffer access here}}
+ sizeof(decltype(p[1]))); // expected-note{{used in buffer access here}}
}
-void testQualifiedParameters(const int * p, const int * const q,
- const int a[10], const int b[10][10],
- int (&c)[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-warning2{{unchecked operation on raw buffer in expression}} `b[1]` is of array type
+void testQualifiedParameters(const int * p, const int * const q, const int a[10], const int b[10][10]) {
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ // expected-warning at -2{{'q' is an unsafe pointer used for buffer access}}
+ // expected-warning at -3{{'a' is an unsafe pointer used for buffer access}}
+ // expected-warning at -4{{'b' is an unsafe pointer used for buffer access}}
+
+ foo(p[1], 1[p], p[-1], // expected-note3{{used in buffer access here}}
+ q[1], 1[q], q[-1], // expected-note3{{used in buffer access here}}
+ a[1], // expected-note{{used in buffer access here}} `a` is of pointer type
+ b[1][2] // expected-note{{used in buffer access here}} `b[1]` is of array type
+ // expected-warning at -1{{unsafe buffer access}}
);
}
@@ -114,57 +133,66 @@ T_t funRetT();
T_t * funRetTStar();
void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) {
- foo(sp->a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- sp->b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- sp->c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- sp->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s.a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s.b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s.c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- sp2->a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- sp2->b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- sp2->c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- sp2->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s2.a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s2.b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s2.c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- s2.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- funRetT().a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- funRetT().b[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- funRetTStar()->a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- funRetTStar()->b[1] // expected-warning{{unchecked operation on raw buffer in expression}}
- );
+ foo(sp->a[1], // expected-warning{{unsafe buffer access}}
+ sp->b[1], // expected-warning{{unsafe buffer access}}
+ sp->c.a[1], // expected-warning{{unsafe buffer access}}
+ sp->c.b[1], // expected-warning{{unsafe buffer access}}
+ s.a[1], // expected-warning{{unsafe buffer access}}
+ s.b[1], // expected-warning{{unsafe buffer access}}
+ s.c.a[1], // expected-warning{{unsafe buffer access}}
+ s.c.b[1], // expected-warning{{unsafe buffer access}}
+ sp2->a[1], // expected-warning{{unsafe buffer access}}
+ sp2->b[1], // expected-warning{{unsafe buffer access}}
+ sp2->c.a[1], // expected-warning{{unsafe buffer access}}
+ sp2->c.b[1], // expected-warning{{unsafe buffer access}}
+ s2.a[1], // expected-warning{{unsafe buffer access}}
+ s2.b[1], // expected-warning{{unsafe buffer access}}
+ s2.c.a[1], // expected-warning{{unsafe buffer access}}
+ s2.c.b[1], // expected-warning{{unsafe buffer access}}
+ funRetT().a[1], // expected-warning{{unsafe buffer access}}
+ funRetT().b[1], // expected-warning{{unsafe buffer access}}
+ funRetTStar()->a[1], // expected-warning{{unsafe buffer access}}
+ funRetTStar()->b[1] // expected-warning{{unsafe buffer access}}
+ );
}
-int garray[10];
-int * gp = garray;
-int gvar = gp[1]; // FIXME: file scope unsafe buffer access is not warned
+int garray[10]; // expected-warning{{'garray' is an unsafe buffer that does not perform bounds checks}}
+int * gp = garray; // expected-warning{{'gp' is an unsafe pointer used for buffer access}}
+int gvar = gp[1]; // FIXME: file scope unsafe buffer access is not warned
+// FIXME: Add test for lambda capture with initializer. E. g. auto Lam = [new_p = p]() {...
void testLambdaCaptureAndGlobal(int * p) {
- int a[10];
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ int a[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
auto Lam = [p, a]() {
- return p[1] // expected-warning{{unchecked operation on raw buffer in expression}}
- + a[1] + garray[1] // expected-warning2{{unchecked operation on raw buffer in expression}}
- + gp[1]; // expected-warning{{unchecked operation on raw buffer in expression}}
+ return p[1] // expected-note{{used in buffer access here}}
+ + a[1] + garray[1] // expected-note2{{used in buffer access here}}
+ + gp[1]; // expected-note{{used in buffer access here}}
};
}
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-warning2{{unchecked operation on raw buffer in expression}}
- p[1].b[1] // expected-warning2{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ foo(p[1], // expected-note{{used in buffer access here}}
+ p[1].a[1], // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
+ p[1].b[1] // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
);
}
template<typename T, int N> T f(T t, T * pt, T a[N], T (&b)[N]) {
- foo(pt[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- a[1], // expected-warning{{unchecked operation on raw buffer in expression}}
- b[1]); // expected-warning{{unchecked operation on raw buffer in expression}}
- return &t[1]; // expected-warning{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'t' is an unsafe pointer used for buffer access}}
+ // expected-warning at -2{{'pt' is an unsafe pointer used for buffer access}}
+ // expected-warning at -3{{'a' is an unsafe pointer used for buffer access}}
+ // expected-warning at -4{{'b' is an unsafe buffer that does not perform bounds checks}}
+ foo(pt[1], // expected-note{{used in buffer access here}}
+ a[1], // expected-note{{used in buffer access here}}
+ b[1]); // expected-note{{used in buffer access here}}
+ return &t[1]; // expected-note{{used in buffer access here}}
}
// Testing pointer arithmetic for pointer-to-int, qualified multi-level
@@ -173,30 +201,32 @@ T_ptr_t getPtr();
template<typename T>
void testPointerArithmetic(int * p, const int **q, T * x) {
+// expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+// expected-warning at -2{{'x' is an unsafe pointer used for buffer access}}
int a[10];
- auto y = &a[0];
+ auto y = &a[0]; // expected-warning{{'y' is an unsafe pointer used for buffer access}}
- 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}}
- x + 1, 1 + x, x - 1, // expected-warning3{{unchecked operation on raw buffer in expression}}
- y + 1, 1 + y, y - 1, // expected-warning3{{unchecked operation on raw buffer in expression}}
- getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unchecked operation on raw buffer in expression}}
+ foo(p + 1, 1 + p, p - 1, // expected-note3{{used in pointer arithmetic here}}
+ *q + 1, 1 + *q, *q - 1, // expected-warning3{{unsafe pointer arithmetic}}
+ x + 1, 1 + x, x - 1, // expected-note3{{used in pointer arithmetic here}}
+ y + 1, 1 + y, y - 1, // expected-note3{{used in pointer arithmetic here}}
+ getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unsafe pointer arithmetic}}
);
- p += 1; p -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}}
- *q += 1; *q -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}}
- y += 1; y -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}}
- x += 1; x -= 1; // expected-warning2{{unchecked operation on raw buffer in expression}}
+ p += 1; p -= 1; // expected-note2{{used in pointer arithmetic here}}
+ *q += 1; *q -= 1; // expected-warning2{{unsafe pointer arithmetic}}
+ y += 1; y -= 1; // expected-note2{{used in pointer arithmetic here}}
+ x += 1; x -= 1; // expected-note2{{used in pointer arithmetic here}}
}
void testTemplate(int * p) {
int *a[10];
- foo(f(p, &p, a, a)[1]); // expected-warning{{unchecked operation on raw buffer in expression}}, \
- expected-note{{in instantiation of function template specialization 'f<int *, 10>' requested here}}
+ foo(f(p, &p, a, a)[1]); // expected-warning{{unsafe buffer access}}
+ // expected-note at -1{{in instantiation of function template specialization 'f<int *, 10>' requested here}}
const int **q = const_cast<const int **>(&p);
- testPointerArithmetic(p, q, p); //expected-note{{in instantiation of function template specialization 'testPointerArithmetic<int>' requested here}}
+ testPointerArithmetic(p, q, p); //expected-note{{in instantiation of}}
}
void testPointerToMember() {
@@ -209,106 +239,125 @@ void testPointerToMember() {
int * S_t::* q = &S_t::y;
foo(S.*p,
- (S.*q)[1]); // expected-warning{{unchecked operation on raw buffer in expression}}
+ (S.*q)[1]); // expected-warning{{unsafe buffer access}}
}
// test that nested callable definitions are scanned only once
void testNestedCallableDefinition(int * p) {
class A {
void inner(int * p) {
- p++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ p++; // expected-note{{used in pointer arithmetic here}}
}
static void innerStatic(int * p) {
- p++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ p++; // expected-note{{used in pointer arithmetic here}}
}
void innerInner(int * p) {
auto Lam = [p]() {
- int * q = p;
- q++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ int * q = p; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
+ q++; // expected-note{{used in pointer arithmetic here}}
return *q;
};
}
};
auto Lam = [p]() {
- int * q = p;
- q++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ int * q = p; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
+ q++; // expected-note{{used in pointer arithmetic here}}
return *q;
};
auto LamLam = [p]() {
auto Lam = [p]() {
- int * q = p;
- q++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ int * q = p; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
+ q++; // expected-note{{used in pointer arithmetic here}}
return *q;
};
};
void (^Blk)(int*) = ^(int *p) {
- p++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ p++; // expected-note{{used in pointer arithmetic here}}
};
void (^BlkBlk)(int*) = ^(int *p) {
void (^Blk)(int*) = ^(int *p) {
- p++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ p++; // expected-note{{used in pointer arithmetic here}}
};
Blk(p);
};
// lambda and block as call arguments...
- foo( [p]() { int * q = p;
- q++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ foo( [p]() { int * q = p; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
+ q++; // expected-note{{used in pointer arithmetic here}}
return *q;
},
- ^(int *p) { p++; // expected-warning{{unchecked operation on raw buffer in expression}}
+ ^(int *p) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
+ p++; // expected-note{{used in pointer arithmetic here}}
}
);
}
int testVariableDecls(int * p) {
- int * q = p++; // expected-warning{{unchecked operation on raw buffer in expression}}
- int a[p[1]]; // expected-warning{{unchecked operation on raw buffer in expression}}
- int b = p[1]; // expected-warning{{unchecked operation on raw buffer in expression}}
- return p[1]; // expected-warning{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'p' is an unsafe pointer used for buffer access}}
+ int * q = p++; // expected-note{{used in pointer arithmetic here}}
+ int a[p[1]]; // expected-note{{used in buffer access here}}
+ int b = p[1]; // expected-note{{used in buffer access here}}
+ return p[1]; // expected-note{{used in buffer access here}}
}
-
+
template<typename T> void fArr(T t[]) {
- foo(t[1]); // expected-warning{{unchecked operation on raw buffer in expression}}
- T ar[8];
- foo(ar[5]); // expected-warning{{unchecked operation on raw buffer in expression}}
+ // expected-warning at -1{{'t' is an unsafe pointer used for buffer access}}
+ foo(t[1]); // expected-note{{used in buffer access here}}
+ T ar[8]; // expected-warning{{'ar' is an unsafe buffer that does not perform bounds checks}}
+ foo(ar[5]); // expected-note{{used in buffer access here}}
}
-template void fArr<int>(int t[]); // expected-note {{in instantiation of function template specialization 'fArr<int>' requested here}}
+template void fArr<int>(int t[]); // expected-note {{in instantiation of}}
+
+int testReturn(int t[]) {
+ // expected-warning at -1{{'t' is an unsafe pointer used for buffer access}}
+ return t[1]; // expected-note{{used in buffer access here}}
+}
- int testReturn(int t[]) {
- return t[1]; // expected-warning{{unchecked operation on raw buffer in expression}}
- }
-
-//FIXME: Array access warnings on 0-indices;ArraySubscriptGadget excludes 0 index for both raw pointers and arrays!
int testArrayAccesses(int n) {
-
- // auto deduced array type
- int cArr[2][3] = {{1, 2, 3}, {4, 5, 6}};
- int d = cArr[0][0];
- foo(cArr[0][0]);
- foo(cArr[1][2]); // expected-warning2{{unchecked operation on raw buffer in expression}}
- auto cPtr = cArr[1][2]; // expected-warning2{{unchecked operation on raw buffer in expression}}
- foo(cPtr);
-
- // Typdefs
- typedef int A[3];
- const A tArr = {4, 5, 6};
- foo(tArr[0], tArr[1]); // expected-warning{{unchecked operation on raw buffer in expression}}
- return cArr[0][1]; // expected-warning{{unchecked operation on raw buffer in expression}}
+ // auto deduced array type
+ int cArr[2][3] = {{1, 2, 3}, {4, 5, 6}};
+ // expected-warning at -1{{'cArr' is an unsafe buffer that does not perform bounds checks}}
+ int d = cArr[0][0];
+ foo(cArr[0][0]);
+ foo(cArr[1][2]); // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
+ auto cPtr = cArr[1][2]; // expected-note{{used in buffer access here}}
+ // expected-warning at -1{{unsafe buffer access}}
+ foo(cPtr);
+
+ // Typdefs
+ typedef int A[3];
+ const A tArr = {4, 5, 6};
+ // expected-warning at -1{{'tArr' is an unsafe buffer that does not perform bounds checks}}
+ foo(tArr[0], tArr[1]); // expected-note{{used in buffer access here}}
+ return cArr[0][1]; // expected-warning{{unsafe buffer access}}
}
-
-void testArrayPtrArithmetic(int x[]) {
- foo (x + 3); // expected-warning{{unchecked operation on raw buffer in expression}}
-
- int y[3] = {0, 1, 2};
- foo(y + 4); // expected-warning{{unchecked operation on raw buffer in expression}}
+
+void testArrayPtrArithmetic(int x[]) { // expected-warning{{'x' is an unsafe pointer used for buffer access}}
+ foo (x + 3); // expected-note{{used in pointer arithmetic here}}
+
+ int y[3] = {0, 1, 2}; // expected-warning{{'y' is an unsafe buffer that does not perform bounds checks}}
+ foo(y + 4); // expected-note{{used in pointer arithmetic here}}
+}
+
+void testMultiLineDeclStmt(int * p) {
+ auto
+
+
+ ap1 = p; // expected-warning{{'ap1' is an unsafe pointer used for buffer access}}
+
+ foo(ap1[1]); // expected-note{{used in buffer access here}}
}
#endif
More information about the cfe-commits
mailing list