[clang] [BoundsSafety][Sema] Allow counted_by and counted_by_or_null on pointers where the pointee type is incomplete but potentially completable (PR #106321)
Dan Liew via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 7 08:33:21 PST 2025
================
@@ -0,0 +1,584 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s
+
+#define __counted_by(f) __attribute__((counted_by(f)))
+
+// =============================================================================
+// # Struct incomplete type with attribute in the decl position
+// =============================================================================
+
+// Note: This could be considered misleading. The typedef isn't actually on this
+// line. Also note the discrepancy in diagnostic count (27 vs 51) is due to
+// the pointer arithmetic on incomplete pointee type diagnostic always using
+// diagnostic text that refers to the underlying forward decl, even when the
+// typedef is used.
+// expected-note at +1 27{{forward declaration of 'Incomplete_t' (aka 'struct IncompleteTy')}}
+struct IncompleteTy; // expected-note 51{{forward declaration of 'struct IncompleteTy'}}
+
+typedef struct IncompleteTy Incomplete_t;
+
+struct CBBufDeclPos {
+ int count;
+ struct IncompleteTy* buf __counted_by(count); // OK expected-note 27{{__counted_by attribute is here}}
+ Incomplete_t* buf_typedef __counted_by(count); // OK expected-note 27{{__counted_by attribute is here}}
+};
+
+void consume_struct_IncompleteTy(struct IncompleteTy* buf);
+
+int idx(void);
+
+
+
+void test_CBBufDeclPos(struct CBBufDeclPos* ptr) {
+ // ===========================================================================
+ // ## Local variable initialization
+ // ===========================================================================
+ struct CBBufDeclPos explicit_desig_init = {
+ .count = 0,
+ // expected-error at +1{{cannot initialize 'CBBufDeclPos::buf' that has type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteTy' or using the '__sized_by' attribute}}
+ .buf = 0x0,
+ // expected-error at +1{{cannot initialize 'CBBufDeclPos::buf_typedef' that has type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_t' or using the '__sized_by' attribute}}
+ .buf_typedef = 0x0
+ };
+ // Variable is not currently marked as invalid so uses of the variable allows
+ // diagnostics to fire.
+ // expected-error at +1{{cannot assign to 'CBBufDeclPos::buf' that has type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteTy' or using the '__sized_by' attribute}}
+ explicit_desig_init.buf = 0x0;
+ // expected-error at +1{{cannot assign to 'CBBufDeclPos::buf_typedef' that has type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'Incomplete_t' or using the '__sized_by' attribute}}
+ explicit_desig_init.buf_typedef = 0x0;
+ // expected-error at +1{{cannot use 'explicit_desig_init.buf' with type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteTy' or using the '__sized_by' attribute}}
+ void *tmp = explicit_desig_init.buf;
+ // expected-error at +1{{cannot use 'explicit_desig_init.buf_typedef' with type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'Incomplete_t' or using the '__sized_by' attribute}}
----------------
delcypher wrote:
Ideally I think the all the information necessary for understanding an error should be contained within the `error` diagnostic itself and additional useful (but not strictly necessary) information can (but doesn't necessarily have to be) put into notes.
What is necessary is a little subjective but...
> ‘Access to bounds-checked field has incomplete type’
doesn't contains all the necessary information IMHO and is vague enough that I think it will cause more confusion than the current diagnostic text.
* These fields are only bounds checked with `-fbounds-safety`. Without `-fbounds-safety` the attributes are just hints for `__builtin_dynamic_object_size`. So calling the field bounds checked isn't accurate unless `-fbound-safety` is on. Even then this is vague enough that someone might not understand this is related to `-fbounds-safety`.
* It's not really obvious what "bounds-checked" field means (given we have multiple implementations of bounds checking in clang) and more information is **neccessary** to understand that this restriction comes from the `__counted_by` attribute . I don't think this **necessary** information should be moved into a note.
I'll grant you the diagnostic text is long but I believe almost everything there is **necessary** to understand the error. However, the `'; consider providing...` text isn't strictly necessary and could be moved to a note.
So I'd prefer to either leave the diagnostic text as it is, or move the `; consider...` part of the text to its own note.
Please let me know what you'd prefer.
https://github.com/llvm/llvm-project/pull/106321
More information about the cfe-commits
mailing list