Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/google/protobuf/repeated_field.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@ class SooRep {
Arena* arena() const {
return ResolveTaggedArena<&SooRep::resolver_, kResolverTaggedBits>(this);
}
int size() const { return size_; }
int size() const {
int res = size_;
PROTOBUF_ASSUME(res >= 0);
return res;
}
void set_size(int size) {
ABSL_DCHECK(!is_soo() || size <= kSooCapacityBytes);
size_ = size;
Expand Down Expand Up @@ -559,7 +563,9 @@ class ABSL_ATTRIBUTE_WARN_UNUSED PROTOBUF_DECLSPEC_EMPTY_BASES
soo_rep_.set_size(size);
}
int Capacity(bool is_soo) const {
return is_soo ? kSooCapacityElements : soo_rep_.capacity();
int res = is_soo ? kSooCapacityElements : soo_rep_.capacity();
PROTOBUF_ASSUME(res >= 0);
return res;
}

template <typename ArenaProvider>
Expand Down
8 changes: 8 additions & 0 deletions src/google/protobuf/repeated_field_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1620,4 +1620,12 @@ TEST(RepeatedFieldIsFullTest, DISABLED_MergeFromPacked) {
} // namespace protobuf
} // namespace google

// Code thunks to be dumped by the debugger to inspect the generated assemtbly.
static const int& CodegenRepeatedFieldGet(const google::protobuf::RepeatedField<int>& a,
int idx) {
return a[idx];
}

static volatile int odr_use = absl::HashOf(&CodegenRepeatedFieldGet);

#include "google/protobuf/port_undef.inc"
24 changes: 16 additions & 8 deletions src/google/protobuf/repeated_ptr_field.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,22 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
}

bool empty() const { return current_size_ == 0; }
int size() const { return current_size_; }
int size() const {
int res = current_size_;
PROTOBUF_ASSUME(res >= 0);
return res;
}
// Returns the size of the buffer with pointers to elements.
//
// Note:
//
// * prefer `SizeAtCapacity()` to `size() == Capacity()`;
// * prefer `AllocatedSizeAtCapacity()` to `allocated_size() == Capacity()`.
int Capacity() const { return using_sso() ? kSSOCapacity : rep()->capacity; }
int Capacity() const {
int res = using_sso() ? kSSOCapacity : rep()->capacity;
PROTOBUF_ASSUME(res >= 0);
return res;
}

template <typename TypeHandler>
const Value<TypeHandler>& at(int index) const {
Expand All @@ -249,7 +257,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {

template <typename TypeHandler>
Value<TypeHandler>* Mutable(int index) {
RuntimeAssertInBounds(index, current_size_);
RuntimeAssertInBounds(index, size());
return cast<TypeHandler>(element_at(index));
}

Expand Down Expand Up @@ -340,7 +348,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
PROTOBUF_FUTURE_ADD_NODISCARD const Value<TypeHandler>& Get(int index) const {
if constexpr (GetBoundsCheckMode() == BoundsCheckMode::kReturnDefault) {
if (ABSL_PREDICT_FALSE(index < 0 || index >= current_size_)) {
if (ABSL_PREDICT_FALSE(index < 0 || index >= size())) {
// `default_instance()` is not supported for MessageLite and Message.
if constexpr (TypeHandler::has_default_instance()) {
LogIndexOutOfBounds(index, current_size_);
Expand All @@ -350,7 +358,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
}
// We refactor this to a separate function instead of inlining it so we
// can measure the performance impact more easily.
RuntimeAssertInBounds(index, current_size_);
RuntimeAssertInBounds(index, size());
return *cast<TypeHandler>(element_at(index));
}

Expand Down Expand Up @@ -518,8 +526,8 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
}

void SwapElements(int index1, int index2) {
internal::RuntimeAssertInBounds(index1, current_size_);
internal::RuntimeAssertInBounds(index2, current_size_);
internal::RuntimeAssertInBounds(index1, size());
internal::RuntimeAssertInBounds(index2, size());
using std::swap; // enable ADL with fallback
swap(element_at(index1), element_at(index2));
}
Expand Down Expand Up @@ -625,7 +633,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
// arena.
template <typename TypeHandler>
Value<TypeHandler>* UnsafeArenaReleaseLast() {
internal::RuntimeAssertInBounds(0, current_size_);
internal::RuntimeAssertInBounds(0, size());
ExchangeCurrentSize(current_size_ - 1);
auto* result = cast<TypeHandler>(element_at(current_size_));
if (using_sso()) {
Expand Down
8 changes: 8 additions & 0 deletions src/google/protobuf/repeated_ptr_field_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2029,4 +2029,12 @@ TEST_F(RepeatedPtrFieldInsertionIteratorsTest, MoveProtos) {
} // namespace protobuf
} // namespace google

// Code thunks to be dumped by the debugger to inspect the generated assemtbly.
static auto& CodegenRepeatedPtrFieldGet(
const google::protobuf::RepeatedPtrField<std::string>& a, int idx) {
return a[idx];
}

static volatile int odr_use = absl::HashOf(&CodegenRepeatedPtrFieldGet);

#include "google/protobuf/port_undef.inc"
Loading