Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

duplicate label error in generated code with fields named step and loop_step #461

Closed
jcooper-korg opened this issue Jun 3, 2015 · 1 comment

Comments

@jcooper-korg
Copy link

If a message contains a repeated submessage step, and a field called loop_step, the generated pb.cc file will contain a duplicate label parse_loop_step and fail to build.
This same message built fine in proto2.x.
I know this seems like a contrived case, but it actually occurred in our code (a message describing a series of looping steps).

message StepTest
{
    message Step
    {
        optional int32 test = 1; 
    }
    repeated Step step = 1;     
    optional int32 loop_step = 2;
}

The generated code in proto3 is:

bool StepTest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:StepTest)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // repeated .StepTest.Step step = 1;
      case 1: {
        if (tag == 10) {
          DO_(input->IncrementRecursionDepth());
         parse_loop_step:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_step()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(10)) goto parse_loop_step;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectTag(16)) goto parse_loop_step;
        break;
      }

      // optional int32 loop_step = 2;
      case 2: {
        if (tag == 16) {
         parse_loop_step:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &loop_step_)));
          set_has_loop_step();
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:StepTest)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:StepTest)
  return false;
#undef DO_
}

And the error is:
StepTest.pb.cc(466): error C2045: 'parse_loop_step' : label redefined

The same message, built with proto2, generates this:

bool StepTest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
  ::google::protobuf::uint32 tag;
  while ((tag = input->ReadTag()) != 0) {
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // repeated .StepTest.Step step = 1;
      case 1: {
        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
         parse_step:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, add_step()));
        } else {
          goto handle_uninterpreted;
        }
        if (input->ExpectTag(10)) goto parse_step;
        if (input->ExpectTag(16)) goto parse_loop_step;
        break;
      }

      // optional int32 loop_step = 2;
      case 2: {
        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
         parse_loop_step:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &loop_step_)));
          set_has_loop_step();
        } else {
          goto handle_uninterpreted;
        }
        if (input->ExpectAtEnd()) return true;
        break;
      }

      default: {
      handle_uninterpreted:
        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          return true;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, mutable_unknown_fields()));
        break;
      }
    }
  }
  return true;
#undef DO_
}
@xfxyjwf
Copy link
Contributor

xfxyjwf commented Jan 20, 2016

Hi @jcooper-korg,

For such issues we usually only update the protocol compiler if renaming the field is not an option. Feel free to send us a patch if that's the case for you.

@xfxyjwf xfxyjwf closed this as completed Jan 20, 2016
taoso pushed a commit to taoso/protobuf that referenced this issue Aug 1, 2018
bithium pushed a commit to bithium/protobuf that referenced this issue Sep 4, 2023
Message and MessageMeta classes for Python
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants