[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