Disallowed 0 byte structs.

This is because they are incompatible with C++ and possibly other
languages that make them minimum size 1 (to make sure multiple
such objects don't reside at the same address). Forcing them to size
1 was also not practical, as that is requires updating the logic
of a lot of implementations and thus possibly backwards incompatible.

More here: https://github.com/google/flatbuffers/issues/4122

Change-Id: I2bfdc8597b7cfd2235bb4074bb2ae06f81f8e57d
parent 705577de
...@@ -8,8 +8,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb; ...@@ -8,8 +8,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
import 'include_test1_my_game.example2_generated.dart'; import 'include_test1_my_game.example2_generated.dart';
import 'include_test2_my_game.example2_generated.dart'; import 'include_test2_my_game.example2_generated.dart';
import './monster_test_my_game.example_generated.dart' as my_game_example;
import './monster_test_my_game_generated.dart' as my_game; import './monster_test_my_game_generated.dart' as my_game;
import './monster_test_my_game.example_generated.dart' as my_game_example;
class Monster { class Monster {
Monster._(this._bc, this._bcOffset); Monster._(this._bc, this._bcOffset);
......
...@@ -8,8 +8,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb; ...@@ -8,8 +8,8 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
import 'include_test1_my_game.example_generated.dart'; import 'include_test1_my_game.example_generated.dart';
import 'include_test2_my_game.example_generated.dart'; import 'include_test2_my_game.example_generated.dart';
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
import './monster_test_my_game_generated.dart' as my_game; import './monster_test_my_game_generated.dart' as my_game;
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
class Color { class Color {
final int value; final int value;
......
...@@ -1778,21 +1778,24 @@ CheckedError Parser::ParseDecl() { ...@@ -1778,21 +1778,24 @@ CheckedError Parser::ParseDecl() {
EXPECT('{'); EXPECT('{');
while (token_ != '}') ECHECK(ParseField(*struct_def)); while (token_ != '}') ECHECK(ParseField(*struct_def));
auto force_align = struct_def->attributes.Lookup("force_align"); auto force_align = struct_def->attributes.Lookup("force_align");
if (fixed && force_align) { if (fixed) {
auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); if (force_align) {
if (force_align->type.base_type != BASE_TYPE_INT || auto align = static_cast<size_t>(atoi(force_align->constant.c_str()));
align < struct_def->minalign || align > FLATBUFFERS_MAX_ALIGNMENT || if (force_align->type.base_type != BASE_TYPE_INT ||
align & (align - 1)) align < struct_def->minalign || align > FLATBUFFERS_MAX_ALIGNMENT ||
return Error( align & (align - 1))
"force_align must be a power of two integer ranging from the" return Error(
"struct\'s natural alignment to " + "force_align must be a power of two integer ranging from the"
NumToString(FLATBUFFERS_MAX_ALIGNMENT)); "struct\'s natural alignment to " +
struct_def->minalign = align; NumToString(FLATBUFFERS_MAX_ALIGNMENT));
struct_def->minalign = align;
}
if (!struct_def->bytesize) return Error("size 0 structs not allowed");
} }
struct_def->PadLastField(struct_def->minalign); struct_def->PadLastField(struct_def->minalign);
// Check if this is a table that has manual id assignments // Check if this is a table that has manual id assignments
auto &fields = struct_def->fields.vec; auto &fields = struct_def->fields.vec;
if (!struct_def->fixed && fields.size()) { if (!fixed && fields.size()) {
size_t num_id_fields = 0; size_t num_id_fields = 0;
for (auto it = fields.begin(); it != fields.end(); ++it) { for (auto it = fields.begin(); it != fields.end(); ++it) {
if ((*it)->attributes.Lookup("id")) num_id_fields++; if ((*it)->attributes.Lookup("id")) num_id_fields++;
......
...@@ -5,7 +5,7 @@ namespace MyGame.OtherNameSpace; ...@@ -5,7 +5,7 @@ namespace MyGame.OtherNameSpace;
enum FromInclude:long { IncludeVal } enum FromInclude:long { IncludeVal }
struct Unused {} struct Unused { a:int; }
table TableB { table TableB {
a:TableA; a:TableA;
......
No preview for this file type
No preview for this file type
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
"MyGame_OtherNameSpace_Unused" : { "MyGame_OtherNameSpace_Unused" : {
"type" : "object", "type" : "object",
"properties" : { "properties" : {
"a" : { "type" : "number" }
}, },
"additionalProperties" : false "additionalProperties" : false
}, },
......
...@@ -1230,6 +1230,7 @@ void ErrorTest() { ...@@ -1230,6 +1230,7 @@ void ErrorTest() {
TestError("enum X:byte (bit_flags) { Y=8 }", "bit flag out"); TestError("enum X:byte (bit_flags) { Y=8 }", "bit flag out");
TestError("table X { Y:int; } table X {", "datatype already"); TestError("table X { Y:int; } table X {", "datatype already");
TestError("struct X (force_align: 7) { Y:int; }", "force_align"); TestError("struct X (force_align: 7) { Y:int; }", "force_align");
TestError("struct X {}", "size 0");
TestError("{}", "no root"); TestError("{}", "no root");
TestError("table X { Y:byte; } root_type X; { Y:1 } { Y:1 }", "end of file"); TestError("table X { Y:byte; } root_type X; { Y:1 } { Y:1 }", "end of file");
TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }", TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment