mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-03 12:21:23 +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,
|
||||
const Vector<Offset<String>> *documentation) {
|
||||
const Vector<Offset<String>> *documentation) {
|
||||
if (documentation == nullptr) return;
|
||||
for (uoffset_t index = 0; index < documentation->size(); index++)
|
||||
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); }
|
||||
|
||||
template<typename T>
|
||||
static std::string TypeToIntervalString() {
|
||||
template<typename T> static std::string TypeToIntervalString() {
|
||||
return "[" + NumToString((flatbuffers::numeric_limits<T>::lowest)()) + "; " +
|
||||
NumToString((flatbuffers::numeric_limits<T>::max)()) + "]";
|
||||
}
|
||||
|
||||
|
||||
// atot: template version of atoi/atof: convert a string to an instance of T.
|
||||
template<typename T>
|
||||
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<>
|
||||
CheckedError atot<Offset<void>>(const char *s, Parser &parser,
|
||||
Offset<void> *val) {
|
||||
Offset<void> *val) {
|
||||
(void)parser;
|
||||
*val = Offset<void>(atoi(s));
|
||||
return NoError();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *LookupTableByName(const SymbolTable<T> &table, const std::string &name,
|
||||
const Namespace ¤t_namespace, size_t skip_top) {
|
||||
static T *LookupTableByName(const SymbolTable<T> &table,
|
||||
const std::string &name,
|
||||
const Namespace ¤t_namespace,
|
||||
size_t skip_top) {
|
||||
const auto &components = current_namespace.components;
|
||||
if (table.dict.empty()) return nullptr;
|
||||
if (components.size() < skip_top) return nullptr;
|
||||
@@ -187,9 +187,7 @@ static std::string TokenToString(int t) {
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
static bool IsIdentifierStart(char c) {
|
||||
return is_alpha(c) || (c == '_');
|
||||
}
|
||||
static bool IsIdentifierStart(char c) { return is_alpha(c) || (c == '_'); }
|
||||
|
||||
static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b,
|
||||
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 :(
|
||||
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;
|
||||
auto l = begin + width;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
|
||||
}
|
||||
@@ -294,7 +291,6 @@ static void SingleValueRepack(Value &e, double val) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
|
||||
if (e1 < e2) { std::swap(e1, e2); } // use std for scalars
|
||||
// Signed overflow may occur, use unsigned calculation.
|
||||
@@ -346,26 +342,19 @@ static uint64_t HashFile(const char *source_filename, const char *source) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool compareName(const T *a, const T *b) {
|
||||
template<typename T> static bool compareName(const T *a, const T *b) {
|
||||
return a->defined_namespace->GetFullyQualifiedName(a->name) <
|
||||
b->defined_namespace->GetFullyQualifiedName(b->name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void AssignIndices(const std::vector<T *> &defvec) {
|
||||
template<typename T> static void AssignIndices(const std::vector<T *> &defvec) {
|
||||
// Pre-sort these vectors, such that we can set the correct indices for them.
|
||||
auto vec = defvec;
|
||||
std::sort(vec.begin(), vec.end(), compareName<T>);
|
||||
for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
// clang-format off
|
||||
const char *const kTypeNames[] = {
|
||||
@@ -384,7 +373,6 @@ const char kTypeSizes[] = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
void Parser::Message(const std::string &msg) {
|
||||
if (!error_.empty()) error_ += "\n"; // log all warnings and errors
|
||||
error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
|
||||
@@ -447,7 +435,6 @@ class Parser::ParseDepthGuard {
|
||||
const int caller_depth_;
|
||||
};
|
||||
|
||||
|
||||
std::string Namespace::GetFullyQualifiedName(const std::string &name,
|
||||
size_t max_components) const {
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
std::string Parser::TokenToStringId(int t) const {
|
||||
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?
|
||||
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);
|
||||
EXPECT('{');
|
||||
// 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:byte { Y, Y }", "value already");
|
||||
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 { } union X { }", "datatype already");
|
||||
TestError("union X { } table X { }", "datatype already");
|
||||
|
||||
Reference in New Issue
Block a user