diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 6d744ecf9d..e79e7ca919 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -786,18 +786,18 @@ void SwapFieldHelper::SwapMessage(const Reflection* r, Message* lhs, if (*lhs_sub != nullptr && *rhs_sub != nullptr) { (*lhs_sub)->GetReflection()->Swap(*lhs_sub, *rhs_sub); - } else if (*lhs_sub == nullptr && r->HasBit(*rhs, field)) { + } else if (*lhs_sub == nullptr && r->HasFieldSingular(*rhs, field)) { *lhs_sub = (*rhs_sub)->New(lhs_arena); (*lhs_sub)->CopyFrom(**rhs_sub); r->ClearField(rhs, field); // Ensures has bit is unchanged after ClearField. - r->SetBit(rhs, field); - } else if (*rhs_sub == nullptr && r->HasBit(*lhs, field)) { + r->SetHasBit(rhs, field); + } else if (*rhs_sub == nullptr && r->HasFieldSingular(*lhs, field)) { *rhs_sub = (*lhs_sub)->New(rhs_arena); (*rhs_sub)->CopyFrom(**lhs_sub); r->ClearField(lhs, field); // Ensures has bit is unchanged after ClearField. - r->SetBit(lhs, field); + r->SetHasBit(lhs, field); } } @@ -1161,7 +1161,7 @@ void Reflection::SwapFieldsImpl( // oneof already. This has to be done after SwapField, because SwapField // may depend on the information in has bits. if (!field->is_repeated()) { - SwapBit(message1, message2, field); + SwapHasBit(message1, message2, field); if (field->options().ctype() == FieldOptions::STRING && IsInlined(field)) { ABSL_DCHECK(!unsafe_shallow_swap || @@ -1217,7 +1217,7 @@ bool Reflection::HasField(const Message& message, if (schema_.InRealOneof(field)) { return HasOneofField(message, field); } else { - return HasBit(message, field); + return HasFieldSingular(message, field); } } } @@ -1363,8 +1363,8 @@ void Reflection::ClearField(Message* message, ClearOneofField(message, field); return; } - if (HasBit(*message, field)) { - ClearBit(message, field); + if (HasFieldSingular(*message, field)) { + ClearHasBit(message, field); // We need to set the field back to its default value. switch (field->cpp_type()) { @@ -1675,11 +1675,12 @@ void Reflection::ListFields(const Message& message, append_to_output(field); } } else if (has_bits && has_bits_indices[i] != static_cast(-1)) { - // Equivalent to: HasBit(message, field) + // Equivalent to: HasFieldSingular(message, field) if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) { append_to_output(field); } - } else if (HasBit(message, field)) { // Fall back on proto3-style HasBit. + } else if (HasFieldSingular(message, field)) { + // Fall back on proto3-style HasBit. append_to_output(field); } } @@ -2329,7 +2330,7 @@ Message* Reflection::MutableMessage(Message* message, *result_holder = default_message->New(message->GetArena()); } } else { - SetBit(message, field); + SetHasBit(message, field); } if (*result_holder == nullptr) { @@ -2363,9 +2364,9 @@ void Reflection::UnsafeArenaSetAllocatedMessage( } if (sub_message == nullptr) { - ClearBit(message, field); + ClearHasBit(message, field); } else { - SetBit(message, field); + SetHasBit(message, field); } Message** sub_message_holder = MutableRaw(message, field); if (message->GetArena() == nullptr) { @@ -2424,7 +2425,7 @@ Message* Reflection::UnsafeArenaReleaseMessage(Message* message, factory)); } else { if (!(field->is_repeated() || schema_.InRealOneof(field))) { - ClearBit(message, field); + ClearHasBit(message, field); } if (schema_.InRealOneof(field)) { if (HasOneofField(*message, field)) { @@ -2898,8 +2899,8 @@ void Reflection::SwapInlinedStringDonated(Message* lhs, Message* rhs, } // Simple accessors for manipulating has_bits_. -bool Reflection::HasBit(const Message& message, - const FieldDescriptor* field) const { +bool Reflection::HasFieldSingular(const Message& message, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); if (schema_.HasBitIndex(field) != static_cast(-1)) { return IsIndexInHasBitSet(GetHasBits(message), schema_.HasBitIndex(field)); @@ -2962,12 +2963,13 @@ bool Reflection::HasBit(const Message& message, // handled above; avoid warning break; } - ABSL_LOG(FATAL) << "Reached impossible case in HasBit()."; + ABSL_LOG(FATAL) << "Reached impossible case in HasFieldSingular()."; return false; } } -void Reflection::SetBit(Message* message, const FieldDescriptor* field) const { +void Reflection::SetHasBit(Message* message, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); const uint32_t index = schema_.HasBitIndex(field); if (index == static_cast(-1)) return; @@ -2975,8 +2977,8 @@ void Reflection::SetBit(Message* message, const FieldDescriptor* field) const { (static_cast(1) << (index % 32)); } -void Reflection::ClearBit(Message* message, - const FieldDescriptor* field) const { +void Reflection::ClearHasBit(Message* message, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); const uint32_t index = schema_.HasBitIndex(field); if (index == static_cast(-1)) return; @@ -2984,22 +2986,22 @@ void Reflection::ClearBit(Message* message, ~(static_cast(1) << (index % 32)); } -void Reflection::SwapBit(Message* message1, Message* message2, - const FieldDescriptor* field) const { +void Reflection::SwapHasBit(Message* message1, Message* message2, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); if (!schema_.HasHasbits()) { return; } - bool temp_has_bit = HasBit(*message1, field); - if (HasBit(*message2, field)) { - SetBit(message1, field); + bool temp_is_present = HasFieldSingular(*message1, field); + if (HasFieldSingular(*message2, field)) { + SetHasBit(message1, field); } else { - ClearBit(message1, field); + ClearHasBit(message1, field); } - if (temp_has_bit) { - SetBit(message2, field); + if (temp_is_present) { + SetHasBit(message2, field); } else { - ClearBit(message2, field); + ClearHasBit(message2, field); } } @@ -3127,14 +3129,14 @@ void Reflection::SetField(Message* message, const FieldDescriptor* field, ClearOneof(message, field->containing_oneof()); } *MutableRaw(message, field) = value; - real_oneof ? SetOneofCase(message, field) : SetBit(message, field); + real_oneof ? SetOneofCase(message, field) : SetHasBit(message, field); } template Type* Reflection::MutableField(Message* message, const FieldDescriptor* field) const { schema_.InRealOneof(field) ? SetOneofCase(message, field) - : SetBit(message, field); + : SetHasBit(message, field); return MutableRaw(message, field); } diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 3527ce2039..6f0c0c52e3 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -1234,11 +1234,17 @@ class PROTOBUF_EXPORT Reflection final { return schema_.IsFieldInlined(field); } - bool HasBit(const Message& message, const FieldDescriptor* field) const; - void SetBit(Message* message, const FieldDescriptor* field) const; - inline void ClearBit(Message* message, const FieldDescriptor* field) const; - inline void SwapBit(Message* message1, Message* message2, - const FieldDescriptor* field) const; + // Returns true if the field is considered to be present. + // Requires the input to be 'singular' i.e. non-extension, non-oneof, non-weak + // field. + // For explicit presence fields, a field is present iff the hasbit is set. + // For implicit presence fields, a field is present iff it is nonzero. + bool HasFieldSingular(const Message& message, + const FieldDescriptor* field) const; + void SetHasBit(Message* message, const FieldDescriptor* field) const; + inline void ClearHasBit(Message* message, const FieldDescriptor* field) const; + inline void SwapHasBit(Message* message1, Message* message2, + const FieldDescriptor* field) const; inline const uint32_t* GetInlinedStringDonatedArray( const Message& message) const; diff --git a/src/google/protobuf/reflection_visit_fields.h b/src/google/protobuf/reflection_visit_fields.h index 063486dc2c..d1b317bc2f 100644 --- a/src/google/protobuf/reflection_visit_fields.h +++ b/src/google/protobuf/reflection_visit_fields.h @@ -249,7 +249,7 @@ void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func, if ((has_bits[index / 32] & (1u << (index % 32))) == 0) continue; } else { // Skip if it has default values. - if (!reflection->HasBit(message, field)) continue; + if (!reflection->HasFieldSingular(message, field)) continue; } switch (field->type()) { #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \