Skip to content

Commit 18e16d5

Browse files
committed
Fix sizeof of structs with a trailing unbound array
Fixes #574 Signed-off-by: Roberto Raggi <[email protected]>
1 parent 31ce6de commit 18e16d5

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

src/parser/cxx/symbols.cc

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,18 +290,34 @@ auto ClassSymbol::buildClassLayout(Control* control)
290290
alignment = std::max(alignment, baseClassSymbol->alignment());
291291
}
292292

293+
FieldSymbol* lastField = nullptr;
294+
293295
for (auto member : scope()->symbols()) {
294296
auto field = symbol_cast<FieldSymbol>(member);
295297
if (!field) continue;
296298
if (field->isStatic()) continue;
297299

300+
if (lastField && control->is_unbounded_array(lastField->type())) {
301+
// If the last field is an unbounded array, we cannot compute the offset
302+
// of the next field, so we report an error.
303+
return std::unexpected(
304+
std::format("size of incomplete type '{}'",
305+
to_string(lastField->type(), lastField->name())));
306+
}
307+
298308
if (!field->alignment()) {
299309
return std::unexpected(
300310
std::format("alignment of incomplete type '{}'",
301311
to_string(field->type(), field->name())));
302312
}
303313

304-
auto size = memoryLayout->sizeOf(field->type());
314+
std::optional<std::size_t> size;
315+
316+
if (control->is_unbounded_array(field->type())) {
317+
size = 0;
318+
} else {
319+
size = memoryLayout->sizeOf(field->type());
320+
}
305321

306322
if (!size.has_value()) {
307323
return std::unexpected(
@@ -318,6 +334,8 @@ auto ClassSymbol::buildClassLayout(Control* control)
318334
}
319335

320336
alignment = std::max(alignment, field->alignment());
337+
338+
lastField = field;
321339
}
322340

323341
offset = align_to(offset, alignment);

tests/unit_tests/sema/sizeof_01.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@ int elements[] = {1, 2, 3, 4, 5};
2727
static_assert(sizeof(elements) == 5 * sizeof(int));
2828

2929
double d[]{1.0, 2.0, 3.0};
30-
static_assert(sizeof(d) == 3 * sizeof(double));
30+
static_assert(sizeof(d) == 3 * sizeof(double));
31+
32+
struct X {
33+
char i;
34+
int dat[];
35+
};
36+
static_assert(sizeof(X) == 4);
37+
static_assert(alignof(X) == 4);

0 commit comments

Comments
 (0)