Add `ABSL_ATTRIBUTE_LIFETIME_BOUND` attribute on Map, RepeatedField and RepeatedPtrField.

This allows the compiler to statically detect use-after-free bugs.

PiperOrigin-RevId: 532245526
pull/12818/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 78ad0933a7
commit 7b7ba2df67
  1. 54
      src/google/protobuf/map.h
  2. 111
      src/google/protobuf/repeated_field.h
  3. 117
      src/google/protobuf/repeated_ptr_field.h

@ -51,6 +51,7 @@
#endif
#include "google/protobuf/stubs/common.h"
#include "absl/base/attributes.h"
#include "absl/container/btree_map.h"
#include "absl/hash/hash.h"
#include "absl/meta/type_traits.h"
@ -1135,7 +1136,7 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
}
}
Map& operator=(Map&& other) noexcept {
Map& operator=(Map&& other) noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (this != &other) {
if (arena() != other.arena()) {
*this = other;
@ -1300,38 +1301,44 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
friend class Map;
};
iterator begin() { return iterator(this); }
iterator end() { return iterator(); }
const_iterator begin() const { return const_iterator(this); }
const_iterator end() const { return const_iterator(); }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(this); }
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(); }
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator(this);
}
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator();
}
const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return begin();
}
const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
using Base::empty;
using Base::size;
// Element access
template <typename K = key_type>
T& operator[](const key_arg<K>& key) {
T& operator[](const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(key).first->second;
}
template <
typename K = key_type,
// Disable for integral types to reduce code bloat.
typename = typename std::enable_if<!std::is_integral<K>::value>::type>
T& operator[](key_arg<K>&& key) {
T& operator[](key_arg<K>&& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(std::forward<K>(key)).first->second;
}
template <typename K = key_type>
const T& at(const key_arg<K>& key) const {
const T& at(const key_arg<K>& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
const_iterator it = find(key);
ABSL_CHECK(it != end()) << "key not found: " << static_cast<Key>(key);
return it->second;
}
template <typename K = key_type>
T& at(const key_arg<K>& key) {
T& at(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
iterator it = find(key);
ABSL_CHECK(it != end()) << "key not found: " << static_cast<Key>(key);
return it->second;
@ -1344,11 +1351,12 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
}
template <typename K = key_type>
const_iterator find(const key_arg<K>& key) const {
const_iterator find(const key_arg<K>& key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_cast<Map*>(this)->find(key);
}
template <typename K = key_type>
iterator find(const key_arg<K>& key) {
iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto res = this->FindHelper(key);
return iterator(static_cast<Node*>(res.node), this, res.bucket);
}
@ -1360,7 +1368,7 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
template <typename K = key_type>
std::pair<const_iterator, const_iterator> equal_range(
const key_arg<K>& key) const {
const key_arg<K>& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
const_iterator it = find(key);
if (it == end()) {
return std::pair<const_iterator, const_iterator>(it, it);
@ -1371,7 +1379,8 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
}
template <typename K = key_type>
std::pair<iterator, iterator> equal_range(const key_arg<K>& key) {
std::pair<iterator, iterator> equal_range(const key_arg<K>& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
iterator it = find(key);
if (it == end()) {
return std::pair<iterator, iterator>(it, it);
@ -1383,7 +1392,8 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
// insert
template <typename K, typename... Args>
std::pair<iterator, bool> try_emplace(K&& k, Args&&... args) {
std::pair<iterator, bool> try_emplace(K&& k, Args&&... args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Inserts a new element into the container if there is no element with the
// key in the container.
// The new element is:
@ -1395,16 +1405,18 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
std::forward<K>(k),
std::forward<Args>(args)...);
}
std::pair<iterator, bool> insert(init_type&& value) {
std::pair<iterator, bool> insert(init_type&& value)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(std::move(value.first), std::move(value.second));
}
template <typename P, RequiresInsertable<P> = 0>
std::pair<iterator, bool> insert(P&& value) {
std::pair<iterator, bool> insert(P&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(std::forward<P>(value).first,
std::forward<P>(value).second);
}
template <typename... Args>
std::pair<iterator, bool> emplace(Args&&... args) {
std::pair<iterator, bool> emplace(Args&&... args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return EmplaceInternal(Rank0{}, std::forward<Args>(args)...);
}
template <class InputIt>
@ -1435,7 +1447,7 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
}
}
iterator erase(iterator pos) {
iterator erase(iterator pos) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto next = std::next(pos);
ABSL_DCHECK_EQ(pos.m_, static_cast<Base*>(this));
auto* node = static_cast<Node*>(pos.node_);
@ -1475,7 +1487,7 @@ class Map : private internal::KeyMapBase<internal::KeyForBase<Key>> {
}
// Assign
Map& operator=(const Map& other) {
Map& operator=(const Map& other) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (this != &other) {
clear();
insert(other.begin(), other.end());

@ -54,6 +54,7 @@
#include "google/protobuf/arena.h"
#include "google/protobuf/port.h"
#include "absl/base/attributes.h"
#include "absl/base/dynamic_annotations.h"
#include "absl/log/absl_check.h"
#include "absl/meta/type_traits.h"
@ -193,29 +194,35 @@ class RepeatedField final
~RepeatedField();
RepeatedField& operator=(const RepeatedField& other);
RepeatedField& operator=(const RepeatedField& other)
ABSL_ATTRIBUTE_LIFETIME_BOUND;
RepeatedField(RepeatedField&& other) noexcept;
RepeatedField& operator=(RepeatedField&& other) noexcept;
RepeatedField& operator=(RepeatedField&& other) noexcept
ABSL_ATTRIBUTE_LIFETIME_BOUND;
bool empty() const;
int size() const;
const Element& Get(int index) const;
Element* Mutable(int index);
const Element& Get(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
Element* Mutable(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND;
const Element& operator[](int index) const { return Get(index); }
Element& operator[](int index) { return *Mutable(index); }
const Element& operator[](int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return Get(index);
}
Element& operator[](int index) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return *Mutable(index);
}
const Element& at(int index) const;
Element& at(int index);
const Element& at(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
Element& at(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND;
void Set(int index, const Element& value);
void Add(Element value);
// Appends a new element and returns a pointer to it.
// The new element is uninitialized if |Element| is a POD type.
Element* Add();
Element* Add() ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Appends elements in the range [begin, end) after reserving
// the appropriate number of elements.
template <typename Iter>
@ -251,8 +258,8 @@ class RepeatedField final
// Adds `n` elements to this instance asserting there is enough capacity.
// The added elements are uninitialized if `Element` is trivial.
Element* AddAlreadyReserved();
Element* AddNAlreadyReserved(int n);
Element* AddAlreadyReserved() ABSL_ATTRIBUTE_LIFETIME_BOUND;
Element* AddNAlreadyReserved(int n) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Like STL resize. Uses value to fill appended elements.
// Like Truncate() if new_size <= size(), otherwise this is
@ -261,8 +268,8 @@ class RepeatedField final
// Gets the underlying array. This pointer is possibly invalidated by
// any add or remove operation.
Element* mutable_data();
const Element* data() const;
Element* mutable_data() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const Element* data() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Swaps entire contents with "other". If they are separate arenas, then
// copies data between each other.
@ -282,22 +289,26 @@ class RepeatedField final
typedef int size_type;
typedef ptrdiff_t difference_type;
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;
iterator end();
const_iterator end() const;
const_iterator cend() const;
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Reverse iterator support
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(end());
}
const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(end());
}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {
reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(begin());
}
const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(begin());
}
@ -315,14 +326,15 @@ class RepeatedField final
// element.
//
// Invalidates all iterators at or after the removed element, including end().
iterator erase(const_iterator position);
iterator erase(const_iterator position) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Removes the elements in the range [first, last).
//
// Returns an iterator to the element immediately following the removed range.
//
// Invalidates all iterators at or after the removed range, including end().
iterator erase(const_iterator first, const_iterator last);
iterator erase(const_iterator first,
const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Gets the Arena on which this RepeatedField stores its elements.
// Note: this can be inaccurate for split default fields so we make this
@ -537,7 +549,7 @@ RepeatedField<Element>::~RepeatedField() {
template <typename Element>
inline RepeatedField<Element>& RepeatedField<Element>::operator=(
const RepeatedField& other) {
const RepeatedField& other) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (this != &other) CopyFrom(other);
return *this;
}
@ -561,7 +573,7 @@ inline RepeatedField<Element>::RepeatedField(RepeatedField&& other) noexcept
template <typename Element>
inline RepeatedField<Element>& RepeatedField<Element>::operator=(
RepeatedField&& other) noexcept {
RepeatedField&& other) noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
// We don't just call Swap(&other) here because it would perform 3 copies if
// the two fields are on different arenas.
if (this != &other) {
@ -601,7 +613,8 @@ inline void RepeatedField<Element>::AddAlreadyReserved(Element value) {
}
template <typename Element>
inline Element* RepeatedField<Element>::AddAlreadyReserved() {
inline Element* RepeatedField<Element>::AddAlreadyReserved()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_DCHECK_LT(current_size_, total_size_);
// new (p) <TrivialType> compiles into nothing: this is intentional as this
// function is documented to return uninitialized data for trivial types.
@ -610,7 +623,8 @@ inline Element* RepeatedField<Element>::AddAlreadyReserved() {
}
template <typename Element>
inline Element* RepeatedField<Element>::AddNAlreadyReserved(int n) {
inline Element* RepeatedField<Element>::AddNAlreadyReserved(int n)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_DCHECK_GE(total_size_ - current_size_, n)
<< total_size_ << ", " << current_size_;
Element* p = unsafe_elements() + ExchangeCurrentSize(current_size_ + n);
@ -634,28 +648,32 @@ inline void RepeatedField<Element>::Resize(int new_size, const Element& value) {
}
template <typename Element>
inline const Element& RepeatedField<Element>::Get(int index) const {
inline const Element& RepeatedField<Element>::Get(int index) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_DCHECK_GE(index, 0);
ABSL_DCHECK_LT(index, current_size_);
return elements()[index];
}
template <typename Element>
inline const Element& RepeatedField<Element>::at(int index) const {
inline const Element& RepeatedField<Element>::at(int index) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_CHECK_GE(index, 0);
ABSL_CHECK_LT(index, current_size_);
return elements()[index];
}
template <typename Element>
inline Element& RepeatedField<Element>::at(int index) {
inline Element& RepeatedField<Element>::at(int index)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_CHECK_GE(index, 0);
ABSL_CHECK_LT(index, current_size_);
return elements()[index];
}
template <typename Element>
inline Element* RepeatedField<Element>::Mutable(int index) {
inline Element* RepeatedField<Element>::Mutable(int index)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_DCHECK_GE(index, 0);
ABSL_DCHECK_LT(index, current_size_);
return &elements()[index];
@ -688,7 +706,7 @@ inline void RepeatedField<Element>::Add(Element value) {
}
template <typename Element>
inline Element* RepeatedField<Element>::Add() {
inline Element* RepeatedField<Element>::Add() ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(current_size_ == total_size_)) {
Grow(current_size_, current_size_ + 1);
}
@ -809,13 +827,13 @@ inline void RepeatedField<Element>::Assign(Iter begin, Iter end) {
template <typename Element>
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
const_iterator position) {
const_iterator position) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return erase(position, position + 1);
}
template <typename Element>
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
const_iterator first, const_iterator last) {
const_iterator first, const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
size_type first_offset = first - cbegin();
if (first != last) {
Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin());
@ -824,12 +842,14 @@ inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
}
template <typename Element>
inline Element* RepeatedField<Element>::mutable_data() {
inline Element* RepeatedField<Element>::mutable_data()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return unsafe_elements();
}
template <typename Element>
inline const Element* RepeatedField<Element>::data() const {
inline const Element* RepeatedField<Element>::data() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return unsafe_elements();
}
@ -879,32 +899,33 @@ void RepeatedField<Element>::SwapElements(int index1, int index2) {
}
template <typename Element>
inline typename RepeatedField<Element>::iterator
RepeatedField<Element>::begin() {
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::begin()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(unsafe_elements());
}
template <typename Element>
inline typename RepeatedField<Element>::const_iterator
RepeatedField<Element>::begin() const {
RepeatedField<Element>::begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator(unsafe_elements());
}
template <typename Element>
inline typename RepeatedField<Element>::const_iterator
RepeatedField<Element>::cbegin() const {
RepeatedField<Element>::cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator(unsafe_elements());
}
template <typename Element>
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::end() {
inline typename RepeatedField<Element>::iterator RepeatedField<Element>::end()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(unsafe_elements() + current_size_);
}
template <typename Element>
inline typename RepeatedField<Element>::const_iterator
RepeatedField<Element>::end() const {
RepeatedField<Element>::end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator(unsafe_elements() + current_size_);
}
template <typename Element>
inline typename RepeatedField<Element>::const_iterator
RepeatedField<Element>::cend() const {
RepeatedField<Element>::cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_iterator(unsafe_elements() + current_size_);
}

@ -58,6 +58,7 @@
#include "google/protobuf/arena.h"
#include "google/protobuf/port.h"
#include "absl/base/attributes.h"
#include "absl/log/absl_check.h"
#include "google/protobuf/message_lite.h"
#include "google/protobuf/port.h"
@ -931,22 +932,24 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
~RepeatedPtrField();
RepeatedPtrField& operator=(const RepeatedPtrField& other);
RepeatedPtrField& operator=(const RepeatedPtrField& other)
ABSL_ATTRIBUTE_LIFETIME_BOUND;
RepeatedPtrField(RepeatedPtrField&& other) noexcept;
RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept;
RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept
ABSL_ATTRIBUTE_LIFETIME_BOUND;
bool empty() const;
int size() const;
const Element& Get(int index) const;
Element* Mutable(int index);
const Element& Get(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
Element* Mutable(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Unlike std::vector, adding an element to a RepeatedPtrField doesn't always
// make a new element; it might re-use an element left over from when the
// field was Clear()'d or reize()'d smaller. For this reason, Add() is the
// fastest API for adding a new element.
Element* Add();
Element* Add() ABSL_ATTRIBUTE_LIFETIME_BOUND;
// `Add(std::move(value));` is equivalent to `*Add() = std::move(value);`
// It will either move-construct to the end of this field, or swap value
@ -968,11 +971,15 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
template <typename Iter>
void Add(Iter begin, Iter end);
const Element& operator[](int index) const { return Get(index); }
Element& operator[](int index) { return *Mutable(index); }
const Element& operator[](int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return Get(index);
}
Element& operator[](int index) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return *Mutable(index);
}
const Element& at(int index) const;
Element& at(int index);
const Element& at(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
Element& at(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Removes the last element in the array.
// Ownership of the element is retained by the array.
@ -1001,8 +1008,8 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
// Gets the underlying array. This pointer is possibly invalidated by
// any add or remove operation.
Element**
mutable_data();
const Element* const* data() const;
mutable_data() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const Element* const* data() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Swaps entire contents with "other". If they are on separate arenas, then
// copies data.
@ -1028,22 +1035,26 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
typedef int size_type;
typedef ptrdiff_t difference_type;
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;
iterator end();
const_iterator end() const;
const_iterator cend() const;
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Reverse iterator support
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(end());
}
const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(end());
}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {
reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(begin());
}
const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(begin());
}
@ -1054,10 +1065,10 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
typedef internal::RepeatedPtrOverPtrsIterator<const Element* const,
const void* const>
const_pointer_iterator;
pointer_iterator pointer_begin();
const_pointer_iterator pointer_begin() const;
pointer_iterator pointer_end();
const_pointer_iterator pointer_end() const;
pointer_iterator pointer_begin() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_pointer_iterator pointer_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
pointer_iterator pointer_end() ABSL_ATTRIBUTE_LIFETIME_BOUND;
const_pointer_iterator pointer_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Returns (an estimate of) the number of bytes used by the repeated field,
// excluding sizeof(*this).
@ -1174,14 +1185,15 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
// element.
//
// Invalidates all iterators at or after the removed element, including end().
iterator erase(const_iterator position);
iterator erase(const_iterator position) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Removes the elements in the range [first, last).
//
// Returns an iterator to the element immediately following the removed range.
//
// Invalidates all iterators at or after the removed range, including end().
iterator erase(const_iterator first, const_iterator last);
iterator erase(const_iterator first,
const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Gets the arena on which this RepeatedPtrField stores its elements.
inline Arena* GetArena();
@ -1282,7 +1294,7 @@ RepeatedPtrField<Element>::~RepeatedPtrField() {
template <typename Element>
inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
const RepeatedPtrField& other) {
const RepeatedPtrField& other) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (this != &other) CopyFrom(other);
return *this;
}
@ -1307,7 +1319,7 @@ inline RepeatedPtrField<Element>::RepeatedPtrField(
template <typename Element>
inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
RepeatedPtrField&& other) noexcept {
RepeatedPtrField&& other) noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
// We don't just call Swap(&other) here because it would perform 3 copies if
// the two fields are on different arenas.
if (this != &other) {
@ -1335,28 +1347,33 @@ inline int RepeatedPtrField<Element>::size() const {
}
template <typename Element>
inline const Element& RepeatedPtrField<Element>::Get(int index) const {
inline const Element& RepeatedPtrField<Element>::Get(int index) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return RepeatedPtrFieldBase::Get<TypeHandler>(index);
}
template <typename Element>
inline const Element& RepeatedPtrField<Element>::at(int index) const {
inline const Element& RepeatedPtrField<Element>::at(int index) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return RepeatedPtrFieldBase::at<TypeHandler>(index);
}
template <typename Element>
inline Element& RepeatedPtrField<Element>::at(int index) {
inline Element& RepeatedPtrField<Element>::at(int index)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return RepeatedPtrFieldBase::at<TypeHandler>(index);
}
template <typename Element>
inline Element* RepeatedPtrField<Element>::Mutable(int index) {
inline Element* RepeatedPtrField<Element>::Mutable(int index)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
}
template <typename Element>
PROTOBUF_NOINLINE Element* RepeatedPtrField<Element>::Add() {
PROTOBUF_NOINLINE Element* RepeatedPtrField<Element>::Add()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return RepeatedPtrFieldBase::Add<TypeHandler>();
}
@ -1509,13 +1526,15 @@ inline void RepeatedPtrField<Element>::Assign(Iter begin, Iter end) {
template <typename Element>
inline typename RepeatedPtrField<Element>::iterator
RepeatedPtrField<Element>::erase(const_iterator position) {
RepeatedPtrField<Element>::erase(const_iterator position)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return erase(position, position + 1);
}
template <typename Element>
inline typename RepeatedPtrField<Element>::iterator
RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) {
RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
size_type pos_offset = static_cast<size_type>(std::distance(cbegin(), first));
size_type last_offset = static_cast<size_type>(std::distance(cbegin(), last));
DeleteSubrange(pos_offset, last_offset - pos_offset);
@ -1523,12 +1542,14 @@ RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) {
}
template <typename Element>
inline Element** RepeatedPtrField<Element>::mutable_data() {
inline Element** RepeatedPtrField<Element>::mutable_data()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
}
template <typename Element>
inline const Element* const* RepeatedPtrField<Element>::data() const {
inline const Element* const* RepeatedPtrField<Element>::data() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return RepeatedPtrFieldBase::data<TypeHandler>();
}
@ -1843,53 +1864,53 @@ class RepeatedPtrOverPtrsIterator {
template <typename Element>
inline typename RepeatedPtrField<Element>::iterator
RepeatedPtrField<Element>::begin() {
RepeatedPtrField<Element>::begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(raw_data());
}
template <typename Element>
inline typename RepeatedPtrField<Element>::const_iterator
RepeatedPtrField<Element>::begin() const {
RepeatedPtrField<Element>::begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(raw_data());
}
template <typename Element>
inline typename RepeatedPtrField<Element>::const_iterator
RepeatedPtrField<Element>::cbegin() const {
RepeatedPtrField<Element>::cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return begin();
}
template <typename Element>
inline typename RepeatedPtrField<Element>::iterator
RepeatedPtrField<Element>::end() {
RepeatedPtrField<Element>::end() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(raw_data() + size());
}
template <typename Element>
inline typename RepeatedPtrField<Element>::const_iterator
RepeatedPtrField<Element>::end() const {
RepeatedPtrField<Element>::end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return iterator(raw_data() + size());
}
template <typename Element>
inline typename RepeatedPtrField<Element>::const_iterator
RepeatedPtrField<Element>::cend() const {
RepeatedPtrField<Element>::cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return end();
}
template <typename Element>
inline typename RepeatedPtrField<Element>::pointer_iterator
RepeatedPtrField<Element>::pointer_begin() {
RepeatedPtrField<Element>::pointer_begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return pointer_iterator(raw_mutable_data());
}
template <typename Element>
inline typename RepeatedPtrField<Element>::const_pointer_iterator
RepeatedPtrField<Element>::pointer_begin() const {
RepeatedPtrField<Element>::pointer_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_pointer_iterator(const_cast<const void* const*>(raw_data()));
}
template <typename Element>
inline typename RepeatedPtrField<Element>::pointer_iterator
RepeatedPtrField<Element>::pointer_end() {
RepeatedPtrField<Element>::pointer_end() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return pointer_iterator(raw_mutable_data() + size());
}
template <typename Element>
inline typename RepeatedPtrField<Element>::const_pointer_iterator
RepeatedPtrField<Element>::pointer_end() const {
RepeatedPtrField<Element>::pointer_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_pointer_iterator(
const_cast<const void* const*>(raw_data() + size()));
}

Loading…
Cancel
Save