From 76f680afaededf946335cf4854c0b43d85a5033f Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 15 Jul 2025 22:35:26 +0200 Subject: [PATCH] Fix sizeof of structs with a trailing unbound array Fixes #574 Signed-off-by: Roberto Raggi --- src/parser/cxx/symbols.cc | 20 +++++++++++++++++++- tests/unit_tests/sema/sizeof_01.cc | 9 ++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/parser/cxx/symbols.cc b/src/parser/cxx/symbols.cc index 5c8c49f2..e8ef097c 100644 --- a/src/parser/cxx/symbols.cc +++ b/src/parser/cxx/symbols.cc @@ -290,18 +290,34 @@ auto ClassSymbol::buildClassLayout(Control* control) alignment = std::max(alignment, baseClassSymbol->alignment()); } + FieldSymbol* lastField = nullptr; + for (auto member : scope()->symbols()) { auto field = symbol_cast(member); if (!field) continue; if (field->isStatic()) continue; + if (lastField && control->is_unbounded_array(lastField->type())) { + // If the last field is an unbounded array, we cannot compute the offset + // of the next field, so we report an error. + return std::unexpected( + std::format("size of incomplete type '{}'", + to_string(lastField->type(), lastField->name()))); + } + if (!field->alignment()) { return std::unexpected( std::format("alignment of incomplete type '{}'", to_string(field->type(), field->name()))); } - auto size = memoryLayout->sizeOf(field->type()); + std::optional size; + + if (control->is_unbounded_array(field->type())) { + size = 0; + } else { + size = memoryLayout->sizeOf(field->type()); + } if (!size.has_value()) { return std::unexpected( @@ -318,6 +334,8 @@ auto ClassSymbol::buildClassLayout(Control* control) } alignment = std::max(alignment, field->alignment()); + + lastField = field; } offset = align_to(offset, alignment); diff --git a/tests/unit_tests/sema/sizeof_01.cc b/tests/unit_tests/sema/sizeof_01.cc index 259574b6..84118408 100644 --- a/tests/unit_tests/sema/sizeof_01.cc +++ b/tests/unit_tests/sema/sizeof_01.cc @@ -27,4 +27,11 @@ int elements[] = {1, 2, 3, 4, 5}; static_assert(sizeof(elements) == 5 * sizeof(int)); double d[]{1.0, 2.0, 3.0}; -static_assert(sizeof(d) == 3 * sizeof(double)); \ No newline at end of file +static_assert(sizeof(d) == 3 * sizeof(double)); + +struct X { + char i; + int dat[]; +}; +static_assert(sizeof(X) == 4); +static_assert(alignof(X) == 4); \ No newline at end of file