mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add tests and improvements for @nopadding and @compact.
This commit is contained in:
committed by
Christoffer Lerno
parent
a4a1a42842
commit
8285720180
@@ -36,7 +36,7 @@ static bool sema_analyse_bitstruct(SemaContext *context, Decl *decl, bool *erase
|
||||
static bool sema_analyse_union_members(SemaContext *context, Decl *decl);
|
||||
static bool sema_analyse_struct_members(SemaContext *context, Decl *decl);
|
||||
static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent, Decl *decl, bool *erase_decl);
|
||||
static inline bool sema_check_struct_holes(SemaContext *context, Decl *decl, Decl *member, Type *member_type);
|
||||
static inline bool sema_check_struct_holes(SemaContext *context, Decl *decl, Decl *member);
|
||||
static inline bool sema_analyse_bitstruct_member(SemaContext *context, Decl *parent, Decl *member, unsigned index, bool allow_overlap, bool *erase_decl);
|
||||
|
||||
static inline bool sema_analyse_doc_header(SemaContext *context, AstId doc, Decl **params, Decl **extra_params, bool *pure_ref);
|
||||
@@ -260,9 +260,10 @@ static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent
|
||||
}
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
// Extend the nopadding attributes to substructs.
|
||||
// Extend the nopadding attributes to nested structs.
|
||||
if (parent->attr_nopadding) decl->attr_nopadding = true;
|
||||
if (parent->attr_compact) decl->attr_compact = true;
|
||||
FALLTHROUGH;
|
||||
case DECL_BITSTRUCT:
|
||||
decl->is_export = is_export;
|
||||
if (!sema_analyse_decl(context, decl)) return false;
|
||||
@@ -272,9 +273,9 @@ static inline bool sema_analyse_struct_member(SemaContext *context, Decl *parent
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_check_struct_holes(SemaContext *context, Decl *decl, Decl *member, Type *member_type)
|
||||
static inline bool sema_check_struct_holes(SemaContext *context, Decl *decl, Decl *member)
|
||||
{
|
||||
member_type = type_flatten(member_type);
|
||||
Type* member_type = type_flatten(member->type);
|
||||
if (!type_is_union_or_strukt(member_type)) return true;
|
||||
assert(decl_is_struct_type(member_type->decl));
|
||||
if (!member_type->decl->strukt.padded_decl_id) return true;
|
||||
@@ -282,8 +283,16 @@ static inline bool sema_check_struct_holes(SemaContext *context, Decl *decl, Dec
|
||||
if (decl->attr_compact)
|
||||
{
|
||||
SEMA_ERROR(member, "%s has padding and can't be used as the type of '%s', because members of a `@compact` type must all have zero padding.", type_quoted_error_string(member_type), member->name);
|
||||
SEMA_NOTE(declptr(member_type->decl->strukt.padded_decl_id), "The first padded field in %s is here.",
|
||||
type_quoted_error_string(member_type));
|
||||
Decl* padded_decl = declptr(member_type->decl->strukt.padded_decl_id);
|
||||
if (decl_is_struct_type(padded_decl))
|
||||
{
|
||||
SEMA_NOTE(padded_decl, "The first padding in %s would be added to the end of this type.",
|
||||
type_quoted_error_string(member_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
SEMA_NOTE(padded_decl, "The first padded field in %s is here.", type_quoted_error_string(member_type));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -337,8 +346,7 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl)
|
||||
AlignSize member_alignment;
|
||||
if (!sema_set_abi_alignment(context, member->type, &member_alignment)) return false;
|
||||
|
||||
Type *member_type = type_flatten(member->type);
|
||||
if (!sema_check_struct_holes(context, decl, member, member_type)) return false;
|
||||
if (!sema_check_struct_holes(context, decl, member)) return false;
|
||||
|
||||
ByteSize member_size = type_size(member->type);
|
||||
assert(member_size <= MAX_TYPE_SIZE);
|
||||
@@ -595,11 +603,11 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl)
|
||||
if (!decl->strukt.padded_decl_id) decl->strukt.padded_decl_id = declid(member);
|
||||
if (decl->attr_nopadding || member->attr_nopadding)
|
||||
{
|
||||
RETURN_SEMA_ERROR(member, "%d bytes of padding would be added to align this member.", align_offset - offset);
|
||||
RETURN_SEMA_ERROR(member, "%d bytes of padding would be added to align this member which is not allowed with `@nopadding` and `@compact`.", align_offset - offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sema_check_struct_holes(context, decl, member, member_type)) return false;
|
||||
if (!sema_check_struct_holes(context, decl, member)) return false;
|
||||
|
||||
offset = align_offset;
|
||||
member->offset = offset;
|
||||
@@ -641,9 +649,9 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl)
|
||||
{
|
||||
Decl *first_member = struct_members[0];
|
||||
Type *type = type_flatten(first_member->type);
|
||||
if (type->type_kind == TYPE_STRUCT && !type->decl->attr_nopadding)
|
||||
if (type_is_union_or_strukt(type) && !type->decl->attr_nopadding)
|
||||
{
|
||||
RETURN_SEMA_ERROR(first_member, "Inlined struct requires @nopadding attribute.");
|
||||
RETURN_SEMA_ERROR(first_member, "An inlined struct or union type also requires the `@nopadding` attribute.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
272
test/test_suite/struct/struct_nopadding_compact.c3t
Normal file
272
test/test_suite/struct/struct_nopadding_compact.c3t
Normal file
@@ -0,0 +1,272 @@
|
||||
module struct2;
|
||||
|
||||
struct Foo1
|
||||
{
|
||||
bool a @nopadding;
|
||||
int b;
|
||||
int c @nopadding;
|
||||
}
|
||||
|
||||
union Foo1_Union
|
||||
{
|
||||
bool a @nopadding;
|
||||
int b;
|
||||
int c @nopadding;
|
||||
}
|
||||
|
||||
struct Foo2 @nopadding
|
||||
{
|
||||
bool a;
|
||||
bool b;
|
||||
bool c;
|
||||
}
|
||||
|
||||
union Foo2_Union @nopadding
|
||||
{
|
||||
bool a;
|
||||
bool b;
|
||||
bool c;
|
||||
}
|
||||
|
||||
struct Foo3
|
||||
{
|
||||
bool a;
|
||||
int b @nopadding; // #error: 3 bytes of padding would be added
|
||||
int c @nopadding;
|
||||
}
|
||||
|
||||
struct Foo4 @nopadding
|
||||
{
|
||||
bool a;
|
||||
int b; // #error: 3 bytes of padding would be added
|
||||
int c;
|
||||
}
|
||||
|
||||
struct Foo5 @nopadding // #error: 3 bytes of padding would be added
|
||||
{
|
||||
int a;
|
||||
bool b;
|
||||
}
|
||||
|
||||
struct Foo5_B @align(16) @nopadding // #error: 8 bytes of padding would be added
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
}
|
||||
|
||||
struct Foo6 @nopadding
|
||||
{
|
||||
int a;
|
||||
struct // #error: 3 bytes of padding would be added
|
||||
{
|
||||
int b;
|
||||
bool c;
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo7 @nopadding
|
||||
{
|
||||
int a;
|
||||
struct nested
|
||||
{
|
||||
bool b;
|
||||
int c; // #error: 3 bytes of padding would be added
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo7_A @nopadding
|
||||
{
|
||||
int a;
|
||||
struct
|
||||
{
|
||||
bool b;
|
||||
union // #error: 7 bytes of padding would be added
|
||||
{
|
||||
int c;
|
||||
long d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo7_B @nopadding
|
||||
{
|
||||
int a;
|
||||
char[4] _pad;
|
||||
struct
|
||||
{
|
||||
long b;
|
||||
union
|
||||
{
|
||||
int c;
|
||||
long d;
|
||||
struct // #error: 3 bytes of padding would be added
|
||||
{
|
||||
int e;
|
||||
bool f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo7_C @nopadding
|
||||
{
|
||||
int a;
|
||||
char[4] _pad;
|
||||
struct
|
||||
{
|
||||
int b @align(8);
|
||||
union // #error: 4 bytes of padding would be added
|
||||
{
|
||||
int c;
|
||||
long d;
|
||||
struct
|
||||
{
|
||||
bool f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo10 @nopadding
|
||||
{
|
||||
inline Foo2 a;
|
||||
}
|
||||
|
||||
struct Foo11 @nopadding
|
||||
{
|
||||
inline Foo1 a; // #error: An inlined struct or union type also requires the `@nopadding` attribute
|
||||
}
|
||||
|
||||
struct Foo11_A @nopadding
|
||||
{
|
||||
inline Foo1_Union a; // #error: An inlined struct or union type also requires the `@nopadding` attribute
|
||||
}
|
||||
|
||||
union Foo12 @nopadding
|
||||
{
|
||||
int b;
|
||||
bool a;
|
||||
long c;
|
||||
struct
|
||||
{
|
||||
bool d;
|
||||
int e; // #error: 3 bytes of padding would be added
|
||||
}
|
||||
}
|
||||
|
||||
union Foo12_A @nopadding
|
||||
{
|
||||
int b;
|
||||
bool a;
|
||||
long c;
|
||||
}
|
||||
|
||||
struct Foo13 @nopadding
|
||||
{
|
||||
inline Foo12_A a;
|
||||
short b @align(32); // #error: 24 bytes of padding would be added
|
||||
}
|
||||
|
||||
struct Foo14 @compact // #error: 2 bytes of padding would be added to the end
|
||||
{
|
||||
Foo10 a @align(4);
|
||||
char[1] _pad;
|
||||
short b;
|
||||
}
|
||||
|
||||
struct Foo1_Compact
|
||||
{
|
||||
bool a @compact; // #error: '@compact' is not a valid member attribute
|
||||
int b;
|
||||
int c @compact;
|
||||
}
|
||||
|
||||
struct Foo2_Compact @compact
|
||||
{
|
||||
bool a;
|
||||
bool b;
|
||||
bool c;
|
||||
}
|
||||
|
||||
struct Foo4_Compact @compact
|
||||
{
|
||||
bool a;
|
||||
int b; // #error: 3 bytes of padding would be added
|
||||
int c;
|
||||
}
|
||||
|
||||
struct Foo5_Compact @compact // #error: 3 bytes of padding would be added
|
||||
{
|
||||
int a;
|
||||
bool b;
|
||||
}
|
||||
|
||||
struct Foo6_Compact @compact
|
||||
{
|
||||
int a;
|
||||
struct nested // #error: 3 bytes of padding would be added
|
||||
{
|
||||
int a;
|
||||
bool b;
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo7_Compact @compact
|
||||
{
|
||||
int a;
|
||||
struct nested
|
||||
{
|
||||
bool b;
|
||||
int a; // #error: 3 bytes of padding would be added
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo8 @compact
|
||||
{
|
||||
Foo8_A a; // #error: 'Foo8_A' has padding
|
||||
}
|
||||
|
||||
struct Foo8_A
|
||||
{
|
||||
long a;
|
||||
Foo8_B b;
|
||||
}
|
||||
|
||||
struct Foo8_B
|
||||
{
|
||||
int a;
|
||||
char[4] _pad;
|
||||
struct
|
||||
{
|
||||
long b;
|
||||
union
|
||||
{
|
||||
int c;
|
||||
long d;
|
||||
struct
|
||||
{
|
||||
int e;
|
||||
Foo8_C f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo8_C
|
||||
{
|
||||
bool a;
|
||||
int b;
|
||||
}
|
||||
|
||||
struct Foo9 @compact
|
||||
{
|
||||
Foo10 a;
|
||||
char[13] _pad;
|
||||
Foo9_A b; // #error: 'Foo9_A' has padding
|
||||
}
|
||||
|
||||
struct Foo9_A @align(16)
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
}
|
||||
Reference in New Issue
Block a user