Skip to content

Commit c9a301e

Browse files
authored
Arrays of Enumerations without a value for 0 are no longer valid (google#8836)
* arrays of enums with no value for 0 now throw errors * move setting key field outside struct check * set to default instead of required * unsure of why these bfbs files have changed at this time, checking them in to run the pipelines. * remove known bad test
1 parent 19b2300 commit c9a301e

File tree

6 files changed

+4364
-4381
lines changed

6 files changed

+4364
-4381
lines changed

src/idl_parser.cpp

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,25 +1133,38 @@ CheckedError Parser::ParseField(StructDef& struct_def) {
11331133
}
11341134
}
11351135

1136-
// For historical convenience reasons, string keys are assumed required.
1137-
// Scalars are kDefault unless otherwise specified.
1138-
// Nonscalars are kOptional unless required;
11391136
field->key = field->attributes.Lookup("key") != nullptr;
1140-
const bool required = field->attributes.Lookup("required") != nullptr ||
1141-
(IsString(type) && field->key);
1142-
const bool default_str_or_vec =
1143-
((IsString(type) || IsVector(type)) && field->value.constant != "0");
1144-
const bool optional = IsScalar(type.base_type)
1145-
? (field->value.constant == "null")
1146-
: !(required || default_str_or_vec);
1147-
if (required && optional) {
1148-
return Error("Fields cannot be both optional and required.");
1149-
}
1150-
field->presence = FieldDef::MakeFieldPresence(optional, required);
11511137

1152-
if (required && (struct_def.fixed || IsScalar(type.base_type))) {
1153-
return Error("only non-scalar fields in tables may be 'required'");
1138+
if (!struct_def.fixed) {
1139+
// For historical convenience reasons, string keys are assumed required.
1140+
// Scalars are kDefault unless otherwise specified.
1141+
// Nonscalars are kOptional unless required;
1142+
const bool required = field->attributes.Lookup("required") != nullptr ||
1143+
(IsString(type) && field->key);
1144+
const bool default_str_or_vec =
1145+
((IsString(type) || IsVector(type)) && field->value.constant != "0");
1146+
const bool optional = IsScalar(type.base_type)
1147+
? (field->value.constant == "null")
1148+
: !(required || default_str_or_vec);
1149+
if (required && optional) {
1150+
return Error("Fields cannot be both optional and required.");
1151+
}
1152+
field->presence = FieldDef::MakeFieldPresence(optional, required);
1153+
1154+
if (required && IsScalar(type.base_type)) {
1155+
return Error("only non-scalar fields in tables may be 'required'");
1156+
}
1157+
} else {
1158+
// all struct fields are required
1159+
field->presence = FieldDef::kDefault;
1160+
1161+
// setting required or optional on a struct field is meaningless
1162+
if (field->attributes.Lookup("required") != nullptr ||
1163+
field->attributes.Lookup("optional") != nullptr) {
1164+
return Error("struct fields are always required");
1165+
}
11541166
}
1167+
11551168
if (field->key) {
11561169
if (struct_def.has_key) return Error("only one field may be set as 'key'");
11571170
struct_def.has_key = true;
@@ -1188,6 +1201,23 @@ CheckedError Parser::ParseField(StructDef& struct_def) {
11881201
}
11891202
}
11901203

1204+
auto check_enum = [this](const FieldDef* field, const Type& type,
1205+
const std::string& name,
1206+
const std::string& constant) -> CheckedError {
1207+
// Optional and bitflags enums may have default constants that are not
1208+
// their specified variants.
1209+
if (!field->IsOptional() &&
1210+
type.enum_def->attributes.Lookup("bit_flags") == nullptr) {
1211+
if (type.enum_def->FindByValue(constant) == nullptr) {
1212+
return Error("default value of `" + constant + "` for " + "field `" +
1213+
name + "` is not part of enum `" + type.enum_def->name +
1214+
"`.");
1215+
}
1216+
}
1217+
1218+
return NoError();
1219+
};
1220+
11911221
if (type.enum_def) {
11921222
// Verify the enum's type and default value.
11931223
const std::string& constant = field->value.constant;
@@ -1203,19 +1233,19 @@ CheckedError Parser::ParseField(StructDef& struct_def) {
12031233
if (constant != "0") {
12041234
return Error("Array defaults are not supported yet.");
12051235
}
1236+
CheckedError err = check_enum(field, type.VectorType(), name, constant);
1237+
if (err.Check()) {
1238+
// reset the check state of the error
1239+
return CheckedError{err};
1240+
}
12061241
} else {
12071242
if (!IsInteger(type.base_type)) {
12081243
return Error("Enums must have integer base types");
12091244
}
1210-
// Optional and bitflags enums may have default constants that are not
1211-
// their specified variants.
1212-
if (!field->IsOptional() &&
1213-
type.enum_def->attributes.Lookup("bit_flags") == nullptr) {
1214-
if (type.enum_def->FindByValue(constant) == nullptr) {
1215-
return Error("default value of `" + constant + "` for " + "field `" +
1216-
name + "` is not part of enum `" + type.enum_def->name +
1217-
"`.");
1218-
}
1245+
CheckedError err = check_enum(field, type, name, constant);
1246+
if (err.Check()) {
1247+
// reset the check state of the error
1248+
return CheckedError{err};
12191249
}
12201250
}
12211251
}

tests/arrays_test.bfbs

-104 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)