diff options
Diffstat (limited to 'absl')
-rw-r--r-- | absl/base/optimization.h | 5 | ||||
-rw-r--r-- | absl/container/internal/btree.h | 8 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set.h | 57 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set_test.cc | 39 | ||||
-rw-r--r-- | absl/debugging/internal/demangle.cc | 28 | ||||
-rw-r--r-- | absl/debugging/internal/demangle_test.cc | 30 | ||||
-rw-r--r-- | absl/debugging/leak_check.cc | 1 | ||||
-rw-r--r-- | absl/debugging/leak_check.h | 13 | ||||
-rw-r--r-- | absl/status/internal/status_internal.h | 11 | ||||
-rw-r--r-- | absl/status/status.h | 9 | ||||
-rw-r--r-- | absl/status/status_test.cc | 4 | ||||
-rw-r--r-- | absl/status/statusor.h | 2 | ||||
-rw-r--r-- | absl/strings/numbers.h | 1 |
13 files changed, 146 insertions, 62 deletions
diff --git a/absl/base/optimization.h b/absl/base/optimization.h index 6332b625..d090be12 100644 --- a/absl/base/optimization.h +++ b/absl/base/optimization.h @@ -106,9 +106,10 @@ // Cacheline aligning objects properly allows constructive memory sharing and // prevents destructive (or "false") memory sharing. // -// NOTE: this macro should be replaced with usage of `alignas()` using +// NOTE: callers should replace uses of this macro with `alignas()` using // `std::hardware_constructive_interference_size` and/or -// `std::hardware_destructive_interference_size` when available within C++17. +// `std::hardware_destructive_interference_size` when C++17 becomes available to +// them. // // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html // for more information. diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index 00444a53..0bb38366 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h @@ -579,10 +579,10 @@ class btree_node { }; // Leaves can have less than kNodeSlots values. - constexpr static layout_type LeafLayout(const int slots = kNodeSlots) { + constexpr static layout_type LeafLayout(const int slot_count = kNodeSlots) { return layout_type(/*parent*/ 1, /*position, start, finish, max_count*/ 4, - /*slots*/ slots, + /*slots*/ slot_count, /*children*/ 0); } constexpr static layout_type InternalLayout() { @@ -591,8 +591,8 @@ class btree_node { /*slots*/ kNodeSlots, /*children*/ kNodeSlots + 1); } - constexpr static size_type LeafSize(const int slots = kNodeSlots) { - return LeafLayout(slots).AllocSize(); + constexpr static size_type LeafSize(const int slot_count = kNodeSlots) { + return LeafLayout(slot_count).AllocSize(); } constexpr static size_type InternalSize() { return InternalLayout().AllocSize(); diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 80fc2cba..8615de8b 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -792,7 +792,8 @@ class raw_hash_set { explicit raw_hash_set(size_t bucket_count, const hasher& hash = hasher(), const key_equal& eq = key_equal(), const allocator_type& alloc = allocator_type()) - : ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) { + : ctrl_(EmptyGroup()), + settings_(0, HashtablezInfoHandle(), hash, eq, alloc) { if (bucket_count) { capacity_ = NormalizeCapacity(bucket_count); initialize_slots(); @@ -903,7 +904,7 @@ class raw_hash_set { auto target = find_first_non_full(ctrl_, hash, capacity_); set_ctrl(target.offset, H2(hash)); emplace_at(target.offset, v); - infoz_.RecordInsert(hash, target.probe_length); + infoz().RecordInsert(hash, target.probe_length); } size_ = that.size(); growth_left() -= that.size(); @@ -917,28 +918,27 @@ class raw_hash_set { slots_(absl::exchange(that.slots_, nullptr)), size_(absl::exchange(that.size_, 0)), capacity_(absl::exchange(that.capacity_, 0)), - infoz_(absl::exchange(that.infoz_, HashtablezInfoHandle())), // Hash, equality and allocator are copied instead of moved because // `that` must be left valid. If Hash is std::function<Key>, moving it // would create a nullptr functor that cannot be called. - settings_(that.settings_) { - // growth_left was copied above, reset the one from `that`. - that.growth_left() = 0; - } + settings_(absl::exchange(that.growth_left(), 0), + absl::exchange(that.infoz(), HashtablezInfoHandle()), + that.hash_ref(), that.eq_ref(), that.alloc_ref()) {} raw_hash_set(raw_hash_set&& that, const allocator_type& a) : ctrl_(EmptyGroup()), slots_(nullptr), size_(0), capacity_(0), - settings_(0, that.hash_ref(), that.eq_ref(), a) { + settings_(0, HashtablezInfoHandle(), that.hash_ref(), that.eq_ref(), + a) { if (a == that.alloc_ref()) { std::swap(ctrl_, that.ctrl_); std::swap(slots_, that.slots_); std::swap(size_, that.size_); std::swap(capacity_, that.capacity_); std::swap(growth_left(), that.growth_left()); - std::swap(infoz_, that.infoz_); + std::swap(infoz(), that.infoz()); } else { reserve(that.size()); // Note: this will copy elements of dense_set and unordered_set instead of @@ -1009,7 +1009,7 @@ class raw_hash_set { reset_growth_left(); } assert(empty()); - infoz_.RecordStorageChanged(0, capacity_); + infoz().RecordStorageChanged(0, capacity_); } // This overload kicks in when the argument is an rvalue of insertable and @@ -1301,7 +1301,7 @@ class raw_hash_set { swap(growth_left(), that.growth_left()); swap(hash_ref(), that.hash_ref()); swap(eq_ref(), that.eq_ref()); - swap(infoz_, that.infoz_); + swap(infoz(), that.infoz()); SwapAlloc(alloc_ref(), that.alloc_ref(), typename AllocTraits::propagate_on_container_swap{}); } @@ -1310,7 +1310,7 @@ class raw_hash_set { if (n == 0 && capacity_ == 0) return; if (n == 0 && size_ == 0) { destroy_slots(); - infoz_.RecordStorageChanged(0, 0); + infoz().RecordStorageChanged(0, 0); return; } // bitor is a faster way of doing `max` here. We will round up to the next @@ -1528,7 +1528,7 @@ class raw_hash_set { set_ctrl(index, was_never_full ? kEmpty : kDeleted); growth_left() += was_never_full; - infoz_.RecordErase(); + infoz().RecordErase(); } void initialize_slots() { @@ -1545,7 +1545,7 @@ class raw_hash_set { // bound more carefully. if (std::is_same<SlotAlloc, std::allocator<slot_type>>::value && slots_ == nullptr) { - infoz_ = Sample(); + infoz() = Sample(); } auto layout = MakeLayout(capacity_); @@ -1555,7 +1555,7 @@ class raw_hash_set { slots_ = layout.template Pointer<1>(mem); reset_ctrl(); reset_growth_left(); - infoz_.RecordStorageChanged(size_, capacity_); + infoz().RecordStorageChanged(size_, capacity_); } void destroy_slots() { @@ -1603,7 +1603,7 @@ class raw_hash_set { Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl, layout.AllocSize()); } - infoz_.RecordRehash(total_probe_length); + infoz().RecordRehash(total_probe_length); } void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE { @@ -1669,7 +1669,7 @@ class raw_hash_set { } } reset_growth_left(); - infoz_.RecordRehash(total_probe_length); + infoz().RecordRehash(total_probe_length); } void rehash_and_grow_if_necessary() { @@ -1743,7 +1743,7 @@ class raw_hash_set { ++size_; growth_left() -= IsEmpty(ctrl_[target.offset]); set_ctrl(target.offset, H2(hash)); - infoz_.RecordInsert(hash, target.probe_length); + infoz().RecordInsert(hash, target.probe_length); return target.offset; } @@ -1800,13 +1800,15 @@ class raw_hash_set { size_t& growth_left() { return settings_.template get<0>(); } - hasher& hash_ref() { return settings_.template get<1>(); } - const hasher& hash_ref() const { return settings_.template get<1>(); } - key_equal& eq_ref() { return settings_.template get<2>(); } - const key_equal& eq_ref() const { return settings_.template get<2>(); } - allocator_type& alloc_ref() { return settings_.template get<3>(); } + HashtablezInfoHandle& infoz() { return settings_.template get<1>(); } + + hasher& hash_ref() { return settings_.template get<2>(); } + const hasher& hash_ref() const { return settings_.template get<2>(); } + key_equal& eq_ref() { return settings_.template get<3>(); } + const key_equal& eq_ref() const { return settings_.template get<3>(); } + allocator_type& alloc_ref() { return settings_.template get<4>(); } const allocator_type& alloc_ref() const { - return settings_.template get<3>(); + return settings_.template get<4>(); } // TODO(alkis): Investigate removing some of these fields: @@ -1816,10 +1818,11 @@ class raw_hash_set { slot_type* slots_ = nullptr; // [capacity * slot_type] size_t size_ = 0; // number of full slots size_t capacity_ = 0; // total number of slots - HashtablezInfoHandle infoz_; - absl::container_internal::CompressedTuple<size_t /* growth_left */, hasher, + absl::container_internal::CompressedTuple<size_t /* growth_left */, + HashtablezInfoHandle, hasher, key_equal, allocator_type> - settings_{0, hasher{}, key_equal{}, allocator_type{}}; + settings_{0, HashtablezInfoHandle{}, hasher{}, key_equal{}, + allocator_type{}}; }; // Erases all elements that satisfy the predicate `pred` from the container `c`. diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 81c4b47c..7dac65a0 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -419,6 +419,13 @@ TEST(Table, EmptyFunctorOptimization) { size_t growth_left; void* infoz; }; + struct MockTableInfozDisabled { + void* ctrl; + void* slots; + size_t size; + size_t capacity; + size_t growth_left; + }; struct StatelessHash { size_t operator()(absl::string_view) const { return 0; } }; @@ -426,17 +433,27 @@ TEST(Table, EmptyFunctorOptimization) { size_t dummy; }; - EXPECT_EQ( - sizeof(MockTable), - sizeof( - raw_hash_set<StringPolicy, StatelessHash, - std::equal_to<absl::string_view>, std::allocator<int>>)); - - EXPECT_EQ( - sizeof(MockTable) + sizeof(StatefulHash), - sizeof( - raw_hash_set<StringPolicy, StatefulHash, - std::equal_to<absl::string_view>, std::allocator<int>>)); + if (std::is_empty<HashtablezInfoHandle>::value) { + EXPECT_EQ(sizeof(MockTableInfozDisabled), + sizeof(raw_hash_set<StringPolicy, StatelessHash, + std::equal_to<absl::string_view>, + std::allocator<int>>)); + + EXPECT_EQ(sizeof(MockTableInfozDisabled) + sizeof(StatefulHash), + sizeof(raw_hash_set<StringPolicy, StatefulHash, + std::equal_to<absl::string_view>, + std::allocator<int>>)); + } else { + EXPECT_EQ(sizeof(MockTable), + sizeof(raw_hash_set<StringPolicy, StatelessHash, + std::equal_to<absl::string_view>, + std::allocator<int>>)); + + EXPECT_EQ(sizeof(MockTable) + sizeof(StatefulHash), + sizeof(raw_hash_set<StringPolicy, StatefulHash, + std::equal_to<absl::string_view>, + std::allocator<int>>)); + } } TEST(Table, Empty) { diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 46cdb67b..5cd56320 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -386,24 +386,28 @@ static bool IsDigit(char c) { return c >= '0' && c <= '9'; } // by GCC 4.5.x and later versions (and our locally-modified version of GCC // 4.4.x) to indicate functions which have been cloned during optimization. // We treat any sequence (.<alpha>+.<digit>+)+ as a function clone suffix. +// Additionally, '_' is allowed along with the alphanumeric sequence. static bool IsFunctionCloneSuffix(const char *str) { size_t i = 0; while (str[i] != '\0') { - // Consume a single .<alpha>+.<digit>+ sequence. - if (str[i] != '.' || !IsAlpha(str[i + 1])) { - return false; + bool parsed = false; + // Consume a single [.<alpha> | _]*[.<digit>]* sequence. + if (str[i] == '.' && (IsAlpha(str[i + 1]) || str[i + 1] == '_')) { + parsed = true; + i += 2; + while (IsAlpha(str[i]) || str[i] == '_') { + ++i; + } } - i += 2; - while (IsAlpha(str[i])) { - ++i; + if (str[i] == '.' && IsDigit(str[i + 1])) { + parsed = true; + i += 2; + while (IsDigit(str[i])) { + ++i; + } } - if (str[i] != '.' || !IsDigit(str[i + 1])) { + if (!parsed) return false; - } - i += 2; - while (IsDigit(str[i])) { - ++i; - } } return true; // Consumed everything in "str". } diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 0bed7359..6b142902 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -70,12 +70,34 @@ TEST(Demangle, Clones) { EXPECT_STREQ("Foo()", tmp); EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp))); EXPECT_STREQ("Foo()", tmp); - // Invalid (truncated), should not demangle. - EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp))); + // Demangle suffixes produced by -funique-internal-linkage-names. + EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345.isra.2.constprop.18", tmp, + sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + // Suffixes without the number should also demangle. + EXPECT_TRUE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + // Suffixes with just the number should also demangle. + EXPECT_TRUE(Demangle("_ZL3Foov.123", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + // (.clone. followed by non-number), should also demangle. + EXPECT_TRUE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + // (.clone. followed by multiple numbers), should also demangle. + EXPECT_TRUE(Demangle("_ZL3Foov.clone.123.456", tmp, sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + // (a long valid suffix), should demangle. + EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp, + sizeof(tmp))); + EXPECT_STREQ("Foo()", tmp); + // Invalid (. without anything else), should not demangle. + EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp))); + // Invalid (. with mix of alpha and digits), should not demangle. + EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp))); // Invalid (.clone. not followed by number), should not demangle. EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp))); - // Invalid (.clone. followed by non-number), should not demangle. - EXPECT_FALSE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp))); // Invalid (.constprop. not followed by number), should not demangle. EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp))); } diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc index ff904955..db9d5d09 100644 --- a/absl/debugging/leak_check.cc +++ b/absl/debugging/leak_check.cc @@ -38,6 +38,7 @@ ABSL_NAMESPACE_END namespace absl { ABSL_NAMESPACE_BEGIN bool HaveLeakSanitizer() { return true; } +bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check(); } void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); } void RegisterLivePointers(const void* ptr, size_t size) { __lsan_register_root_region(ptr, size); diff --git a/absl/debugging/leak_check.h b/absl/debugging/leak_check.h index b66a81c3..61c3216f 100644 --- a/absl/debugging/leak_check.h +++ b/absl/debugging/leak_check.h @@ -71,6 +71,19 @@ T* IgnoreLeak(T* ptr) { return ptr; } +// FindAndReportLeaks() +// +// If any leaks are detected, prints a leak report and returns true. This +// function may be called repeatedly, and does not affect end-of-process leak +// checking. +// +// Example: +// if (FindAndReportLeaks()) { +// ... diagnostic already printed. Exit with failure code. +// exit(1) +// } +bool FindAndReportLeaks(); + // LeakCheckDisabler // // This helper class indicates that any heap allocations done in the code block diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h index 279f8f55..99a2d964 100644 --- a/absl/status/internal/status_internal.h +++ b/absl/status/internal/status_internal.h @@ -19,6 +19,17 @@ #include "absl/container/inlined_vector.h" #include "absl/strings/cord.h" +#ifndef SWIG +// Disabled for SWIG as it doesn't parse attributes correctly. +namespace absl { +ABSL_NAMESPACE_BEGIN +// Returned Status objects may not be ignored. Codesearch doesn't handle ifdefs +// as part of a class definitions (b/6995610), so we use a forward declaration. +class ABSL_MUST_USE_RESULT Status; +ABSL_NAMESPACE_END +} // namespace absl +#endif // !SWIG + namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/absl/status/status.h b/absl/status/status.h index df9e330c..61486fee 100644 --- a/absl/status/status.h +++ b/absl/status/status.h @@ -291,6 +291,8 @@ enum class StatusToStringMode : int { kWithNoExtraData = 0, // ToString will contain the payloads. kWithPayload = 1 << 0, + // ToString will include all the extra data this Status has. + kWithEverything = ~kWithNoExtraData, }; // absl::StatusToStringMode is specified as a bitmask type, which means the @@ -410,7 +412,12 @@ inline StatusToStringMode& operator^=(StatusToStringMode& lhs, // return result; // } // -class ABSL_MUST_USE_RESULT Status final { +// For documentation see https://abseil.io/docs/cpp/guides/status. +// +// Returned Status objects may not be ignored. status_internal.h has a forward +// declaration of the form +// class ABSL_MUST_USE_RESULT Status; +class Status final { public: // Constructors diff --git a/absl/status/status_test.cc b/absl/status/status_test.cc index 7116ba67..0e1a43ce 100644 --- a/absl/status/status_test.cc +++ b/absl/status/status_test.cc @@ -292,6 +292,10 @@ TEST(Status, ToStringMode) { AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), HasSubstr("[bar='\\xff']"))); + EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything), + AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"), + HasSubstr("[bar='\\xff']"))); + EXPECT_THAT(s.ToString(~absl::StatusToStringMode::kWithPayload), AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")), Not(HasSubstr("[bar='\\xff']")))); diff --git a/absl/status/statusor.h b/absl/status/statusor.h index 469d486f..b7c55cc8 100644 --- a/absl/status/statusor.h +++ b/absl/status/statusor.h @@ -135,7 +135,7 @@ class ABSL_MUST_USE_RESULT StatusOr; // // NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will // throw an exception if exceptions are enabled or terminate the process when -// execeptions are not enabled. +// exceptions are not enabled. // // Example: // diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h index ffc738fa..1780bb44 100644 --- a/absl/strings/numbers.h +++ b/absl/strings/numbers.h @@ -124,6 +124,7 @@ inline void PutTwoDigits(size_t i, char* buf) { } // safe_strto?() functions for implementing SimpleAtoi() + bool safe_strto32_base(absl::string_view text, int32_t* value, int base); bool safe_strto64_base(absl::string_view text, int64_t* value, int base); bool safe_strto128_base(absl::string_view text, absl::int128* value, |