================
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify=disabled -Wno-counted-by-addrof %s
+// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | 
FileCheck %s
+
+// disabled-no-diagnostics
+
+#define __counted_by(f) __attribute__((counted_by(f)))
+
+typedef __SIZE_TYPE__ size_t;
+
+struct annotated_flex {
+  size_t count;
+  char induce_padding;
+  char fam[] __counted_by(count);
+};
+
+struct plain_flex {
+  size_t count;
+  char fam[];
+};
+
+struct annotated_flex *get_ptr(void);
+
+size_t ptr_addrof(struct annotated_flex *p) {
+  return __builtin_dynamic_object_size(&p->fam, 1); // expected-warning 
{{taking the address of flexible array member 'fam' discards the 'counted_by' 
bound}}
+}
+
+// Opaque pointer return. Allocation not statically known. fix-it offered.
+size_t ret_addrof(void) {
+  return __builtin_dynamic_object_size(&get_ptr()->fam, 1); // 
expected-warning {{taking the address of flexible array member 'fam' discards 
the 'counted_by' bound}}
+}
+
+// Subscripting a pointer escapes to an unknown allocation. fix-it offered.
+size_t ptr_subscript_addrof(struct annotated_flex *parr, int i) {
+  return __builtin_dynamic_object_size(&parr[i].fam, 1); // expected-warning 
{{taking the address of flexible array member 'fam' discards the 'counted_by' 
bound}}
+}
+
+struct annotated_flex gaf;
+
+// Global: fixed allocation, so the layout answer is already correct. No 
warning.
+size_t global_addrof(void) {
+  return __builtin_dynamic_object_size(&gaf.fam, 1);
+}
+
+// Local: fixed allocation. No warning.
+size_t local_addrof(size_t n) {
+  struct annotated_flex af;
+  af.count = n;
+  return __builtin_dynamic_object_size(&af.fam, 1);
+}
+
+// Static local (static storage, local scope). No warning.
+size_t static_local_addrof(void) {
+  static struct annotated_flex saf;
+  return __builtin_dynamic_object_size(&saf.fam, 1);
+}
+
+size_t decayed(struct annotated_flex *p) {
+  // Decayed pointer-to-element honors the count. There is no '&'.
+  return __builtin_dynamic_object_size(p->fam, 1);
+}
+
+size_t element_addrof(struct annotated_flex *p, int i) {
+  // Address of an element, not the whole array.
+  return __builtin_dynamic_object_size(&p->fam[i], 1);
+}
+
+// __builtin_object_size (non-dynamic) never consults the count, so &fam
+// discards nothing here.
+size_t static_object_size(struct annotated_flex *p) {
+  return __builtin_object_size(&p->fam, 1);
+}
+
+// Taking the address outside of __builtin_dynamic_object_size is not flagged:
+// the count is only silently discarded in the __bdos lowering.
+char (*bare_addrof(struct annotated_flex *p))[] {
+  return &p->fam;
+}
+
+char *count_addrof(struct annotated_flex *p) {
+  return (char *)&p->count; // non-FAM field.
+}
+
+char (*plain_addrof(struct plain_flex *p))[] {
+  return &p->fam; // FAM without counted_by.
+}
+
+// CHECK-COUNT-3: fix-it:{{.*}}:""
----------------
hnrklssn wrote:

This doesn't validate the correctness of the fixits, only that they exist. 
Create individual CHECK directives  instead, next to where they are emitted, 
with `[[@LINE+$N]]:$START_COL-[[@LINE+$N]]:$END_COL` etc to show what each 
fixit does.

I would also suggest following the lead of e.g. 
`clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.c` and compile 
the file with `-fixit` and check that it compiles without diagnostics after.

https://github.com/llvm/llvm-project/pull/206760
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to