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

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

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

Loading…
Cancel
Save