CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
631 lines
41 KiB
C
631 lines
41 KiB
C
// 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@+3 27{{consider providing a complete definition for 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
// The 'forward declaration' notes come from 'arithmetic on a pointer to an incomplete type' errors
|
|
// expected-note@+1 24{{forward declaration of 'struct IncompleteTy'}}
|
|
struct IncompleteTy; // expected-note 27{{consider providing a complete definition for 'struct IncompleteTy'}}
|
|
|
|
typedef struct IncompleteTy Incomplete_t;
|
|
|
|
struct CBBufDeclPos {
|
|
int count;
|
|
struct IncompleteTy* buf __counted_by(count); // OK expected-note 27{{consider using '__sized_by' instead of '__counted_by'}}
|
|
Incomplete_t* buf_typedef __counted_by(count); // OK expected-note 27{{consider using '__sized_by' instead of '__counted_by'}}
|
|
};
|
|
|
|
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' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
.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' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
explicit_desig_init.buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
explicit_desig_init.buf_typedef = 0x0;
|
|
// expected-error@+1{{cannot use 'explicit_desig_init.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
void *tmp = explicit_desig_init.buf;
|
|
// expected-error@+1{{cannot use 'explicit_desig_init.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
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' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
// expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
};
|
|
|
|
struct CBBufDeclPos implicit_full_init = {
|
|
0
|
|
// expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
// expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
};
|
|
// Variable is not currently marked as invalid so uses of the variable allows
|
|
// diagnostics to fire.
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
implicit_full_init.buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
implicit_full_init.buf_typedef = 0x0;
|
|
// expected-error@+1{{cannot use 'implicit_full_init.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
void* tmp3 = implicit_full_init.buf;
|
|
// expected-error@+1{{cannot use 'implicit_full_init.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
void* tmp4 = implicit_full_init.buf_typedef;
|
|
|
|
struct CBBufDeclPos explicit_non_desig_init = {
|
|
0,
|
|
// expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
0x0
|
|
};
|
|
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
// ## Assignment to fields
|
|
// ===========================================================================
|
|
struct CBBufDeclPos uninit;
|
|
uninit.count = 0;
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
uninit.buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
uninit.buf_typedef = 0x0;
|
|
ptr->count = 0;
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
ptr->buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
ptr->buf_typedef = 0x0;
|
|
|
|
|
|
// ===========================================================================
|
|
// ## Make sure modifying the fields through other assignment operators is not
|
|
// allowed
|
|
// ===========================================================================
|
|
uninit.buf++; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
++uninit.buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
uninit.buf += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
uninit.buf_typedef++; // // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
++uninit.buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
uninit.buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
|
|
uninit.buf--; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
--uninit.buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
uninit.buf -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
uninit.buf_typedef--; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
--uninit.buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
uninit.buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
|
|
ptr->buf++; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
++ptr->buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
ptr->buf += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
ptr->buf--; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
--ptr->buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
ptr->buf -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}}
|
|
|
|
ptr->buf_typedef++; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
++ptr->buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
ptr->buf_typedef += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
ptr->buf_typedef--; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
--ptr->buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
ptr->buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}}
|
|
|
|
// ===========================================================================
|
|
// ## Use of fields in expressions
|
|
// ===========================================================================
|
|
// expected-error@+2{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
void* addr =
|
|
((char*) uninit.buf ) + 1;
|
|
// expected-error@+2{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
void* addr_typedef =
|
|
((char*) uninit.buf_typedef ) + 1;
|
|
// expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
void* addr_ptr =
|
|
((char*) ptr->buf ) + 1;
|
|
// expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
void* addr_ptr_typedef =
|
|
((char*) ptr->buf_typedef ) + 1;
|
|
|
|
|
|
// ===========================================================================
|
|
// ## Take address of fields
|
|
// ===========================================================================
|
|
// TODO: This should be forbidden, not because of the incomplete pointee type
|
|
// but because in the -fbounds-safety language model the address of a
|
|
// `counted_by` pointer cannot be taken to avoid it being possible to modify
|
|
// the `counted_by` pointer through another pointer. Whether or not this
|
|
// should be forbidden when `-fbounds-safety` is off is TBD.
|
|
//
|
|
// The incomplete pointee type isn't actually a problem here for
|
|
// `-fbounds-safety` because taking the address of a pointer returns a pointer
|
|
// that have the bounds of a single `void*`, so bounds checks on the resulting
|
|
// pointer don't need to know `sizeof(struct IncompleteTy)` but instead
|
|
// `sizeof(struct IncompleteTy* buf __counted_by(count))` which is just the
|
|
// size of a pointer.
|
|
void* take_addr = &uninit.buf;
|
|
void* take_addr_typedef = &uninit.buf_typedef;
|
|
void* take_addr_ptr = &ptr->buf;
|
|
void* take_addr_ptr_typedef = &ptr->buf_typedef;
|
|
|
|
// expected-error@+1{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
struct IncompleteTy* addr_elt_zero = &uninit.buf[0];
|
|
// expected-error@+1{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
struct IncompleteTy* addr_elt_idx = &uninit.buf[idx()];
|
|
|
|
// expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
struct IncompleteTy* addr_elt_zero_typedef = &uninit.buf_typedef[0];
|
|
// expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
struct IncompleteTy* addr_elt_idx_typedef = &uninit.buf_typedef[idx()];
|
|
|
|
// expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
struct IncompleteTy* addr_elt_zero_ptr = &ptr->buf[0];
|
|
// expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
struct IncompleteTy* addr_elt_idx_ptr = &ptr->buf[idx()];
|
|
// expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
struct IncompleteTy* addr_elt_zero_ptr_typedef = &ptr->buf_typedef[0];
|
|
// expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
struct IncompleteTy* addr_elt_idx_ptr_typedef = &ptr->buf_typedef[idx()];
|
|
|
|
|
|
// ===========================================================================
|
|
// ## Use fields as call arguments
|
|
// ===========================================================================
|
|
// expected-error@+1{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
consume_struct_IncompleteTy(uninit.buf);
|
|
// expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
consume_struct_IncompleteTy(uninit.buf_typedef);
|
|
// expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
consume_struct_IncompleteTy(ptr->buf);
|
|
// expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
consume_struct_IncompleteTy(ptr->buf_typedef);
|
|
|
|
// ===========================================================================
|
|
// ## Use [] operator on fields
|
|
// ===========================================================================
|
|
// expected-error@+1 2{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
uninit.buf[0] = uninit.buf[1];
|
|
// expected-error@+1 2{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
uninit.buf_typedef[0] = uninit.buf_typedef[1];
|
|
// expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
ptr->buf[0] = ptr->buf[1];
|
|
// expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
ptr->buf_typedef[0] = ptr->buf_typedef[1];
|
|
}
|
|
|
|
|
|
// =============================================================================
|
|
// ## Global initialization
|
|
// =============================================================================
|
|
|
|
struct CBBufDeclPos global_explicit_desig_init = {
|
|
.count = 0,
|
|
// expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
void use_global_explicit_desig_init(void) {
|
|
// Variable isn't marked as invalid so diagnostics still fire
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
global_explicit_desig_init.buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
global_explicit_desig_init.buf_typedef = 0x0;
|
|
}
|
|
|
|
struct CBBufDeclPos global_partial_explicit_desig_init = {
|
|
.count = 0,
|
|
// .buf and .buf_typedef are implicit zero initialized
|
|
// expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
// expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
};
|
|
|
|
struct CBBufDeclPos global_implicit_full_init = {
|
|
0
|
|
// expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
// expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
};
|
|
|
|
struct CBBufDeclPos global_explicit_non_desig_init = {
|
|
0,
|
|
// expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}}
|
|
0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}}
|
|
0x0
|
|
};
|
|
|
|
extern struct CBBufDeclPos global_declaration; // OK
|
|
|
|
// TODO: These tentative definitions are implicitly empty initialized to zero.
|
|
// This should generate an error diagnostic but currently doesn't. There should
|
|
// be a carve out to allow `__counted_by(0)` which is the only constant count
|
|
// version of the attribute where it is valid to assign NULL.
|
|
struct CBBufDeclPos global_tentative_defn;
|
|
static struct CBBufDeclPos global_tentative_defn2;
|
|
|
|
// =============================================================================
|
|
// ## Completing the definition of the type allows use of CBBufDeclPos fields
|
|
// =============================================================================
|
|
struct IncompleteTy {
|
|
int field;
|
|
};
|
|
|
|
void test_CBBufDeclPos_completed(struct CBBufDeclPos* ptr) {
|
|
// Initialization is ok
|
|
struct CBBufDeclPos explicit_desig_init = {
|
|
.count = 0,
|
|
.buf = 0x0,
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
struct CBBufDeclPos partial_explicit_desig_init = {
|
|
.count = 0,
|
|
// .buf and .buf_typedef are implicit zero initialized
|
|
};
|
|
|
|
struct CBBufDeclPos implicit_full_init = {0};
|
|
|
|
struct CBBufDeclPos explicit_non_desig_init = {
|
|
0,
|
|
0x0,
|
|
0x0
|
|
};
|
|
|
|
// Assignment to fields is ok
|
|
ptr->buf = 0x0;
|
|
ptr->buf_typedef = 0x0;
|
|
|
|
// Use of fields in expressions is ok
|
|
void* tmp = ptr->buf;
|
|
void* tmp2 = ptr->buf_typedef;
|
|
|
|
// Take address of fields is ok
|
|
void* take_addr_ptr = &ptr->buf;
|
|
void* take_addr_ptr_typedef = &ptr->buf_typedef;
|
|
|
|
struct IncompleteTy* addr_elt_zero_ptr = &ptr->buf[0];
|
|
struct IncompleteTy* addr_elt_idx_ptr = &ptr->buf[idx()];
|
|
struct IncompleteTy* addr_elt_zero_ptr_typedef = &ptr->buf_typedef[0];
|
|
struct IncompleteTy* addr_elt_idx_ptr_typedef = &ptr->buf_typedef[idx()];
|
|
|
|
// As call arguments is ok
|
|
consume_struct_IncompleteTy(ptr->buf);
|
|
consume_struct_IncompleteTy(ptr->buf_typedef);
|
|
|
|
// In [] operator is ok
|
|
ptr->buf[0] = ptr->buf[1];
|
|
ptr->buf_typedef[0] = ptr->buf_typedef[1];
|
|
}
|
|
|
|
// Global initialization is ok
|
|
|
|
struct CBBufDeclPos global_explicit_desig_init_completed = {
|
|
.count = 0,
|
|
.buf = 0x0,
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
struct CBBufDeclPos global_partial_explicit_desig_init_completed = {
|
|
.count = 0,
|
|
// .buf and .buf_typedef are implicit zero initialized
|
|
};
|
|
|
|
struct CBBufDeclPos global_implicit_full_init_completed = {0};
|
|
|
|
struct CBBufDeclPos global_explicit_non_desig_init_completed = {
|
|
0,
|
|
0x0,
|
|
0x0
|
|
};
|
|
|
|
extern struct CBBufDeclPos global_declaration;
|
|
struct CBBufDeclPos global_tentative_defn;
|
|
static struct CBBufDeclPos global_tentative_defn2;
|
|
|
|
// =============================================================================
|
|
// # Struct incomplete type with attribute in the pointer position
|
|
// =============================================================================
|
|
|
|
// expected-note@+1 8{{consider providing a complete definition for 'Incomplete_ty2' (aka 'struct IncompleteTy2')}}
|
|
struct IncompleteTy2; // expected-note 8{{consider providing a complete definition for 'struct IncompleteTy2'}}
|
|
typedef struct IncompleteTy2 Incomplete_ty2;
|
|
|
|
void consume_struct_IncompleteTy2(struct IncompleteTy2* buf);
|
|
|
|
struct CBBufTyPos {
|
|
int count;
|
|
struct IncompleteTy2* __counted_by(count) buf ; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}}
|
|
Incomplete_ty2 *__counted_by(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}}
|
|
};
|
|
|
|
void use_CBBufTyPos(struct CBBufTyPos* ptr) {
|
|
struct CBBufTyPos explicit_desig_init = {
|
|
.count = 0,
|
|
// expected-error@+1{{cannot initialize 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}}
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
// Assignment
|
|
// expected-error@+1{{cannot assign to 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}}
|
|
explicit_desig_init.buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}}
|
|
explicit_desig_init.buf_typedef = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}}
|
|
ptr->buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}}
|
|
ptr->buf_typedef = 0x0;
|
|
|
|
// Use
|
|
// expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}}
|
|
void* addr =
|
|
((char*) ptr->buf ) + 1;
|
|
// expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}}
|
|
void* addr_typedef =
|
|
((char*) ptr->buf_typedef ) + 1;
|
|
|
|
// expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}}
|
|
consume_struct_IncompleteTy2(ptr->buf);
|
|
// expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}}
|
|
consume_struct_IncompleteTy2(ptr->buf_typedef);
|
|
|
|
// expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}}
|
|
ptr->buf[0] = ptr->buf[1];
|
|
// expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}}
|
|
ptr->buf_typedef[0] = ptr->buf_typedef[1];
|
|
}
|
|
|
|
struct CBBufTyPos global_explicit_desig_init_struct_type_pos = {
|
|
.count = 0,
|
|
// expected-error@+1{{cannot initialize 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}}
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
// Defining the type makes `CBBufTyPos` fields usable
|
|
struct IncompleteTy2 {
|
|
int field;
|
|
};
|
|
|
|
void use_CBBufTyPos_completed(struct CBBufTyPos* ptr) {
|
|
ptr->buf = 0x0;
|
|
ptr->buf_typedef = 0x0;
|
|
void* addr = ((char*) ptr->buf) + 1;
|
|
void* addr_typedef = ((char*) ptr->buf_typedef) + 1;
|
|
}
|
|
|
|
// =============================================================================
|
|
// # union incomplete type
|
|
// =============================================================================
|
|
|
|
// expected-note@+1 8{{consider providing a complete definition for 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy')}}
|
|
union IncompleteUnionTy; // expected-note 8{{consider providing a complete definition for 'union IncompleteUnionTy'}}
|
|
typedef union IncompleteUnionTy IncompleteUnion_ty;
|
|
|
|
void consume_struct_IncompleteUnionTy(union IncompleteUnionTy* buf);
|
|
|
|
struct CBBufUnionTyPos {
|
|
int count;
|
|
union IncompleteUnionTy* __counted_by(count) buf ; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}}
|
|
IncompleteUnion_ty *__counted_by(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}}
|
|
};
|
|
|
|
void use_CBBufUnionTyPos(struct CBBufUnionTyPos* ptr) {
|
|
struct CBBufUnionTyPos explicit_desig_init = {
|
|
.count = 0,
|
|
// expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}}
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
// Assignment
|
|
// expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}}
|
|
explicit_desig_init.buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}}
|
|
explicit_desig_init.buf_typedef = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}}
|
|
ptr->buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}}
|
|
ptr->buf_typedef = 0x0;
|
|
|
|
// Use
|
|
// expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}}
|
|
void* addr =
|
|
((char*) ptr->buf ) + 1;
|
|
// expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}}
|
|
void* addr_typedef =
|
|
((char*) ptr->buf_typedef ) + 1;
|
|
|
|
// expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}}
|
|
consume_struct_IncompleteUnionTy(ptr->buf);
|
|
// expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}}
|
|
consume_struct_IncompleteUnionTy(ptr->buf_typedef);
|
|
|
|
// expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}}
|
|
ptr->buf[0] = ptr->buf[1];
|
|
// expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}}
|
|
ptr->buf_typedef[0] = ptr->buf_typedef[1];
|
|
}
|
|
|
|
struct CBBufUnionTyPos global_explicit_desig_init_union_type_pos = {
|
|
.count = 0,
|
|
// expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}}
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
// Defining the type makes `CBBufUnionTyPos` fields usable
|
|
union IncompleteUnionTy {
|
|
int field;
|
|
};
|
|
|
|
void use_CBBufUnionTyPos_completed(struct CBBufUnionTyPos* ptr) {
|
|
ptr->buf = 0x0;
|
|
ptr->buf_typedef = 0x0;
|
|
void* addr = ((char*) ptr->buf) + 1;
|
|
void* addr_typedef = ((char*) ptr->buf_typedef) + 1;
|
|
}
|
|
|
|
// =============================================================================
|
|
// # enum incomplete type
|
|
// =============================================================================
|
|
|
|
// expected-note@+1 8{{consider providing a complete definition for 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy')}}
|
|
enum IncompleteEnumTy; // expected-note 8{{consider providing a complete definition for 'enum IncompleteEnumTy'}}
|
|
typedef enum IncompleteEnumTy IncompleteEnum_ty;
|
|
|
|
void consume_struct_IncompleteEnumTy(enum IncompleteEnumTy* buf);
|
|
|
|
struct CBBufEnumTyPos {
|
|
int count;
|
|
enum IncompleteEnumTy* __counted_by(count) buf ; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}}
|
|
IncompleteEnum_ty *__counted_by(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}}
|
|
};
|
|
|
|
void use_CBBufEnumTyPos(struct CBBufEnumTyPos* ptr) {
|
|
struct CBBufEnumTyPos explicit_desig_init = {
|
|
.count = 0,
|
|
// expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}}
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
// Assignment
|
|
// expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}}
|
|
explicit_desig_init.buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}}
|
|
explicit_desig_init.buf_typedef = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}}
|
|
ptr->buf = 0x0;
|
|
// expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}}
|
|
ptr->buf_typedef = 0x0;
|
|
|
|
// Use
|
|
// expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}}
|
|
void* addr =
|
|
((char*) ptr->buf ) + 1;
|
|
// expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}}
|
|
void* addr_typedef =
|
|
((char*) ptr->buf_typedef ) + 1;
|
|
|
|
// expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}}
|
|
consume_struct_IncompleteEnumTy(ptr->buf);
|
|
// expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}}
|
|
consume_struct_IncompleteEnumTy(ptr->buf_typedef);
|
|
|
|
// expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}}
|
|
ptr->buf[0] = ptr->buf[1];
|
|
// expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}}
|
|
ptr->buf_typedef[0] = ptr->buf_typedef[1];
|
|
}
|
|
|
|
struct CBBufEnumTyPos global_explicit_desig_init_enum_type_pos = {
|
|
.count = 0,
|
|
// expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}}
|
|
.buf = 0x0,
|
|
// expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}}
|
|
.buf_typedef = 0x0
|
|
};
|
|
|
|
// Defining the type makes `CBBufEnumTyPos` fields usable
|
|
enum IncompleteEnumTy {
|
|
ONE,
|
|
TWO
|
|
};
|
|
|
|
void use_CBBufEnumTyPos_completed(struct CBBufEnumTyPos* ptr) {
|
|
ptr->buf = 0x0;
|
|
ptr->buf_typedef = 0x0;
|
|
void* addr = ((char*) ptr->buf) + 1;
|
|
void* addr_typedef = ((char*) ptr->buf_typedef) + 1;
|
|
}
|
|
|
|
// Make a complete enum by providing an underlying type
|
|
enum CompleteEnumTy : unsigned;
|
|
typedef enum CompleteEnumTy CompleteEnum_ty;
|
|
struct CBBufEnumTyPos2 {
|
|
int count;
|
|
enum CompleteEnumTy* __counted_by(count) buf;
|
|
CompleteEnum_ty *__counted_by(count) buf_typedef;
|
|
};
|
|
|
|
void use_CBBufEnumTyPos2(struct CBBufEnumTyPos2* ptr) {
|
|
struct CBBufEnumTyPos2 explicit_desig_init = {
|
|
.count = 0,
|
|
.buf = 0x0, // OK
|
|
.buf_typedef = 0x0 // OK
|
|
};
|
|
}
|
|
|
|
// Make a complete enum by providing a concrete declaration
|
|
enum CompleteEnumTy2 {
|
|
VALUE_ONE,
|
|
VALUE_TWO
|
|
};
|
|
typedef enum CompleteEnumTy2 CompleteEnum_ty2;
|
|
struct CBBufEnumTyPos3 {
|
|
int count;
|
|
enum CompleteEnumTy2* __counted_by(count) buf;
|
|
CompleteEnum_ty2 *__counted_by(count) buf_typedef;
|
|
};
|
|
|
|
void use_CBBufEnumTyPos3(struct CBBufEnumTyPos3* ptr) {
|
|
struct CBBufEnumTyPos3 explicit_desig_init = {
|
|
.count = 0,
|
|
.buf = 0x0, // OK
|
|
.buf_typedef = 0x0 // OK
|
|
};
|
|
}
|
|
|
|
|
|
// =============================================================================
|
|
// # Array of __counted_by pointers
|
|
// =============================================================================
|
|
|
|
struct IncompleteTy3;
|
|
|
|
struct CBBufFAMofCountedByPtrs {
|
|
int size;
|
|
// TODO: This is misleading. The attribute is written in the type position
|
|
// but clang currently doesn't treat it like that and it gets treated as
|
|
// an attribute on the array, rather than on the element type.
|
|
struct IncompleteTy3* __counted_by(size) arr[];
|
|
};
|
|
|
|
void arr_of_counted_by_ptr(struct CBBufFAMofCountedByPtrs* ptr) {
|
|
// TODO: Should be disallowed once parsing attributes in the type position
|
|
// works.
|
|
ptr->arr[0] = 0x0;
|
|
void* addr = ((char*) ptr->arr[0]) + 1;
|
|
}
|