From 7b7ba2df67199a2c95b21ce6eec9e6d62b71cc60 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Mon, 15 May 2023 15:28:47 -0700 Subject: [PATCH] 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 --- src/google/protobuf/map.h | 54 +++++++---- src/google/protobuf/repeated_field.h | 111 ++++++++++++--------- src/google/protobuf/repeated_ptr_field.h | 117 +++++++++++++---------- 3 files changed, 168 insertions(+), 114 deletions(-) diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 4c61d3eea8..7b8d08ec45 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.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> { } } - 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> { 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 - T& operator[](const key_arg& key) { + T& operator[](const key_arg& 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::value>::type> - T& operator[](key_arg&& key) { + T& operator[](key_arg&& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { return try_emplace(std::forward(key)).first->second; } template - const T& at(const key_arg& key) const { + const T& at(const key_arg& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND { const_iterator it = find(key); ABSL_CHECK(it != end()) << "key not found: " << static_cast(key); return it->second; } template - T& at(const key_arg& key) { + T& at(const key_arg& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { iterator it = find(key); ABSL_CHECK(it != end()) << "key not found: " << static_cast(key); return it->second; @@ -1344,11 +1351,12 @@ class Map : private internal::KeyMapBase> { } template - const_iterator find(const key_arg& key) const { + const_iterator find(const key_arg& key) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_cast(this)->find(key); } template - iterator find(const key_arg& key) { + iterator find(const key_arg& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { auto res = this->FindHelper(key); return iterator(static_cast(res.node), this, res.bucket); } @@ -1360,7 +1368,7 @@ class Map : private internal::KeyMapBase> { template std::pair equal_range( - const key_arg& key) const { + const key_arg& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND { const_iterator it = find(key); if (it == end()) { return std::pair(it, it); @@ -1371,7 +1379,8 @@ class Map : private internal::KeyMapBase> { } template - std::pair equal_range(const key_arg& key) { + std::pair equal_range(const key_arg& key) + ABSL_ATTRIBUTE_LIFETIME_BOUND { iterator it = find(key); if (it == end()) { return std::pair(it, it); @@ -1383,7 +1392,8 @@ class Map : private internal::KeyMapBase> { // insert template - std::pair try_emplace(K&& k, Args&&... args) { + std::pair 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> { std::forward(k), std::forward(args)...); } - std::pair insert(init_type&& value) { + std::pair insert(init_type&& value) + ABSL_ATTRIBUTE_LIFETIME_BOUND { return try_emplace(std::move(value.first), std::move(value.second)); } template = 0> - std::pair insert(P&& value) { + std::pair insert(P&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND { return try_emplace(std::forward

(value).first, std::forward

(value).second); } template - std::pair emplace(Args&&... args) { + std::pair emplace(Args&&... args) + ABSL_ATTRIBUTE_LIFETIME_BOUND { return EmplaceInternal(Rank0{}, std::forward(args)...); } template @@ -1435,7 +1447,7 @@ class Map : private internal::KeyMapBase> { } } - iterator erase(iterator pos) { + iterator erase(iterator pos) ABSL_ATTRIBUTE_LIFETIME_BOUND { auto next = std::next(pos); ABSL_DCHECK_EQ(pos.m_, static_cast(this)); auto* node = static_cast(pos.node_); @@ -1475,7 +1487,7 @@ class Map : private internal::KeyMapBase> { } // Assign - Map& operator=(const Map& other) { + Map& operator=(const Map& other) ABSL_ATTRIBUTE_LIFETIME_BOUND { if (this != &other) { clear(); insert(other.begin(), other.end()); diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 85ed0b2691..2da745dc0f 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -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 @@ -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_reverse_iterator; typedef std::reverse_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::~RepeatedField() { template inline RepeatedField& RepeatedField::operator=( - const RepeatedField& other) { + const RepeatedField& other) ABSL_ATTRIBUTE_LIFETIME_BOUND { if (this != &other) CopyFrom(other); return *this; } @@ -561,7 +573,7 @@ inline RepeatedField::RepeatedField(RepeatedField&& other) noexcept template inline RepeatedField& RepeatedField::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::AddAlreadyReserved(Element value) { } template -inline Element* RepeatedField::AddAlreadyReserved() { +inline Element* RepeatedField::AddAlreadyReserved() + ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_DCHECK_LT(current_size_, total_size_); // new (p) 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::AddAlreadyReserved() { } template -inline Element* RepeatedField::AddNAlreadyReserved(int n) { +inline Element* RepeatedField::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::Resize(int new_size, const Element& value) { } template -inline const Element& RepeatedField::Get(int index) const { +inline const Element& RepeatedField::Get(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_DCHECK_GE(index, 0); ABSL_DCHECK_LT(index, current_size_); return elements()[index]; } template -inline const Element& RepeatedField::at(int index) const { +inline const Element& RepeatedField::at(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_CHECK_GE(index, 0); ABSL_CHECK_LT(index, current_size_); return elements()[index]; } template -inline Element& RepeatedField::at(int index) { +inline Element& RepeatedField::at(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_CHECK_GE(index, 0); ABSL_CHECK_LT(index, current_size_); return elements()[index]; } template -inline Element* RepeatedField::Mutable(int index) { +inline Element* RepeatedField::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::Add(Element value) { } template -inline Element* RepeatedField::Add() { +inline Element* RepeatedField::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::Assign(Iter begin, Iter end) { template inline typename RepeatedField::iterator RepeatedField::erase( - const_iterator position) { + const_iterator position) ABSL_ATTRIBUTE_LIFETIME_BOUND { return erase(position, position + 1); } template inline typename RepeatedField::iterator RepeatedField::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::iterator RepeatedField::erase( } template -inline Element* RepeatedField::mutable_data() { +inline Element* RepeatedField::mutable_data() + ABSL_ATTRIBUTE_LIFETIME_BOUND { return unsafe_elements(); } template -inline const Element* RepeatedField::data() const { +inline const Element* RepeatedField::data() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { return unsafe_elements(); } @@ -879,32 +899,33 @@ void RepeatedField::SwapElements(int index1, int index2) { } template -inline typename RepeatedField::iterator -RepeatedField::begin() { +inline typename RepeatedField::iterator RepeatedField::begin() + ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(unsafe_elements()); } template inline typename RepeatedField::const_iterator -RepeatedField::begin() const { +RepeatedField::begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_iterator(unsafe_elements()); } template inline typename RepeatedField::const_iterator -RepeatedField::cbegin() const { +RepeatedField::cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_iterator(unsafe_elements()); } template -inline typename RepeatedField::iterator RepeatedField::end() { +inline typename RepeatedField::iterator RepeatedField::end() + ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(unsafe_elements() + current_size_); } template inline typename RepeatedField::const_iterator -RepeatedField::end() const { +RepeatedField::end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_iterator(unsafe_elements() + current_size_); } template inline typename RepeatedField::const_iterator -RepeatedField::cend() const { +RepeatedField::cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_iterator(unsafe_elements() + current_size_); } diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h index 20f29ca824..06b3f7baac 100644 --- a/src/google/protobuf/repeated_ptr_field.h +++ b/src/google/protobuf/repeated_ptr_field.h @@ -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 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_reverse_iterator; typedef std::reverse_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_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::~RepeatedPtrField() { template inline RepeatedPtrField& RepeatedPtrField::operator=( - const RepeatedPtrField& other) { + const RepeatedPtrField& other) ABSL_ATTRIBUTE_LIFETIME_BOUND { if (this != &other) CopyFrom(other); return *this; } @@ -1307,7 +1319,7 @@ inline RepeatedPtrField::RepeatedPtrField( template inline RepeatedPtrField& RepeatedPtrField::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::size() const { } template -inline const Element& RepeatedPtrField::Get(int index) const { +inline const Element& RepeatedPtrField::Get(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { return RepeatedPtrFieldBase::Get(index); } template -inline const Element& RepeatedPtrField::at(int index) const { +inline const Element& RepeatedPtrField::at(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { return RepeatedPtrFieldBase::at(index); } template -inline Element& RepeatedPtrField::at(int index) { +inline Element& RepeatedPtrField::at(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { return RepeatedPtrFieldBase::at(index); } template -inline Element* RepeatedPtrField::Mutable(int index) { +inline Element* RepeatedPtrField::Mutable(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { return RepeatedPtrFieldBase::Mutable(index); } template -PROTOBUF_NOINLINE Element* RepeatedPtrField::Add() { +PROTOBUF_NOINLINE Element* RepeatedPtrField::Add() + ABSL_ATTRIBUTE_LIFETIME_BOUND { return RepeatedPtrFieldBase::Add(); } @@ -1509,13 +1526,15 @@ inline void RepeatedPtrField::Assign(Iter begin, Iter end) { template inline typename RepeatedPtrField::iterator -RepeatedPtrField::erase(const_iterator position) { +RepeatedPtrField::erase(const_iterator position) + ABSL_ATTRIBUTE_LIFETIME_BOUND { return erase(position, position + 1); } template inline typename RepeatedPtrField::iterator -RepeatedPtrField::erase(const_iterator first, const_iterator last) { +RepeatedPtrField::erase(const_iterator first, const_iterator last) + ABSL_ATTRIBUTE_LIFETIME_BOUND { size_type pos_offset = static_cast(std::distance(cbegin(), first)); size_type last_offset = static_cast(std::distance(cbegin(), last)); DeleteSubrange(pos_offset, last_offset - pos_offset); @@ -1523,12 +1542,14 @@ RepeatedPtrField::erase(const_iterator first, const_iterator last) { } template -inline Element** RepeatedPtrField::mutable_data() { +inline Element** RepeatedPtrField::mutable_data() + ABSL_ATTRIBUTE_LIFETIME_BOUND { return RepeatedPtrFieldBase::mutable_data(); } template -inline const Element* const* RepeatedPtrField::data() const { +inline const Element* const* RepeatedPtrField::data() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { return RepeatedPtrFieldBase::data(); } @@ -1843,53 +1864,53 @@ class RepeatedPtrOverPtrsIterator { template inline typename RepeatedPtrField::iterator -RepeatedPtrField::begin() { +RepeatedPtrField::begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(raw_data()); } template inline typename RepeatedPtrField::const_iterator -RepeatedPtrField::begin() const { +RepeatedPtrField::begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(raw_data()); } template inline typename RepeatedPtrField::const_iterator -RepeatedPtrField::cbegin() const { +RepeatedPtrField::cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return begin(); } template inline typename RepeatedPtrField::iterator -RepeatedPtrField::end() { +RepeatedPtrField::end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(raw_data() + size()); } template inline typename RepeatedPtrField::const_iterator -RepeatedPtrField::end() const { +RepeatedPtrField::end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(raw_data() + size()); } template inline typename RepeatedPtrField::const_iterator -RepeatedPtrField::cend() const { +RepeatedPtrField::cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); } template inline typename RepeatedPtrField::pointer_iterator -RepeatedPtrField::pointer_begin() { +RepeatedPtrField::pointer_begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return pointer_iterator(raw_mutable_data()); } template inline typename RepeatedPtrField::const_pointer_iterator -RepeatedPtrField::pointer_begin() const { +RepeatedPtrField::pointer_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_pointer_iterator(const_cast(raw_data())); } template inline typename RepeatedPtrField::pointer_iterator -RepeatedPtrField::pointer_end() { +RepeatedPtrField::pointer_end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return pointer_iterator(raw_mutable_data() + size()); } template inline typename RepeatedPtrField::const_pointer_iterator -RepeatedPtrField::pointer_end() const { +RepeatedPtrField::pointer_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_pointer_iterator( const_cast(raw_data() + size())); }