================
@@ -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
+ //
===========================================================================
----------------
delcypher wrote:
> but my point is that if you try to perform pointer arithmetic on an
> incomplete type, we’re going to reject that anyway, irrespective of whether
> the member in question has the __counted_by attribute or not
But we should test that... That is indeed what I expect but that expectation
for the `__counted_by` attribute should be tested.
https://github.com/llvm/llvm-project/pull/106321
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits