[PATCH] D154880: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage.

2023-07-26 Thread Rashmi Mudduluru via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa6ae740e743a: [-Wunsafe-buffer-usage] Add a facility for 
debugging low fixit coverage (authored by t-rasmud).
Herald added a project: clang.

Changed prior to commit:
  https://reviews.llvm.org/D154880?vs=544547=544561#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154880/new/

https://reviews.llvm.org/D154880

Files:
  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-debug.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -verify=expected %s
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -verify=expected,debug %s
+
+// A generic -debug would also enable our notes. This is probably fine.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -mllvm -debug \
+// RUN:-verify=expected,debug %s
+
+// This test file checks the behavior under the assumption that no fixits
+// were emitted for the test cases. If -Wunsafe-buffer-usage is improved
+// to support these cases (thus failing the test), the test should be changed
+// to showcase a different unsupported example.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -fdiagnostics-parseable-fixits %s \
+// RUN:2>&1 | FileCheck %s
+// CHECK-NOT: fix-it:
+
+// This debugging facility is only available in debug builds.
+//
+// REQUIRES: asserts
+
+void foo() {
+  int *x = new int[10]; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
+  x[5] = 10;// expected-note{{used in buffer access here}}
+  int z = x[-1];// expected-note{{used in buffer access here}} \
+// debug-note{{safe buffers debug: gadget 'ULCArraySubscript' refused to produce a fix}}
+}
+
+void failed_decl() {
+  int a[10];  // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : not a pointer}}
+  
+  for (int i = 0; i < 10; i++) {
+a[i] = i;  // expected-note{{used in buffer access here}}
+  }
+}
+
+void failed_multiple_decl() {
+  int *a = new int[4], b;  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : multiple VarDecls}}
+  a[4] = 3;  // expected-note{{used in buffer access here}}
+}
+
+void failed_param_var_decl(int *a =new int[3]) {  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : has default arg}}
+  a[4] = 6;  // expected-note{{used in buffer access here}}
+}
+
+void unclaimed_use() {
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[2] = 9;  // expected-note{{used in buffer access here}}
+  int *b = a++;  // expected-note{{used in pointer arithmetic here}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for 'a' : has an unclaimed use}}
+}
+
+void implied_unclaimed_var(int *b) {  // expected-warning{{'b' is an unsafe pointer used for buffer access}}
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[4] = 7;  // expected-note{{used in buffer access here}}
+  a = b;  // debug-note{{safe buffers debug: gadget 'PointerAssignment' refused to produce a fix}}
+  b++;  // expected-note{{used in pointer arithmetic here}} \
+// debug-note{{safe buffers debug: failed to produce fixit for 'b' : has an unclaimed use}}
+}
Index: clang/lib/Sema/AnalysisBasedWarnings.cpp
===
--- clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2276,6 +2276,12 @@
   for (const auto  : Fixes)
 FD << F;
 }
+
+#ifndef NDEBUG
+if (areDebugNotesRequested())
+  for (const DebugNote : DebugNotesByVar[Variable])
+S.Diag(Note.first, diag::note_safe_buffer_debug_mode) << Note.second;
+#endif
   }
 
   bool isSafeBufferOptOut(const SourceLocation ) const override {
Index: 

[PATCH] D154880: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage.

2023-07-26 Thread Rashmi Mudduluru via Phabricator via cfe-commits
t-rasmud updated this revision to Diff 544547.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154880/new/

https://reviews.llvm.org/D154880

Files:
  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-debug.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -verify=expected %s
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -verify=expected,debug %s
+
+// A generic -debug would also enable our notes. This is probably fine.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -mllvm -debug \
+// RUN:-verify=expected,debug %s
+
+// This test file checks the behavior under the assumption that no fixits
+// were emitted for the test cases. If -Wunsafe-buffer-usage is improved
+// to support these cases (thus failing the test), the test should be changed
+// to showcase a different unsupported example.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -fdiagnostics-parseable-fixits %s \
+// RUN:2>&1 | FileCheck %s
+// CHECK-NOT: fix-it:
+
+// This debugging facility is only available in debug builds.
+//
+// REQUIRES: asserts
+
+void foo() {
+  int *x = new int[10]; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
+  x[5] = 10;// expected-note{{used in buffer access here}}
+  int z = x[-1];// expected-note{{used in buffer access here}} \
+// debug-note{{safe buffers debug: gadget 'ULCArraySubscript' refused to produce a fix}}
+}
+
+void failed_decl() {
+  int a[10];  // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : not a pointer}}
+  
+  for (int i = 0; i < 10; i++) {
+a[i] = i;  // expected-note{{used in buffer access here}}
+  }
+}
+
+void failed_multiple_decl() {
+  int *a = new int[4], b;  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : multiple VarDecls}}
+  a[4] = 3;  // expected-note{{used in buffer access here}}
+}
+
+void failed_param_var_decl(int *a =new int[3]) {  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : has default arg}}
+  a[4] = 6;  // expected-note{{used in buffer access here}}
+}
+
+void unclaimed_use() {
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[2] = 9;  // expected-note{{used in buffer access here}}
+  int *b = a++;  // expected-note{{used in pointer arithmetic here}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for 'a' : has an unclaimed use}}
+}
+
+void implied_unclaimed_var(int *b) {  // expected-warning{{'b' is an unsafe pointer used for buffer access}}
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[4] = 7;  // expected-note{{used in buffer access here}}
+  a = b;  // debug-note{{safe buffers debug: gadget 'PointerAssignment' refused to produce a fix}}
+  b++;  // expected-note{{used in pointer arithmetic here}} \
+// debug-note{{safe buffers debug: failed to produce fixit for 'b' : has an unclaimed use}}
+}
Index: clang/lib/Sema/AnalysisBasedWarnings.cpp
===
--- clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2276,6 +2276,12 @@
   for (const auto  : Fixes)
 FD << F;
 }
+
+#ifndef NDEBUG
+if (areDebugNotesRequested())
+  for (const DebugNote : DebugNotesByVar[Variable])
+S.Diag(Note.first, diag::note_safe_buffer_debug_mode) << Note.second;
+#endif
   }
 
   bool isSafeBufferOptOut(const SourceLocation ) const override {
Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -319,6 +319,15 @@
 
   Kind getKind() const { return K; }
 
+#ifndef NDEBUG
+  StringRef getDebugName() const {
+switch (K) {
+#define GADGET(x) case Kind::x: return #x;

[PATCH] D154880: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage.

2023-07-26 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ accepted this revision.
NoQ added a comment.
This revision is now accepted and ready to land.

LGTM! I'm excited to learn what this new facility discovers!




Comment at: clang/lib/Analysis/UnsafeBufferUsage.cpp:1730-1735
+#ifndef NDEBUG
+#define DEBUG_NOTE_DECL_FAIL(D, Msg)  \
+Handler.addDebugNoteForVar((D), (D)->getBeginLoc(), "failed to produce fixit 
for declaration '" + D->getNameAsString() + "'" + Msg)
+#else
+#define DEBUG_NOTE_DECL_FAIL(D, Msg)
+#endif

An extra bit of paranoia.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154880/new/

https://reviews.llvm.org/D154880

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154880: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage.

2023-07-26 Thread Rashmi Mudduluru via Phabricator via cfe-commits
t-rasmud updated this revision to Diff 544521.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154880/new/

https://reviews.llvm.org/D154880

Files:
  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-debug.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -verify=expected %s
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -verify=expected,debug %s
+
+// A generic -debug would also enable our notes. This is probably fine.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -mllvm -debug \
+// RUN:-verify=expected,debug %s
+
+// This test file checks the behavior under the assumption that no fixits
+// were emitted for the test cases. If -Wunsafe-buffer-usage is improved
+// to support these cases (thus failing the test), the test should be changed
+// to showcase a different unsupported example.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -fdiagnostics-parseable-fixits %s \
+// RUN:2>&1 | FileCheck %s
+// CHECK-NOT: fix-it:
+
+// This debugging facility is only available in debug builds.
+//
+// REQUIRES: asserts
+
+void foo() {
+  int *x = new int[10]; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
+  x[5] = 10;// expected-note{{used in buffer access here}}
+  int z = x[-1];// expected-note{{used in buffer access here}} \
+// debug-note{{safe buffers debug: gadget 'ULCArraySubscript' refused to produce a fix}}
+}
+
+void failed_decl() {
+  int a[10];  // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : not a pointer}}
+  
+  for (int i = 0; i < 10; i++) {
+a[i] = i;  // expected-note{{used in buffer access here}}
+  }
+}
+
+void failed_multiple_decl() {
+  int *a = new int[4], b;  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : multiple VarDecls}}
+  a[4] = 3;  // expected-note{{used in buffer access here}}
+}
+
+void failed_param_var_decl(int *a =new int[3]) {  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : has default arg}}
+  a[4] = 6;  // expected-note{{used in buffer access here}}
+}
+
+void unclaimed_use() {
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[2] = 9;  // expected-note{{used in buffer access here}}
+  int *b = a++;  // expected-note{{used in pointer arithmetic here}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for 'a' : has an unclaimed use}}
+}
+
+void implied_unclaimed_var(int *b) {  // expected-warning{{'b' is an unsafe pointer used for buffer access}}
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[4] = 7;  // expected-note{{used in buffer access here}}
+  a = b;  // debug-note{{safe buffers debug: gadget 'PointerAssignment' refused to produce a fix}}
+  b++;  // expected-note{{used in pointer arithmetic here}} \
+// debug-note{{safe buffers debug: failed to produce fixit for 'b' : has an unclaimed use}}
+}
Index: clang/lib/Sema/AnalysisBasedWarnings.cpp
===
--- clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2276,6 +2276,12 @@
   for (const auto  : Fixes)
 FD << F;
 }
+
+#ifndef NDEBUG
+if (areDebugNotesRequested())
+  for (const DebugNote : DebugNotesByVar[Variable])
+S.Diag(Note.first, diag::note_safe_buffer_debug_mode) << Note.second;
+#endif
   }
 
   bool isSafeBufferOptOut(const SourceLocation ) const override {
Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -319,6 +319,15 @@
 
   Kind getKind() const { return K; }
 
+#ifndef NDEBUG
+  StringRef getDebugName() const {
+switch (K) {
+#define GADGET(x) case Kind::x: return #x;

[PATCH] D154880: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage.

2023-07-26 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: clang/lib/Analysis/UnsafeBufferUsage.cpp:1730-1731
 
+#define DEBUG_NOTE_DECL_FAIL(D, Msg)  \
+Handler.addDebugNoteForVar((D), (D)->getBeginLoc(), "failed to produce fixit 
for declaration '" + D->getNameAsString() + "'" + Msg)
+

Ooo that's actually really nice! Maybe you can go even further and add this 
extra harness, so that to eliminate the need for `#ifndef NDEBUG` at every use.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154880/new/

https://reviews.llvm.org/D154880

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154880: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage.

2023-07-26 Thread Rashmi Mudduluru via Phabricator via cfe-commits
t-rasmud added a comment.

In D154880#4533035 , @ziqingluo-90 
wrote:

> This is a lot of work, thank you @t-rasmud & @NoQ !
>
> I have a minor suggestion: can we use some macros to make the debug stub even 
> shorter?
> The prefix `"failed to produce fixit for declaration"`  is used in many 
> places so probably we do not have to repeat it everywhere.  And, maybe some 
> prefixes could be a bit more blurry so that they can be shared.  For example, 
> we can just replace `"failed to produce fixit for parm var decl"` with 
> `"failed to produce fixit for declaration"`.   We have source location and 
> more specific message attached to the note so we are not losing information I 
> think.
>
> I'm imagining something like this:
>
>   #define DEBUG_NOTE_DECL_FAIL(D, Msg)  \
>   Handler.addDebugNoteForVar((D), (D)->getBeginLoc(),  "failed to produce 
> fixit for declaration "##Msg)
>   
>   #define DEBUG_NOTE_GADGET_FAIL(Gadget, Msg)  ...
>
> Does it make sense to you?

I like this suggestion. I've made changes to replace 
`Handler.addDebugNoteForVar` for declarations. The Gadget case appears just 
once as of now, so I've left it as is.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154880/new/

https://reviews.llvm.org/D154880

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154880: [-Wunsafe-buffer-usage] Add a facility for debugging low fixit coverage.

2023-07-26 Thread Rashmi Mudduluru via Phabricator via cfe-commits
t-rasmud updated this revision to Diff 544510.
t-rasmud retitled this revision from "[-Wunsafe-buffer-usage][WIP] Add a 
facility for debugging low fixit coverage." to "[-Wunsafe-buffer-usage] Add a 
facility for debugging low fixit coverage.".

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154880/new/

https://reviews.llvm.org/D154880

Files:
  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-debug.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -verify=expected %s
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -verify=expected,debug %s
+
+// A generic -debug would also enable our notes. This is probably fine.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-std=c++20 -mllvm -debug \
+// RUN:-verify=expected,debug %s
+
+// This test file checks the behavior under the assumption that no fixits
+// were emitted for the test cases. If -Wunsafe-buffer-usage is improved
+// to support these cases (thus failing the test), the test should be changed
+// to showcase a different unsupported example.
+//
+// RUN: %clang_cc1 -Wunsafe-buffer-usage -fsafe-buffer-usage-suggestions \
+// RUN:-mllvm -debug-only=SafeBuffers \
+// RUN:-std=c++20 -fdiagnostics-parseable-fixits %s \
+// RUN:2>&1 | FileCheck %s
+// CHECK-NOT: fix-it:
+
+// This debugging facility is only available in debug builds.
+//
+// REQUIRES: asserts
+
+void foo() {
+  int *x = new int[10]; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
+  x[5] = 10;// expected-note{{used in buffer access here}}
+  int z = x[-1];// expected-note{{used in buffer access here}} \
+// debug-note{{safe buffers debug: gadget 'ULCArraySubscript' refused to produce a fix}}
+}
+
+void failed_decl() {
+  int a[10];  // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : not a pointer}}
+  
+  for (int i = 0; i < 10; i++) {
+a[i] = i;  // expected-note{{used in buffer access here}}
+  }
+}
+
+void failed_multiple_decl() {
+  int *a = new int[4], b;  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : multiple VarDecls}}
+  a[4] = 3;  // expected-note{{used in buffer access here}}
+}
+
+void failed_param_var_decl(int *a =new int[3]) {  // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for declaration 'a' : has default arg}}
+  a[4] = 6;  // expected-note{{used in buffer access here}}
+}
+
+void unclaimed_use() {
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[2] = 9;  // expected-note{{used in buffer access here}}
+  int *b = a++;  // expected-note{{used in pointer arithmetic here}} \
+  // debug-note{{safe buffers debug: failed to produce fixit for 'a' : has an unclaimed use}}
+}
+
+void implied_unclaimed_var(int *b) {  // expected-warning{{'b' is an unsafe pointer used for buffer access}}
+  int *a = new int[3];  // expected-warning{{'a' is an unsafe pointer used for buffer access}}
+  a[4] = 7;  // expected-note{{used in buffer access here}}
+  a = b;  // debug-note{{safe buffers debug: gadget 'PointerAssignment' refused to produce a fix}}
+  b++;  // expected-note{{used in pointer arithmetic here}} \
+// debug-note{{safe buffers debug: failed to produce fixit for 'b' : has an unclaimed use}}
+}
Index: clang/lib/Sema/AnalysisBasedWarnings.cpp
===
--- clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2276,6 +2276,12 @@
   for (const auto  : Fixes)
 FD << F;
 }
+
+#ifndef NDEBUG
+if (areDebugNotesRequested())
+  for (const DebugNote : DebugNotesByVar[Variable])
+S.Diag(Note.first, diag::note_safe_buffer_debug_mode) << Note.second;
+#endif
   }
 
   bool isSafeBufferOptOut(const SourceLocation ) const override {
Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++