From 0b0cf58f24a007075d17bff42c3a2724eda8ddf2 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 1 Jun 2016 10:04:55 +0300 Subject: [PATCH 1/4] We already know the underlying_type. We just need to pass it to DEFINE_BITMASK_OPERATORS macro --- include/flatbuffers/flatbuffers.h | 6 +----- src/idl_gen_cpp.cpp | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 5de3a6611..b6260b6d5 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1485,21 +1485,17 @@ volatile __attribute__((weak)) const char *flatbuffer_version_string = #endif // !defined(_WIN32) && !defined(__CYGWIN__) -#define DEFINE_BITMASK_OPERATORS(E)\ +#define DEFINE_BITMASK_OPERATORS(E, T)\ inline E operator | (E lhs, E rhs){\ - using T = std::underlying_type::type;\ return E(T(lhs) | T(rhs));\ }\ inline E operator & (E lhs, E rhs){\ - using T = std::underlying_type::type;\ return E(T(lhs) & T(rhs));\ }\ inline E operator ^ (E lhs, E rhs){\ - using T = std::underlying_type::type;\ return E(T(lhs) ^ T(rhs));\ }\ inline E operator ~ (E lhs){\ - using T = std::underlying_type::type;\ return E(~T(lhs));\ }\ inline E operator |= (E &lhs, E rhs){\ diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index f0daca26a..f045fe4a5 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -184,7 +184,7 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def, code += GenEnumVal(enum_def, maxv->name, parser.opts) + "\n"; code += "};\n"; if (parser.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags")) - code += "DEFINE_BITMASK_OPERATORS(" + enum_def.name + ")\n"; + code += "DEFINE_BITMASK_OPERATORS(" + enum_def.name + ", " + GenTypeBasic(enum_def.underlying_type, false) + ")\n"; code += "\n"; // Generate a generate string table for enum values. From 038ea7c1d37cccac23ff962d8dcf62f6bce2a67f Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 1 Jun 2016 10:05:27 +0300 Subject: [PATCH 2/4] Add ! operator --- include/flatbuffers/flatbuffers.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index b6260b6d5..e487fe4d6 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1509,6 +1509,10 @@ volatile __attribute__((weak)) const char *flatbuffer_version_string = inline E operator ^= (E &lhs, E rhs){\ lhs = lhs ^ rhs;\ return lhs;\ + }\ + inline bool operator !(E rhs) \ + {\ + return !bool(T(rhs)); \ } /// @endcond } // namespace flatbuffers From cccd7003ed395d7f48ce28cac0cfd79e8e137eab Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 1 Jun 2016 10:03:40 +0300 Subject: [PATCH 3/4] MIN & MAX are useless for bit_flags Instead we need NONE (0) and ANY (all orred values), if the user didn't already defined them --- src/idl_gen_cpp.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index f045fe4a5..a163ee816 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -166,6 +166,7 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def, if (parser.opts.scoped_enums) code += " : " + GenTypeBasic(enum_def.underlying_type, false); code += " {\n"; + int64_t anyv = 0; EnumVal *minv = nullptr, *maxv = nullptr; for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); @@ -176,12 +177,20 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def, code += NumToString(ev.value) + ",\n"; minv = !minv || minv->value > ev.value ? &ev : minv; maxv = !maxv || maxv->value < ev.value ? &ev : maxv; + anyv |= ev.value; } assert(minv && maxv); - code += " " + GenEnumVal(enum_def, "MIN", parser.opts) + " = "; - code += GenEnumVal(enum_def, minv->name, parser.opts) + ",\n"; - code += " " + GenEnumVal(enum_def, "MAX", parser.opts) + " = "; - code += GenEnumVal(enum_def, maxv->name, parser.opts) + "\n"; + if (enum_def.attributes.Lookup("bit_flags")) { + if (minv->value != 0) // If the user didn't defined NONE value + code += " " + GenEnumVal(enum_def, "NONE", parser.opts) + " = 0,\n"; + if (maxv->value != anyv) // If the user didn't defined ANY value + code += " " + GenEnumVal(enum_def, "ANY", parser.opts) + " = " + NumToString(anyv) + "\n"; + } else { // MIN & MAX are useless for bit_flags + code += " " + GenEnumVal(enum_def, "MIN", parser.opts) + " = "; + code += GenEnumVal(enum_def, minv->name, parser.opts) + ",\n"; + code += " " + GenEnumVal(enum_def, "MAX", parser.opts) + " = "; + code += GenEnumVal(enum_def, maxv->name, parser.opts) + "\n"; + } code += "};\n"; if (parser.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags")) code += "DEFINE_BITMASK_OPERATORS(" + enum_def.name + ", " + GenTypeBasic(enum_def.underlying_type, false) + ")\n"; From 3e52fecd1ed1c68e62b441c9e227b64351eef1c4 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 1 Jun 2016 10:23:44 +0300 Subject: [PATCH 4/4] Don't generate MIN & MAX enum values if "--no-prefix" is used. Close #3892 --- src/idl_gen_cpp.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index a163ee816..1cb801356 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -179,17 +179,19 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def, maxv = !maxv || maxv->value < ev.value ? &ev : maxv; anyv |= ev.value; } - assert(minv && maxv); - if (enum_def.attributes.Lookup("bit_flags")) { - if (minv->value != 0) // If the user didn't defined NONE value - code += " " + GenEnumVal(enum_def, "NONE", parser.opts) + " = 0,\n"; - if (maxv->value != anyv) // If the user didn't defined ANY value - code += " " + GenEnumVal(enum_def, "ANY", parser.opts) + " = " + NumToString(anyv) + "\n"; - } else { // MIN & MAX are useless for bit_flags - code += " " + GenEnumVal(enum_def, "MIN", parser.opts) + " = "; - code += GenEnumVal(enum_def, minv->name, parser.opts) + ",\n"; - code += " " + GenEnumVal(enum_def, "MAX", parser.opts) + " = "; - code += GenEnumVal(enum_def, maxv->name, parser.opts) + "\n"; + if (parser.opts.scoped_enums || parser.opts.prefixed_enums) { + assert(minv && maxv); + if (enum_def.attributes.Lookup("bit_flags")) { + if (minv->value != 0) // If the user didn't defined NONE value + code += " " + GenEnumVal(enum_def, "NONE", parser.opts) + " = 0,\n"; + if (maxv->value != anyv) // If the user didn't defined ANY value + code += " " + GenEnumVal(enum_def, "ANY", parser.opts) + " = " + NumToString(anyv) + "\n"; + } else { // MIN & MAX are useless for bit_flags + code += " " + GenEnumVal(enum_def, "MIN", parser.opts) + " = "; + code += GenEnumVal(enum_def, minv->name, parser.opts) + ",\n"; + code += " " + GenEnumVal(enum_def, "MAX", parser.opts) + " = "; + code += GenEnumVal(enum_def, maxv->name, parser.opts) + "\n"; + } } code += "};\n"; if (parser.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags"))