diff options
Diffstat (limited to 'compiler/cpp/src/thrifty.yy')
-rw-r--r-- | compiler/cpp/src/thrifty.yy | 75 |
1 files changed, 51 insertions, 24 deletions
diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy index da5c562f9..3755d134c 100644 --- a/compiler/cpp/src/thrifty.yy +++ b/compiler/cpp/src/thrifty.yy @@ -53,6 +53,13 @@ * assigned starting from -1 and working their way down. */ int y_field_val = -1; +/** + * This global variable is used for automatic numbering of enum values. + * y_enum_val is the last value assigned; the next auto-assigned value will be + * y_enum_val+1, and then it continues working upwards. Explicitly specified + * enum values reset y_enum_val to that value. + */ +int32_t y_enum_val = -1; int g_arglist = 0; const int struct_is_struct = 0; const int struct_is_union = 1; @@ -200,6 +207,7 @@ const int struct_is_union = 1; %type<tenum> Enum %type<tenum> EnumDefList %type<tenumv> EnumDef +%type<tenumv> EnumValue %type<ttypedef> Senum %type<tbase> SenumDefList @@ -569,7 +577,7 @@ Enum: $$->annotations_ = $6->annotations_; delete $6; } - $$->resolve_values(); + // make constants for all the enum values if (g_parse_mode == PROGRAM) { const std::vector<t_enum_value*>& enum_values = $$->get_constants(); @@ -597,36 +605,28 @@ EnumDefList: { pdebug("EnumDefList -> "); $$ = new t_enum(g_program); + y_enum_val = -1; } EnumDef: - CaptureDocText tok_identifier '=' tok_int_constant TypeAnnotations CommaOrSemicolonOptional + CaptureDocText EnumValue TypeAnnotations CommaOrSemicolonOptional { - pdebug("EnumDef -> tok_identifier = tok_int_constant"); - if ($4 < 0) { - pwarning(1, "Negative value supplied for enum %s.\n", $2); - } - if ($4 > INT_MAX) { - pwarning(1, "64-bit value supplied for enum %s.\n", $2); - } - validate_simple_identifier( $2); - $$ = new t_enum_value($2, static_cast<int>($4)); + pdebug("EnumDef -> EnumValue"); + $$ = $2; if ($1 != NULL) { $$->set_doc($1); } - if ($5 != NULL) { - $$->annotations_ = $5->annotations_; - delete $5; - } - } -| - CaptureDocText tok_identifier TypeAnnotations CommaOrSemicolonOptional - { - pdebug("EnumDef -> tok_identifier"); - validate_simple_identifier( $2); - $$ = new t_enum_value($2); - if ($1 != NULL) { - $$->set_doc($1); + if (g_parse_mode == PROGRAM) { + // The scope constants never get deleted, so it's okay for us + // to share a single t_const object between our scope and the parent + // scope + t_const* constant = new t_const(g_type_i32, $2->get_name(), + new t_const_value($2->get_value())); + g_scope->add_constant($2->get_name(), constant); + if (g_parent_scope != NULL) { + g_parent_scope->add_constant(g_parent_prefix + $2->get_name(), + constant); + } } if ($3 != NULL) { $$->annotations_ = $3->annotations_; @@ -634,6 +634,33 @@ EnumDef: } } +EnumValue: + tok_identifier '=' tok_int_constant + { + pdebug("EnumValue -> tok_identifier = tok_int_constant"); + if ($3 < INT32_MIN || $3 > INT32_MAX) { + // Note: this used to be just a warning. However, since thrift always + // treats enums as i32 values, I'm changing it to a fatal error. + // I doubt this will affect many people, but users who run into this + // will have to update their thrift files to manually specify the + // truncated i32 value that thrift has always been using anyway. + failure("64-bit value supplied for enum %s will be truncated.", $1); + } + y_enum_val = static_cast<int32_t>($3); + $$ = new t_enum_value($1, y_enum_val); + } + | + tok_identifier + { + pdebug("EnumValue -> tok_identifier"); + validate_simple_identifier( $1); + if (y_enum_val == INT32_MAX) { + failure("enum value overflow at enum %s", $1); + } + ++y_enum_val; + $$ = new t_enum_value($1, y_enum_val); + } + Senum: tok_senum tok_identifier '{' SenumDefList '}' TypeAnnotations { |