mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-27 16:38:06 +00:00
prevent force_align attribute on enums (#7523)
This commit is contained in:
@@ -79,7 +79,7 @@ static bool IsLowerSnakeCase(const std::string &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void DeserializeDoc(std::vector<std::string> &doc,
|
static void DeserializeDoc(std::vector<std::string> &doc,
|
||||||
const Vector<Offset<String>> *documentation) {
|
const Vector<Offset<String>> *documentation) {
|
||||||
if (documentation == nullptr) return;
|
if (documentation == nullptr) return;
|
||||||
for (uoffset_t index = 0; index < documentation->size(); index++)
|
for (uoffset_t index = 0; index < documentation->size(); index++)
|
||||||
doc.push_back(documentation->Get(index)->str());
|
doc.push_back(documentation->Get(index)->str());
|
||||||
@@ -87,13 +87,11 @@ static void DeserializeDoc(std::vector<std::string> &doc,
|
|||||||
|
|
||||||
static CheckedError NoError() { return CheckedError(false); }
|
static CheckedError NoError() { return CheckedError(false); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static std::string TypeToIntervalString() {
|
||||||
static std::string TypeToIntervalString() {
|
|
||||||
return "[" + NumToString((flatbuffers::numeric_limits<T>::lowest)()) + "; " +
|
return "[" + NumToString((flatbuffers::numeric_limits<T>::lowest)()) + "; " +
|
||||||
NumToString((flatbuffers::numeric_limits<T>::max)()) + "]";
|
NumToString((flatbuffers::numeric_limits<T>::max)()) + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// atot: template version of atoi/atof: convert a string to an instance of T.
|
// atot: template version of atoi/atof: convert a string to an instance of T.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool atot_scalar(const char *s, T *val, bool_constant<false>) {
|
static bool atot_scalar(const char *s, T *val, bool_constant<false>) {
|
||||||
@@ -120,15 +118,17 @@ static CheckedError atot(const char *s, Parser &parser, T *val) {
|
|||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
CheckedError atot<Offset<void>>(const char *s, Parser &parser,
|
CheckedError atot<Offset<void>>(const char *s, Parser &parser,
|
||||||
Offset<void> *val) {
|
Offset<void> *val) {
|
||||||
(void)parser;
|
(void)parser;
|
||||||
*val = Offset<void>(atoi(s));
|
*val = Offset<void>(atoi(s));
|
||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T *LookupTableByName(const SymbolTable<T> &table, const std::string &name,
|
static T *LookupTableByName(const SymbolTable<T> &table,
|
||||||
const Namespace ¤t_namespace, size_t skip_top) {
|
const std::string &name,
|
||||||
|
const Namespace ¤t_namespace,
|
||||||
|
size_t skip_top) {
|
||||||
const auto &components = current_namespace.components;
|
const auto &components = current_namespace.components;
|
||||||
if (table.dict.empty()) return nullptr;
|
if (table.dict.empty()) return nullptr;
|
||||||
if (components.size() < skip_top) return nullptr;
|
if (components.size() < skip_top) return nullptr;
|
||||||
@@ -187,9 +187,7 @@ static std::string TokenToString(int t) {
|
|||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
static bool IsIdentifierStart(char c) {
|
static bool IsIdentifierStart(char c) { return is_alpha(c) || (c == '_'); }
|
||||||
return is_alpha(c) || (c == '_');
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b,
|
static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b,
|
||||||
const FieldDef &key) {
|
const FieldDef &key) {
|
||||||
@@ -258,7 +256,8 @@ static void SwapSerializedTables(Offset<Table> *a, Offset<Table> *b) {
|
|||||||
|
|
||||||
// See below for why we need our own sort :(
|
// See below for why we need our own sort :(
|
||||||
template<typename T, typename F, typename S>
|
template<typename T, typename F, typename S>
|
||||||
static void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
|
static void SimpleQsort(T *begin, T *end, size_t width, F comparator,
|
||||||
|
S swapper) {
|
||||||
if (end - begin <= static_cast<ptrdiff_t>(width)) return;
|
if (end - begin <= static_cast<ptrdiff_t>(width)) return;
|
||||||
auto l = begin + width;
|
auto l = begin + width;
|
||||||
auto r = end;
|
auto r = end;
|
||||||
@@ -276,9 +275,7 @@ static void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper)
|
|||||||
SimpleQsort(r, end, width, comparator, swapper);
|
SimpleQsort(r, end, width, comparator, swapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T> static inline void SingleValueRepack(Value &e, T val) {
|
||||||
template<typename T>
|
|
||||||
static inline void SingleValueRepack(Value &e, T val) {
|
|
||||||
// Remove leading zeros.
|
// Remove leading zeros.
|
||||||
if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
|
if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
|
||||||
}
|
}
|
||||||
@@ -294,7 +291,6 @@ static void SingleValueRepack(Value &e, double val) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
|
template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
|
||||||
if (e1 < e2) { std::swap(e1, e2); } // use std for scalars
|
if (e1 < e2) { std::swap(e1, e2); } // use std for scalars
|
||||||
// Signed overflow may occur, use unsigned calculation.
|
// Signed overflow may occur, use unsigned calculation.
|
||||||
@@ -346,26 +342,19 @@ static uint64_t HashFile(const char *source_filename, const char *source) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static bool compareName(const T *a, const T *b) {
|
||||||
static bool compareName(const T *a, const T *b) {
|
|
||||||
return a->defined_namespace->GetFullyQualifiedName(a->name) <
|
return a->defined_namespace->GetFullyQualifiedName(a->name) <
|
||||||
b->defined_namespace->GetFullyQualifiedName(b->name);
|
b->defined_namespace->GetFullyQualifiedName(b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> static void AssignIndices(const std::vector<T *> &defvec) {
|
||||||
static void AssignIndices(const std::vector<T *> &defvec) {
|
|
||||||
// Pre-sort these vectors, such that we can set the correct indices for them.
|
// Pre-sort these vectors, such that we can set the correct indices for them.
|
||||||
auto vec = defvec;
|
auto vec = defvec;
|
||||||
std::sort(vec.begin(), vec.end(), compareName<T>);
|
std::sort(vec.begin(), vec.end(), compareName<T>);
|
||||||
for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
|
for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
const char *const kTypeNames[] = {
|
const char *const kTypeNames[] = {
|
||||||
@@ -384,7 +373,6 @@ const char kTypeSizes[] = {
|
|||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
||||||
void Parser::Message(const std::string &msg) {
|
void Parser::Message(const std::string &msg) {
|
||||||
if (!error_.empty()) error_ += "\n"; // log all warnings and errors
|
if (!error_.empty()) error_ += "\n"; // log all warnings and errors
|
||||||
error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
|
error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
|
||||||
@@ -447,7 +435,6 @@ class Parser::ParseDepthGuard {
|
|||||||
const int caller_depth_;
|
const int caller_depth_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
std::string Namespace::GetFullyQualifiedName(const std::string &name,
|
std::string Namespace::GetFullyQualifiedName(const std::string &name,
|
||||||
size_t max_components) const {
|
size_t max_components) const {
|
||||||
// Early exit if we don't have a defined namespace.
|
// Early exit if we don't have a defined namespace.
|
||||||
@@ -465,7 +452,6 @@ std::string Namespace::GetFullyQualifiedName(const std::string &name,
|
|||||||
return stream_str;
|
return stream_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Parser::TokenToStringId(int t) const {
|
std::string Parser::TokenToStringId(int t) const {
|
||||||
return t == kTokenIdentifier ? attribute_ : TokenToString(t);
|
return t == kTokenIdentifier ? attribute_ : TokenToString(t);
|
||||||
}
|
}
|
||||||
@@ -2413,6 +2399,9 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest,
|
|||||||
// todo: Convert to the Error in the future?
|
// todo: Convert to the Error in the future?
|
||||||
Warning("underlying type of bit_flags enum must be unsigned");
|
Warning("underlying type of bit_flags enum must be unsigned");
|
||||||
}
|
}
|
||||||
|
if (enum_def->attributes.Lookup("force_align")) {
|
||||||
|
return Error("`force_align` is not a valid attribute for Enums. ");
|
||||||
|
}
|
||||||
EnumValBuilder evb(*this, *enum_def);
|
EnumValBuilder evb(*this, *enum_def);
|
||||||
EXPECT('{');
|
EXPECT('{');
|
||||||
// A lot of code generatos expect that an enum is not-empty.
|
// A lot of code generatos expect that an enum is not-empty.
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ void ErrorTest() {
|
|||||||
TestError("enum X:float {}", "underlying");
|
TestError("enum X:float {}", "underlying");
|
||||||
TestError("enum X:byte { Y, Y }", "value already");
|
TestError("enum X:byte { Y, Y }", "value already");
|
||||||
TestError("enum X:byte { Y=2, Z=2 }", "unique");
|
TestError("enum X:byte { Y=2, Z=2 }", "unique");
|
||||||
|
TestError("enum X:byte (force_align: 4) { Y }", "force_align");
|
||||||
TestError("table X { Y:int; } table X {", "datatype already");
|
TestError("table X { Y:int; } table X {", "datatype already");
|
||||||
TestError("table X { } union X { }", "datatype already");
|
TestError("table X { } union X { }", "datatype already");
|
||||||
TestError("union X { } table X { }", "datatype already");
|
TestError("union X { } table X { }", "datatype already");
|
||||||
|
|||||||
Reference in New Issue
Block a user