aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-10-05 17:58:28 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-12-29 14:44:21 +0100
commit2cf493d1f63f075e6fe0cccbcb7463b1aa773a74 (patch)
treea673b2a8ad549a2631936ef54d141731859dc2e3
parentf07a1053a90039a2d88ed62f74add2ee131d67b7 (diff)
downloadsparse-2cf493d1f63f075e6fe0cccbcb7463b1aa773a74.tar.gz
packed: add support for __packed struct
Now that the 'packed' attribute is parsed and propagated into the type system, adapt the layout of structures. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--Documentation/TODO.md3
-rw-r--r--parse.c5
-rw-r--r--symbol.c12
-rw-r--r--symbol.h1
-rw-r--r--validation/packed-bitfield0.c1
-rw-r--r--validation/packed-bitfield1.c1
-rw-r--r--validation/packed-bitfield2.c1
-rw-r--r--validation/packed-bitfield5.c1
-rw-r--r--validation/packed-deref0.c1
-rw-r--r--validation/packed-struct.c1
10 files changed, 14 insertions, 13 deletions
diff --git a/Documentation/TODO.md b/Documentation/TODO.md
index 4dc9e63a..3f00bb11 100644
--- a/Documentation/TODO.md
+++ b/Documentation/TODO.md
@@ -4,9 +4,6 @@ TODO
Essential
---------
* SSA is broken by simplify_loads() & branches rewriting/simplification
-* attributes of struct, union & enums are ignored (and maybe others too).
- This requires correct support for __packed which itself needs partial
- and unaligned loads & stores (wip)
* add support for bitwise enums (wip)
Documentation
diff --git a/parse.c b/parse.c
index 338e525f..70be616c 100644
--- a/parse.c
+++ b/parse.c
@@ -767,6 +767,7 @@ static struct token *struct_union_enum_specifier(enum type type,
attr.ctype.base_type = sym;
token = handle_attributes(token, &attr);
apply_ctype(token->pos, &sym->ctype, &attr.ctype);
+ sym->packed = attr.packed;
sym->endpos = token->pos;
@@ -1089,8 +1090,10 @@ static struct token *ignore_attribute(struct token *token, struct symbol *attr,
static struct token *attribute_packed(struct token *token, struct symbol *attr, struct decl_state *ctx)
{
- if (!ctx->ctype.alignment)
+ if (!ctx->ctype.alignment) {
ctx->ctype.alignment = 1;
+ ctx->packed = 1;
+ }
return token;
}
diff --git a/symbol.c b/symbol.c
index 1a083fb8..aa02c8c5 100644
--- a/symbol.c
+++ b/symbol.c
@@ -88,6 +88,7 @@ struct struct_union_info {
unsigned long bit_size;
int align_size;
char has_flex_array;
+ bool packed;
struct symbol *flex_array;
};
@@ -120,6 +121,7 @@ static int bitfield_base_size(struct symbol *sym)
static void lay_out_struct(struct symbol *sym, struct struct_union_info *info)
{
unsigned long bit_size, align_bit_mask;
+ unsigned long alignment;
int base_size;
bit_size = info->bit_size;
@@ -136,7 +138,8 @@ static void lay_out_struct(struct symbol *sym, struct struct_union_info *info)
info->flex_array = sym;
}
- align_bit_mask = bytes_to_bits(sym->ctype.alignment) - 1;
+ alignment = info->packed ? 1 : sym->ctype.alignment;
+ align_bit_mask = bytes_to_bits(alignment) - 1;
/*
* Bitfields have some very special rules..
@@ -147,7 +150,7 @@ static void lay_out_struct(struct symbol *sym, struct struct_union_info *info)
// Zero-width fields just fill up the unit.
int width = base_size ? : (bit_offset ? room : 0);
- if (width > room) {
+ if (width > room && !info->packed) {
bit_size = (bit_size + align_bit_mask) & ~align_bit_mask;
bit_offset = 0;
}
@@ -157,6 +160,8 @@ static void lay_out_struct(struct symbol *sym, struct struct_union_info *info)
info->bit_size = bit_size + width;
// warning (sym->pos, "bitfield: offset=%d:%d size=:%d", sym->offset, sym->bit_offset, width);
+ if (info->packed && sym->type == SYM_NODE)
+ sym->packed = 1;
return;
}
@@ -173,6 +178,7 @@ static void lay_out_struct(struct symbol *sym, struct struct_union_info *info)
static struct symbol * examine_struct_union_type(struct symbol *sym, int advance)
{
struct struct_union_info info = {
+ .packed = sym->packed,
.max_align = 1,
.bit_size = 0,
.align_size = 1
@@ -191,7 +197,7 @@ static struct symbol * examine_struct_union_type(struct symbol *sym, int advance
sparse_error(info.flex_array->pos, "flexible array member '%s' is not last", show_ident(info.flex_array->ident));
examine_symbol_type(member);
- if (member->ctype.alignment > info.max_align) {
+ if (member->ctype.alignment > info.max_align && !sym->packed) {
// Unnamed bitfields do not affect alignment.
if (member->ident || !is_bitfield_type(member))
info.max_align = member->ctype.alignment;
diff --git a/symbol.h b/symbol.h
index 866d5752..15b21452 100644
--- a/symbol.h
+++ b/symbol.h
@@ -112,6 +112,7 @@ struct decl_state {
unsigned char prefer_abstract;
unsigned char autotype;
unsigned char forced;
+ unsigned char packed;
};
struct pseudo;
diff --git a/validation/packed-bitfield0.c b/validation/packed-bitfield0.c
index f84e7b90..2e209161 100644
--- a/validation/packed-bitfield0.c
+++ b/validation/packed-bitfield0.c
@@ -55,5 +55,4 @@ int main(void)
/*
* check-name: packed-bitfield0
- * check-known-to-fail
*/
diff --git a/validation/packed-bitfield1.c b/validation/packed-bitfield1.c
index 208a3dc5..b7b575ce 100644
--- a/validation/packed-bitfield1.c
+++ b/validation/packed-bitfield1.c
@@ -24,5 +24,4 @@ static int foo(struct s *ptr)
/*
* check-name: packed-bitfield1
- * check-known-to-fail
*/
diff --git a/validation/packed-bitfield2.c b/validation/packed-bitfield2.c
index 4587ebec..244204c2 100644
--- a/validation/packed-bitfield2.c
+++ b/validation/packed-bitfield2.c
@@ -12,5 +12,4 @@ _Static_assert(sizeof(struct bf2) == 8);
/*
* check-name: packed-bitfield2
- * check-known-to-fail
*/
diff --git a/validation/packed-bitfield5.c b/validation/packed-bitfield5.c
index 8f44d4c2..87dbf9c2 100644
--- a/validation/packed-bitfield5.c
+++ b/validation/packed-bitfield5.c
@@ -17,5 +17,4 @@ static int ld(struct s *s)
/*
* check-name: packed-bitfield5
* check-description: is check_access() OK with 'overlapping' packed bitfields?
- * check-known-to-fail
*/
diff --git a/validation/packed-deref0.c b/validation/packed-deref0.c
index 865ad68a..d48ad1ac 100644
--- a/validation/packed-deref0.c
+++ b/validation/packed-deref0.c
@@ -20,5 +20,4 @@ static void bar(obj_t o)
/*
* check-name: packed-deref0
- * check-known-to-fail
*/
diff --git a/validation/packed-struct.c b/validation/packed-struct.c
index e21d1153..dad22791 100644
--- a/validation/packed-struct.c
+++ b/validation/packed-struct.c
@@ -29,5 +29,4 @@ _Static_assert( sizeof(struct c) == 6, "size struct");
/*
* check-name: packed-struct
- * check-known-to-fail
*/