diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 6ee8c984e8d6..da6ba406bbc0 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -1061,7 +1061,7 @@ void Reflection::ListFields(const Message& message, if (oneof_case_array[containing_oneof->index()] == field->number()) { output->push_back(field); } - } else if (has_bits) { + } else if (has_bits && has_bits_indices[i] != -1) { // Equivalent to: HasBit(message, field) if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) { output->push_back(field); diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc index 27fb58b44c05..72fd8257db05 100644 --- a/src/google/protobuf/proto3_arena_unittest.cc +++ b/src/google/protobuf/proto3_arena_unittest.cc @@ -217,9 +217,15 @@ TEST(Proto3OptionalTest, OptionalFieldDescriptor) { for (int i = 0; i < d->field_count(); i++) { const FieldDescriptor* f = d->field(i); - EXPECT_TRUE(f->has_optional_keyword()) << f->full_name(); - EXPECT_TRUE(f->has_presence()) << f->full_name(); - EXPECT_TRUE(f->containing_oneof()) << f->full_name(); + if (HasPrefixString(f->name(), "singular")) { + EXPECT_FALSE(f->has_optional_keyword()) << f->full_name(); + EXPECT_FALSE(f->has_presence()) << f->full_name(); + EXPECT_FALSE(f->containing_oneof()) << f->full_name(); + } else { + EXPECT_TRUE(f->has_optional_keyword()) << f->full_name(); + EXPECT_TRUE(f->has_presence()) << f->full_name(); + EXPECT_TRUE(f->containing_oneof()) << f->full_name(); + } } } diff --git a/src/google/protobuf/unittest_proto3_optional.proto b/src/google/protobuf/unittest_proto3_optional.proto index b32a5d22b7a6..3c47f12e28b1 100644 --- a/src/google/protobuf/unittest_proto3_optional.proto +++ b/src/google/protobuf/unittest_proto3_optional.proto @@ -72,4 +72,8 @@ message TestProto3Optional { optional NestedMessage optional_nested_message = 18; optional NestedMessage lazy_nested_message = 19 [lazy = true]; optional NestedEnum optional_nested_enum = 21; + + // Add some non-optional fields to verify we can mix them. + int32 singular_int32 = 22; + int64 singular_int64 = 23; }