Skip to content

Commit 6c56f19

Browse files
Daniel Kroeningtautschnig
Daniel Kroening
authored andcommitted
Do not attempt to compute union sizes when not required
Packed unions/structs without alignment specification may use fields of dynamic size. It is then unnecessary to compute their full size as it would never be used anyway.
1 parent 28fb804 commit 6c56f19

File tree

5 files changed

+91
-12
lines changed

5 files changed

+91
-12
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
static unsigned bar()
2+
{
3+
unsigned r;
4+
return r;
5+
}
6+
7+
#ifdef _MSC_VER
8+
9+
static void foo()
10+
{
11+
}
12+
13+
#else
14+
15+
static void foo()
16+
{
17+
unsigned len=bar();
18+
struct {
19+
int a;
20+
union {
21+
int s;
22+
unsigned char b[len];
23+
} __attribute__ (( packed )) S;
24+
int c;
25+
} __attribute__ (( packed )) *l;
26+
}
27+
28+
#endif
29+
30+
int main()
31+
{
32+
foo();
33+
return 0;
34+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <stdlib.h>
2+
#include <assert.h>
3+
4+
int main()
5+
{
6+
unsigned x;
7+
8+
if(x>=0 && x<=1000)
9+
{
10+
struct
11+
{
12+
int asd;
13+
14+
union {
15+
int i;
16+
char array[x];
17+
};
18+
} *ptr;
19+
20+
if(x<=sizeof(int))
21+
assert(sizeof(*ptr)==sizeof(int)*2);
22+
else
23+
assert(sizeof(*ptr)==sizeof(int)+x);
24+
}
25+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/ansi-c/padding.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -303,36 +303,40 @@ void add_padding(struct_typet &type, const namespacet &ns)
303303

304304
void add_padding(union_typet &type, const namespacet &ns)
305305
{
306-
mp_integer max_alignment=alignment(type, ns)*8;
307-
mp_integer size_bits=pointer_offset_bits(type, ns);
306+
mp_integer max_alignment_bits=alignment(type, ns)*8;
307+
mp_integer size_bits=0;
308308

309-
if(size_bits<0)
310-
throw "type of unknown size:\n"+type.pretty();
311-
312-
union_typet::componentst &components=type.components();
309+
// check per component, and ignore those without fixed size
310+
for(const auto &c : type.components())
311+
{
312+
mp_integer s=pointer_offset_bits(c.type(), ns);
313+
if(s>0)
314+
size_bits=std::max(size_bits, s);
315+
}
313316

314317
// Is the union packed?
315318
if(type.get_bool(ID_C_packed))
316319
{
317-
// The size needs to be a multiple of 8 only.
318-
max_alignment=8;
320+
// The size needs to be a multiple of 8 bits only.
321+
max_alignment_bits=8;
319322
}
320323

321324
// The size must be a multiple of the alignment, or
322325
// we add a padding member to the union.
323326

324-
if(size_bits%max_alignment!=0)
327+
if(size_bits%max_alignment_bits!=0)
325328
{
326-
mp_integer padding=max_alignment-(size_bits%max_alignment);
329+
mp_integer padding_bits=
330+
max_alignment_bits-(size_bits%max_alignment_bits);
327331

328332
unsignedbv_typet padding_type;
329-
padding_type.set_width(integer2unsigned(size_bits+padding));
333+
padding_type.set_width(integer2size_t(size_bits+padding_bits));
330334

331335
struct_typet::componentt component;
332336
component.type()=padding_type;
333337
component.set_name("$pad");
334338
component.set_is_padding(true);
335339

336-
components.push_back(component);
340+
type.components().push_back(component);
337341
}
338342
}

0 commit comments

Comments
 (0)