================ @@ -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@+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@+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@+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@+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@+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@+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@+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}} + void *tmp2 = explicit_desig_init.buf_typedef; + + struct CBBufDeclPos partial_explicit_desig_init = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized + // expected-error@+2{{cannot implicitly 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}} + // expected-error@+1{{cannot implicitly 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}} + }; + + struct CBBufDeclPos implicit_full_init = { + 0 + // expected-error@+2{{cannot implicitly 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}} + // expected-error@+1{{cannot implicitly 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}} + }; + // Variable is not currently marked as invalid so uses of the variable allows + // diagnostics to fire. + // expected-error@+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}} + implicit_full_init.buf = 0x0; + // expected-error@+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}} + implicit_full_init.buf_typedef = 0x0; + // expected-error@+1{{cannot use 'implicit_full_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* tmp3 = implicit_full_init.buf; + // expected-error@+1{{cannot use 'implicit_full_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}} + void* tmp4 = implicit_full_init.buf_typedef; + + struct CBBufDeclPos explicit_non_desig_init = { + 0, + // expected-error@+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}} + 0x0, + // expected-error@+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}} + 0x0 + }; + + // =========================================================================== + // ## Assignment to fields + // =========================================================================== + struct CBBufDeclPos uninit; + uninit.count = 0; + // expected-error@+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}} + uninit.buf = 0x0; + // expected-error@+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}} + uninit.buf_typedef = 0x0; + ptr->count = 0; + // expected-error@+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}} + ptr->buf = 0x0; + // expected-error@+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}} + ptr->buf_typedef = 0x0; + + + // =========================================================================== + // ## Make sure modifying the fields through other assignment operators is not + // allowed + // =========================================================================== ---------------- Sirraide wrote:
What is the point of these tests? Because isn’t this just testing that we don’t allow pointer arithmetic on incomplete types... which is implemented somewhere else entirely (or are we emitting this diagnostic somewhere in the bounds-checking code that I missed)? https://github.com/llvm/llvm-project/pull/106321 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits