allocate immediately required fields (#1)

Reviewed-on: BigfootDev/flatbuffers-bigfoot#1
Co-authored-by: Romain BOULLARD <romain.boullard@protonmail.com>
This commit is contained in:
2026-08-23 11:22:46 +00:00
committed by rboullard
parent 4bd1e24e75
commit d239f8942c
6 changed files with 86 additions and 2 deletions
+39
View File
@@ -0,0 +1,39 @@
#include "required_table_default_test.h"
#include "required_table_default_test_generated.h"
#include "test_assert.h"
namespace flatbuffers {
namespace tests {
// Exercises the (required) table-field default member initializer added to
// GenMember() in idl_gen_cpp.cpp: a `(required)` table field can never
// legally be missing once Pack()/Verify() succeed, so a plain native default
// constructor must not leave it null - callers should never have to
// remember to allocate it themselves before the first Pack(). The sibling
// `optional_inner` field (same type, no `required`) is checked alongside it
// to confirm the change is scoped to required fields only.
void RequiredTableDefaultTest() {
using RequiredTableDefaultTestNS::Holder;
using RequiredTableDefaultTestNS::HolderT;
HolderT src;
TEST_NOTNULL(src.required_inner.get());
TEST_NULL(src.optional_inner.get());
// Never manually allocated required_inner - only relying on the default
// constructor above - yet Pack() must still succeed and round-trip it.
src.required_inner->value = 42;
flatbuffers::FlatBufferBuilder fbb;
fbb.Finish(Holder::Pack(fbb, &src));
auto dst = RequiredTableDefaultTestNS::UnPackHolder(fbb.GetBufferPointer());
TEST_NOTNULL(dst->required_inner.get());
TEST_EQ(dst->required_inner->value, 42u);
TEST_NULL(dst->optional_inner.get());
}
} // namespace tests
} // namespace flatbuffers
+17
View File
@@ -0,0 +1,17 @@
namespace RequiredTableDefaultTestNS;
table Inner {
value: uint32;
}
// `required_inner` has no default in the wire format (tables can't have one),
// but Pack()/Verify() both reject a buffer where it is missing - so the
// native default constructor must never leave it null. `optional_inner` is
// the same field type without `required`, kept alongside it to confirm the
// fix only changes required table fields, not every table pointer field.
table Holder {
required_inner: Inner (required);
optional_inner: Inner;
}
root_type Holder;
+12
View File
@@ -0,0 +1,12 @@
#ifndef REQUIRED_TABLE_DEFAULT_TEST_H
#define REQUIRED_TABLE_DEFAULT_TEST_H
namespace flatbuffers {
namespace tests {
void RequiredTableDefaultTest();
} // namespace tests
} // namespace flatbuffers
#endif // REQUIRED_TABLE_DEFAULT_TEST_H
+2
View File
@@ -68,6 +68,7 @@
#include "util_test.h"
#include "cpp_vector_type_test.h"
#include "bigfoot_ref_test_impl.h"
#include "required_table_default_test.h"
#include "vector_table_naked_ptr_test.h"
void FlatBufferBuilderTest();
@@ -1817,6 +1818,7 @@ int FlatBufferTests(const std::string& tests_data_path) {
FixedLengthArrayTest();
NativeTypeTest();
flatbuffers::tests::BigfootRefTest();
flatbuffers::tests::RequiredTableDefaultTest();
OptionalScalarsTest();
ParseFlexbuffersFromJsonWithNullTest();
FlatbuffersSpanTest();