From 06181ce588ee58e87691a97da6a1cf7afa2c0148 Mon Sep 17 00:00:00 2001 From: Paul Serice Date: Thu, 8 Dec 2022 23:06:07 -0600 Subject: [PATCH] [C++] Add Command-Line Flag to Suppress MIN and MAX Enums Add the --no-minmax-values flag to prevent flatc from generating C++ enums with MIN and MAX enumerated values that otherwise would be set to the inclusive lower and upper bound respectively of the enum. This command-line flag is needed to avoid collisions when an enum that is being ported to FlatBuffers already has a MIN or MAX enumerated value. It is also needed to work around a long-standing problem with magic_enum that causes magic_enum to not see enumerated values that are not unique. For example, if FlatBuffers sets MIN = FOO and MAX = BAR, MIN and FOO share the same underlying value so they are not unique. The same is true of MAX and BAR. This prevents magic_enum from converting FOO and BAR to and from strings as well as causing magic_enum to return a count of enumerated values that is two fewer than it should be. --- docs/source/Compiler.md | 5 ++++- include/flatbuffers/idl.h | 2 ++ src/flatc.cpp | 5 +++++ src/idl_gen_cpp.cpp | 4 +++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md index 242506a5b0a..7571a4252ae 100644 --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@ -90,7 +90,10 @@ Additional options: - `--scoped-enums` : Use C++11 style scoped and strongly typed enums in generated C++. This also implies `--no-prefix`. - + +- `--no-emit-min-max-enum-values` : Disable generation of MIN and MAX + enumerated values for scoped enums and prefixed enums. + - `--gen-includes` : (deprecated), this is the default behavior. If the original behavior is required (no include statements) use `--no-includes.` diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index b564b1b2714..43b2ddf02bc 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -598,6 +598,7 @@ struct IDLOptions { bool output_enum_identifiers; bool prefixed_enums; bool scoped_enums; + bool emit_min_max_enum_values; bool swift_implementation_only; bool include_dependence_headers; bool mutable_buffer; @@ -711,6 +712,7 @@ struct IDLOptions { output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false), + emit_min_max_enum_values(true), swift_implementation_only(false), include_dependence_headers(true), mutable_buffer(false), diff --git a/src/flatc.cpp b/src/flatc.cpp index 998d77b8fcf..02119dd63a8 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -88,6 +88,9 @@ const static FlatCOption options[] = { { "", "scoped-enums", "", "Use C++11 style scoped and strongly typed enums. Also implies " "--no-prefix." }, + { "", "no-emit-min-max-enum-values", "", + "Disable generation of MIN and MAX enumerated values for scoped enums " + "and prefixed enums." }, { "", "swift-implementation-only", "", "Adds a @_implementationOnly to swift imports" }, { "", "gen-includes", "", @@ -464,6 +467,8 @@ int FlatCompiler::Compile(int argc, const char **argv) { } else if (arg == "--scoped-enums") { opts.prefixed_enums = false; opts.scoped_enums = true; + } else if (arg == "--no-emit-min-max-enum-values") { + opts.emit_min_max_enum_values = false; } else if (arg == "--no-union-value-namespacing") { opts.union_value_namespacing = false; } else if (arg == "--gen-mutable") { diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 5b9e181eb12..b8c162a4eda 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -1223,6 +1223,8 @@ class CppGenerator : public BaseGenerator { FLATBUFFERS_ASSERT(minv && maxv); code_.SetValue("SEP", ",\n"); + + // MIN & MAX are useless for bit_flags if (enum_def.attributes.Lookup("bit_flags")) { code_.SetValue("KEY", GenEnumValDecl(enum_def, "NONE")); code_.SetValue("VALUE", "0"); @@ -1233,7 +1235,7 @@ class CppGenerator : public BaseGenerator { NumToStringCpp(enum_def.AllFlags(), enum_def.underlying_type.base_type)); code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; - } else { // MIN & MAX are useless for bit_flags + } else if (opts_.emit_min_max_enum_values) { code_.SetValue("KEY", GenEnumValDecl(enum_def, "MIN")); code_.SetValue("VALUE", GenEnumValDecl(enum_def, Name(*minv))); code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";