- static absl::Nonnull Launder(absl::Nonnull
p) {
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
- return std::launder(p);
-#elif ABSL_HAVE_BUILTIN(__builtin_launder)
- return __builtin_launder(p);
-#else
- // When `std::launder` or equivalent are not available, we rely on
- // undefined behavior, which works as intended on Abseil's officially
- // supported platforms as of Q3 2023.
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
- return p;
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-#endif
+ T* absl_nonnull get() {
+ return std::launder(reinterpret_cast(&space_));
}
+ private:
alignas(T) unsigned char space_[sizeof(T)];
};
@@ -199,12 +180,10 @@ class NoDestructor {
impl_;
};
-#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
// Provide 'Class Template Argument Deduction': the type of NoDestructor's T
// will be the same type as the argument passed to NoDestructor's constructor.
template
NoDestructor(T) -> NoDestructor;
-#endif // ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/base/nullability.h b/absl/base/nullability.h
index 241c65a..3a5d6e8 100644
--- a/absl/base/nullability.h
+++ b/absl/base/nullability.h
@@ -16,21 +16,21 @@
// File: nullability.h
// -----------------------------------------------------------------------------
//
-// This header file defines a set of "templated annotations" for designating the
-// expected nullability of pointers. These annotations allow you to designate
-// pointers in one of three classification states:
+// This header file defines a set of annotations for designating the expected
+// nullability of pointers. These annotations allow you to designate pointers in
+// one of three classification states:
//
-// * "Non-null" (for pointers annotated `Nonnull`), indicating that it is
+// * "Non-null" (for pointers annotated `absl_nonnull`), indicating that it is
// invalid for the given pointer to ever be null.
-// * "Nullable" (for pointers annotated `Nullable`), indicating that it is
+// * "Nullable" (for pointers annotated `absl_nullable`), indicating that it is
// valid for the given pointer to be null.
-// * "Unknown" (for pointers annotated `NullabilityUnknown`), indicating
-// that the given pointer has not been yet classified as either nullable or
+// * "Unknown" (for pointers annotated `absl_nullability_unknown`), indicating
+// that the given pointer has not yet been classified as either nullable or
// non-null. This is the default state of unannotated pointers.
//
-// NOTE: unannotated pointers implicitly bear the annotation
-// `NullabilityUnknown`; you should rarely, if ever, see this annotation used
-// in the codebase explicitly.
+// NOTE: Unannotated pointers implicitly bear the annotation
+// `absl_nullability_unknown`; you should rarely, if ever, see this annotation
+// used in the codebase explicitly.
//
// -----------------------------------------------------------------------------
// Nullability and Contracts
@@ -64,16 +64,49 @@
// formalize those contracts within the codebase.
//
// -----------------------------------------------------------------------------
+// Annotation Syntax
+// -----------------------------------------------------------------------------
+//
+// The annotations should be positioned as a qualifier for the pointer type. For
+// example, the position of `const` when declaring a const pointer (not a
+// pointer to a const type) is the position you should also use for these
+// annotations.
+//
+// Example:
+//
+// // A const non-null pointer to an `Employee`.
+// Employee* absl_nonnull const e;
+//
+// // A non-null pointer to a const `Employee`.
+// const Employee* absl_nonnull e;
+//
+// // A non-null pointer to a const nullable pointer to an `Employee`.
+// Employee* absl_nullable const* absl_nonnull e = nullptr;
+//
+// // A non-null function pointer.
+// void (*absl_nonnull func)(int, double);
+//
+// // A non-null array of `Employee`s as a parameter.
+// void func(Employee employees[absl_nonnull]);
+//
+// // A non-null std::unique_ptr to an `Employee`.
+// // As with `const`, it is possible to place the annotation on either side of
+// // a named type not ending in `*`, but placing it before the type it
+// // describes is preferred, unless inconsistent with surrounding code.
+// absl_nonnull std::unique_ptr employee;
+//
+// // Invalid annotation usage – this attempts to declare a pointer to a
+// // nullable `Employee`, which is meaningless.
+// absl_nullable Employee* e;
+//
+// -----------------------------------------------------------------------------
// Using Nullability Annotations
// -----------------------------------------------------------------------------
//
-// It is important to note that these annotations are not distinct strong
-// *types*. They are alias templates defined to be equal to the underlying
-// pointer type. A pointer annotated `Nonnull`, for example, is simply a
-// pointer of type `T*`. Each annotation acts as a form of documentation about
-// the contract for the given pointer. Each annotation requires providers or
-// consumers of these pointers across API boundaries to take appropriate steps
-// when setting or using these pointers:
+// Each annotation acts as a form of documentation about the contract for the
+// given pointer. Each annotation requires providers or consumers of these
+// pointers across API boundaries to take appropriate steps when setting or
+// using these pointers:
//
// * "Non-null" pointers should never be null. It is the responsibility of the
// provider of this pointer to ensure that the pointer may never be set to
@@ -91,20 +124,20 @@
// Example:
//
// // PaySalary() requires the passed pointer to an `Employee` to be non-null.
-// void PaySalary(absl::Nonnull e) {
+// void PaySalary(Employee* absl_nonnull e) {
// pay(e->salary); // OK to dereference
// }
//
// // CompleteTransaction() guarantees the returned pointer to an `Account` to
// // be non-null.
-// absl::Nonnull balance CompleteTransaction(double fee) {
+// Account* absl_nonnull balance CompleteTransaction(double fee) {
// ...
// }
//
// // Note that specifying a nullability annotation does not prevent someone
// // from violating the contract:
//
-// Nullable find(Map& employees, std::string_view name);
+// Employee* absl_nullable find(Map& employees, std::string_view name);
//
// void g(Map& employees) {
// Employee *e = find(employees, "Pat");
@@ -144,14 +177,14 @@
// These nullability annotations are primarily a human readable signal about the
// intended contract of the pointer. They are not *types* and do not currently
// provide any correctness guarantees. For example, a pointer annotated as
-// `Nonnull` is *not guaranteed* to be non-null, and the compiler won't
-// alert or prevent assignment of a `Nullable` to a `Nonnull`.
+// `absl_nonnull` is *not guaranteed* to be non-null, and the compiler won't
+// alert or prevent assignment of a `T* absl_nullable` to a `T* absl_nonnull`.
// ===========================================================================
#ifndef ABSL_BASE_NULLABILITY_H_
#define ABSL_BASE_NULLABILITY_H_
#include "absl/base/config.h"
-#include "absl/base/internal/nullability_impl.h"
+#include "absl/base/internal/nullability_deprecated.h"
// ABSL_POINTERS_DEFAULT_NONNULL
//
@@ -168,14 +201,14 @@
// ABSL_POINTERS_DEFAULT_NONNULL
//
// void FillMessage(Message *m); // implicitly non-null
-// absl::Nullable GetNullablePtr(); // explicitly nullable
-// absl::NullabilityUnknown GetUnknownPtr(); // explicitly unknown
+// T* absl_nullable GetNullablePtr(); // explicitly nullable
+// T* absl_nullability_unknown GetUnknownPtr(); // explicitly unknown
//
-// The macro can be safely used in header files -- it will not affect any files
+// The macro can be safely used in header files – it will not affect any files
// that include it.
//
-// In files with the macro, plain `T*` syntax means `absl::Nonnull`, and the
-// exceptions (`Nullable` and `NullabilityUnknown`) must be marked
+// In files with the macro, plain `T*` syntax means `T* absl_nonnull`, and the
+// exceptions (`absl_nullable` and `absl_nullability_unknown`) must be marked
// explicitly. The same holds, correspondingly, for smart pointer types.
//
// For comparison, without the macro, all unannotated pointers would default to
@@ -183,17 +216,16 @@
//
// #include "absl/base/nullability.h"
//
-// void FillMessage(absl::Nonnull m); // explicitly non-null
-// absl::Nullable GetNullablePtr(); // explicitly nullable
+// void FillMessage(Message* absl_nonnull m); // explicitly non-null
+// T* absl_nullable GetNullablePtr(); // explicitly nullable
// T* GetUnknownPtr(); // implicitly unknown
//
// No-op except for being a human readable signal.
#define ABSL_POINTERS_DEFAULT_NONNULL
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// absl::Nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`)
+#if defined(__clang__) && !defined(__OBJC__) && \
+ ABSL_HAVE_FEATURE(nullability_on_classes)
+// absl_nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`)
//
// The indicated pointer is never null. It is the responsibility of the provider
// of this pointer across an API boundary to ensure that the pointer is never
@@ -203,13 +235,12 @@ ABSL_NAMESPACE_BEGIN
// Example:
//
// // `employee` is designated as not null.
-// void PaySalary(absl::Nonnull employee) {
+// void PaySalary(Employee* absl_nonnull employee) {
// pay(*employee); // OK to dereference
// }
-template
-using Nonnull = nullability_internal::NonnullImpl;
+#define absl_nonnull _Nonnull
-// absl::Nullable
+// absl_nullable
//
// The indicated pointer may, by design, be either null or non-null. Consumers
// of this pointer across an API boundary should perform a `nullptr` check
@@ -218,15 +249,14 @@ using Nonnull = nullability_internal::NonnullImpl;
// Example:
//
// // `employee` may be null.
-// void PaySalary(absl::Nullable employee) {
+// void PaySalary(Employee* absl_nullable employee) {
// if (employee != nullptr) {
// Pay(*employee); // OK to dereference
// }
// }
-template
-using Nullable = nullability_internal::NullableImpl;
+#define absl_nullable _Nullable
-// absl::NullabilityUnknown (default without `ABSL_POINTERS_DEFAULT_NONNULL`)
+// absl_nullability_unknown (default without `ABSL_POINTERS_DEFAULT_NONNULL`)
//
// The indicated pointer has not yet been determined to be definitively
// "non-null" or "nullable." Providers of such pointers across API boundaries
@@ -234,8 +264,8 @@ using Nullable = nullability_internal::NullableImpl;
// Consumers of these pointers across an API boundary should treat such pointers
// with the same caution they treat currently unannotated pointers. Most
// existing code will have "unknown" pointers, which should eventually be
-// migrated into one of the above two nullability states: `Nonnull` or
-// `Nullable`.
+// migrated into one of the above two nullability states: `absl_nonnull` or
+// `absl_nullable`.
//
// NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`,
// because this annotation is the global default state, unannotated pointers are
@@ -245,7 +275,7 @@ using Nullable = nullability_internal::NullableImpl;
// Example:
//
// // `employee`s nullability state is unknown.
-// void PaySalary(absl::NullabilityUnknown employee) {
+// void PaySalary(Employee* absl_nullability_unknown employee) {
// Pay(*employee); // Potentially dangerous. API provider should investigate.
// }
//
@@ -256,11 +286,15 @@ using Nullable = nullability_internal::NullableImpl;
// void PaySalary(Employee* employee) {
// Pay(*employee); // Potentially dangerous. API provider should investigate.
// }
-template
-using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl;
-
-ABSL_NAMESPACE_END
-} // namespace absl
+#define absl_nullability_unknown _Null_unspecified
+#else
+// No-op for non-Clang compilers or Objective-C.
+#define absl_nonnull
+// No-op for non-Clang compilers or Objective-C.
+#define absl_nullable
+// No-op for non-Clang compilers or Objective-C.
+#define absl_nullability_unknown
+#endif
// ABSL_NULLABILITY_COMPATIBLE
//
@@ -281,26 +315,4 @@ ABSL_NAMESPACE_END
#define ABSL_NULLABILITY_COMPATIBLE
#endif
-// ABSL_NONNULL
-// ABSL_NULLABLE
-// ABSL_NULLABILITY_UNKNOWN
-//
-// These macros are analogues of the alias template nullability annotations
-// above.
-//
-// Example:
-// int* ABSL_NULLABLE foo;
-// Is equivalent to:
-// absl::Nullable foo;
-#if defined(__clang__) && !defined(__OBJC__) && \
- ABSL_HAVE_FEATURE(nullability_on_classes)
-#define ABSL_NONNULL _Nonnull
-#define ABSL_NULLABLE _Nullable
-#define ABSL_NULLABILITY_UNKNOWN _Null_unspecified
-#else
-#define ABSL_NONNULL
-#define ABSL_NULLABLE
-#define ABSL_NULLABILITY_UNKNOWN
-#endif
-
#endif // ABSL_BASE_NULLABILITY_H_
diff --git a/absl/base/options.h b/absl/base/options.h
index 5caa58f..f904f64 100644
--- a/absl/base/options.h
+++ b/absl/base/options.h
@@ -64,65 +64,14 @@
// proper Abseil implementation at compile-time, which will not be sufficient
// to guarantee ABI stability to package managers.
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
#ifndef ABSL_BASE_OPTIONS_H_
#define ABSL_BASE_OPTIONS_H_
// -----------------------------------------------------------------------------
// Type Compatibility Options
// -----------------------------------------------------------------------------
-//
-// ABSL_OPTION_USE_STD_ANY
-//
-// This option controls whether absl::any is implemented as an alias to
-// std::any, or as an independent implementation.
-//
-// A value of 0 means to use Abseil's implementation. This requires only C++11
-// support, and is expected to work on every toolchain we support.
-//
-// A value of 1 means to use an alias to std::any. This requires that all code
-// using Abseil is built in C++17 mode or later.
-//
-// A value of 2 means to detect the C++ version being used to compile Abseil,
-// and use an alias only if a working std::any is available. This option is
-// useful when you are building your entire program, including all of its
-// dependencies, from source. It should not be used otherwise -- for example,
-// if you are distributing Abseil in a binary package manager -- since in
-// mode 2, absl::any will name a different type, with a different mangled name
-// and binary layout, depending on the compiler flags passed by the end user.
-// For more info, see https://abseil.io/about/design/dropin-types.
-//
-// User code should not inspect this macro. To check in the preprocessor if
-// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY.
-
-#define ABSL_OPTION_USE_STD_ANY 2
-
-
-// ABSL_OPTION_USE_STD_OPTIONAL
-//
-// This option controls whether absl::optional is implemented as an alias to
-// std::optional, or as an independent implementation.
-//
-// A value of 0 means to use Abseil's implementation. This requires only C++11
-// support, and is expected to work on every toolchain we support.
-//
-// A value of 1 means to use an alias to std::optional. This requires that all
-// code using Abseil is built in C++17 mode or later.
-//
-// A value of 2 means to detect the C++ version being used to compile Abseil,
-// and use an alias only if a working std::optional is available. This option
-// is useful when you are building your program from source. It should not be
-// used otherwise -- for example, if you are distributing Abseil in a binary
-// package manager -- since in mode 2, absl::optional will name a different
-// type, with a different mangled name and binary layout, depending on the
-// compiler flags passed by the end user. For more info, see
-// https://abseil.io/about/design/dropin-types.
-
-// User code should not inspect this macro. To check in the preprocessor if
-// absl::optional is a typedef of std::optional, use the feature macro
-// ABSL_USES_STD_OPTIONAL.
-
-#define ABSL_OPTION_USE_STD_OPTIONAL 2
-
// ABSL_OPTION_USE_STD_STRING_VIEW
//
@@ -150,32 +99,6 @@
#define ABSL_OPTION_USE_STD_STRING_VIEW 2
-// ABSL_OPTION_USE_STD_VARIANT
-//
-// This option controls whether absl::variant is implemented as an alias to
-// std::variant, or as an independent implementation.
-//
-// A value of 0 means to use Abseil's implementation. This requires only C++11
-// support, and is expected to work on every toolchain we support.
-//
-// A value of 1 means to use an alias to std::variant. This requires that all
-// code using Abseil is built in C++17 mode or later.
-//
-// A value of 2 means to detect the C++ version being used to compile Abseil,
-// and use an alias only if a working std::variant is available. This option
-// is useful when you are building your program from source. It should not be
-// used otherwise -- for example, if you are distributing Abseil in a binary
-// package manager -- since in mode 2, absl::variant will name a different
-// type, with a different mangled name and binary layout, depending on the
-// compiler flags passed by the end user. For more info, see
-// https://abseil.io/about/design/dropin-types.
-//
-// User code should not inspect this macro. To check in the preprocessor if
-// absl::variant is a typedef of std::variant, use the feature macro
-// ABSL_USES_STD_VARIANT.
-
-#define ABSL_OPTION_USE_STD_VARIANT 2
-
// ABSL_OPTION_USE_STD_ORDERING
//
// This option controls whether absl::{partial,weak,strong}_ordering are
@@ -226,7 +149,7 @@
// allowed.
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
-#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250127
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250512
// ABSL_OPTION_HARDENED
//
diff --git a/absl/base/policy_checks.h b/absl/base/policy_checks.h
index 7538166..f84944c 100644
--- a/absl/base/policy_checks.h
+++ b/absl/base/policy_checks.h
@@ -71,15 +71,15 @@
// C++ Version Check
// -----------------------------------------------------------------------------
-// Enforce C++14 as the minimum.
+// Enforce C++17 as the minimum.
#if defined(_MSVC_LANG)
-#if _MSVC_LANG < 201402L
-#error "C++ versions less than C++14 are not supported."
-#endif // _MSVC_LANG < 201402L
+#if _MSVC_LANG < 201703L
+#error "C++ versions less than C++17 are not supported."
+#endif // _MSVC_LANG < 201703L
#elif defined(__cplusplus)
-#if __cplusplus < 201402L
-#error "C++ versions less than C++14 are not supported."
-#endif // __cplusplus < 201402L
+#if __cplusplus < 201703L
+#error "C++ versions less than C++17 are not supported."
+#endif // __cplusplus < 201703L
#endif
// -----------------------------------------------------------------------------
diff --git a/absl/cleanup/cleanup.h b/absl/cleanup/cleanup.h
index 960ccd0..311e482 100644
--- a/absl/cleanup/cleanup.h
+++ b/absl/cleanup/cleanup.h
@@ -78,7 +78,7 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
template
-class ABSL_MUST_USE_RESULT Cleanup final {
+class [[nodiscard]] Cleanup final {
static_assert(cleanup_internal::WasDeduced(),
"Explicit template parameters are not supported.");
@@ -115,10 +115,8 @@ class ABSL_MUST_USE_RESULT Cleanup final {
// `absl::Cleanup c = /* callback */;`
//
// C++17 type deduction API for creating an instance of `absl::Cleanup`
-#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
template
Cleanup(Callback callback) -> Cleanup;
-#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
// `auto c = absl::MakeCleanup(/* callback */);`
//
diff --git a/absl/cleanup/internal/cleanup.h b/absl/cleanup/internal/cleanup.h
index 2783fcb..4dd6f91 100644
--- a/absl/cleanup/internal/cleanup.h
+++ b/absl/cleanup/internal/cleanup.h
@@ -19,7 +19,6 @@
#include
#include
-#include "absl/base/internal/invoke.h"
#include "absl/base/macros.h"
#include "absl/base/thread_annotations.h"
#include "absl/utility/utility.h"
@@ -39,7 +38,7 @@ constexpr bool WasDeduced() {
template
constexpr bool ReturnsVoid() {
- return (std::is_same, void>::value);
+ return (std::is_same, void>::value);
}
template
@@ -70,7 +69,7 @@ class Storage {
Storage& operator=(const Storage& other) = delete;
- void* GetCallbackBuffer() { return static_cast(+callback_buffer_); }
+ void* GetCallbackBuffer() { return static_cast(callback_buffer_); }
Callback& GetCallback() {
return *reinterpret_cast(GetCallbackBuffer());
@@ -89,7 +88,7 @@ class Storage {
private:
bool is_callback_engaged_;
- alignas(Callback) char callback_buffer_[sizeof(Callback)];
+ alignas(Callback) unsigned char callback_buffer_[sizeof(Callback)];
};
} // namespace cleanup_internal
diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h
index 470de2a..32a82ef 100644
--- a/absl/container/btree_map.h
+++ b/absl/container/btree_map.h
@@ -47,8 +47,10 @@
// iterator at the current position. Another important difference is that
// key-types must be copy-constructible.
//
-// Another API difference is that btree iterators can be subtracted, and this
-// is faster than using std::distance.
+// There are other API differences: first, btree iterators can be subtracted,
+// and this is faster than using `std::distance`. Additionally, btree
+// iterators can be advanced via `operator+=` and `operator-=`, which is faster
+// than using `std::advance`.
//
// B-tree maps are not exception-safe.
diff --git a/absl/container/btree_set.h b/absl/container/btree_set.h
index e57d6d9..16181de 100644
--- a/absl/container/btree_set.h
+++ b/absl/container/btree_set.h
@@ -46,8 +46,10 @@
// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid
// iterator at the current position.
//
-// Another API difference is that btree iterators can be subtracted, and this
-// is faster than using std::distance.
+// There are other API differences: first, btree iterators can be subtracted,
+// and this is faster than using `std::distance`. Additionally, btree
+// iterators can be advanced via `operator+=` and `operator-=`, which is faster
+// than using `std::advance`.
//
// B-tree sets are not exception-safe.
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 95abb0a..6c238fc 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -44,11 +44,13 @@
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/dynamic_annotations.h"
+#include "absl/base/internal/iterator_traits.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
#include "absl/container/internal/compressed_tuple.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
#include "absl/memory/memory.h"
namespace absl {
@@ -85,9 +87,8 @@ class ABSL_ATTRIBUTE_WARN_UNUSED FixedArray {
// std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
// but this seems to be mostly pedantic.
template
- using EnableIfForwardIterator = absl::enable_if_t::iterator_category,
- std::forward_iterator_tag>::value>;
+ using EnableIfForwardIterator = std::enable_if_t<
+ base_internal::IsAtLeastForwardIterator::value>;
static constexpr bool NoexceptCopyable() {
return std::is_nothrow_copy_constructible::value &&
absl::allocator_is_nothrow::value;
@@ -392,7 +393,7 @@ class ABSL_ATTRIBUTE_WARN_UNUSED FixedArray {
template
friend H AbslHashValue(H h, const FixedArray& v) {
return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
- v.size());
+ hash_internal::WeaklyMixedInteger{v.size()});
}
private:
@@ -447,7 +448,8 @@ class ABSL_ATTRIBUTE_WARN_UNUSED FixedArray {
private:
ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
- alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
+ alignas(StorageElement) unsigned char buff_[sizeof(
+ StorageElement[inline_elements])];
ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);
};
@@ -517,15 +519,6 @@ class ABSL_ATTRIBUTE_WARN_UNUSED FixedArray {
Storage storage_;
};
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template
-constexpr size_t FixedArray::kInlineBytesDefault;
-
-template
-constexpr typename FixedArray::size_type
- FixedArray::inline_elements;
-#endif
-
template
void FixedArray::NonEmptyInlinedStorage::AnnotateConstruct(
typename FixedArray::size_type n) {
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index 735ee34..bc86ced 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -104,6 +104,11 @@ struct FlatHashMapPolicy;
// If your types are not moveable or you require pointer stability for keys,
// consider `absl::node_hash_map`.
//
+// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:
+// * Iteration takes O(capacity) time, not O(size).
+// * erase() slows down begin() and ++iterator.
+// * Capacity only shrinks on rehash() or clear() -- not on erase().
+//
// Example:
//
// // Create a flat hash map of three strings (that map to strings)
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index b5d0f7f..bf63eb5 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -62,7 +62,7 @@ struct FlatHashSetPolicy;
// Its interface is similar to that of `std::unordered_set` with the
// following notable differences:
//
-// * Requires keys that are CopyConstructible
+// * Requires keys that are MoveConstructible
// * Supports heterogeneous lookup, through `find()` and `insert()`, provided
// that the set is provided a compatible heterogeneous hashing function and
// equality operator. See below for details.
@@ -103,6 +103,11 @@ struct FlatHashSetPolicy;
// `absl::flat_hash_set>`. If your type is not moveable and
// you require pointer stability, consider `absl::node_hash_set` instead.
//
+// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:
+// * Iteration takes O(capacity) time, not O(size).
+// * erase() slows down begin() and ++iterator.
+// * Capacity only shrinks on rehash() or clear() -- not on erase().
+//
// Example:
//
// // Create a flat hash set of three strings
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index cbf8bc2..f871b34 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -47,11 +47,13 @@
#include "absl/algorithm/algorithm.h"
#include "absl/base/attributes.h"
+#include "absl/base/internal/iterator_traits.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
#include "absl/container/internal/inlined_vector.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
@@ -90,11 +92,11 @@ class ABSL_ATTRIBUTE_WARN_UNUSED InlinedVector {
inlined_vector_internal::DefaultValueAdapter;
template
- using EnableIfAtLeastForwardIterator = absl::enable_if_t<
- inlined_vector_internal::IsAtLeastForwardIterator::value, int>;
+ using EnableIfAtLeastForwardIterator = std::enable_if_t<
+ base_internal::IsAtLeastForwardIterator::value, int>;
template
- using DisableIfAtLeastForwardIterator = absl::enable_if_t<
- !inlined_vector_internal::IsAtLeastForwardIterator::value, int>;
+ using DisableIfAtLeastForwardIterator = std::enable_if_t<
+ !base_internal::IsAtLeastForwardIterator::value, int>;
using MemcpyPolicy = typename Storage::MemcpyPolicy;
using ElementwiseAssignPolicy = typename Storage::ElementwiseAssignPolicy;
@@ -1007,7 +1009,8 @@ bool operator>=(const absl::InlinedVector& a,
template
H AbslHashValue(H h, const absl::InlinedVector& a) {
auto size = a.size();
- return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size);
+ return H::combine(H::combine_contiguous(std::move(h), a.data(), size),
+ hash_internal::WeaklyMixedInteger{size});
}
ABSL_NAMESPACE_END
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index 689e71a..ed541e7 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -60,6 +60,7 @@
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
#include "absl/container/internal/common.h"
#include "absl/container/internal/common_policy_traits.h"
#include "absl/container/internal/compressed_tuple.h"
@@ -224,7 +225,7 @@ struct key_compare_adapter {
public:
using Base::Base;
- checked_compare(Compare comp) : Base(std::move(comp)) {} // NOLINT
+ checked_compare(Compare cmp) : Base(std::move(cmp)) {} // NOLINT
// Allow converting to Compare for use in key_comp()/value_comp().
explicit operator Compare() const { return comp(); }
@@ -708,6 +709,8 @@ class btree_node {
}
// Getter for the parent of this node.
+ // TODO(ezb): assert that the child of the returned node at position
+ // `node_->position()` maps to the current node.
btree_node *parent() const { return *GetField<0>(); }
// Getter for whether the node is the root of the tree. The parent of the
// root of the tree is the leftmost node in the tree which is guaranteed to
@@ -1175,6 +1178,26 @@ class btree_iterator : private btree_iterator_generation_info {
return distance_slow(other);
}
+ // Advances the iterator by `n`. Values of `n` must not result in going past
+ // the `end` iterator (for a positive `n`) or before the `begin` iterator (for
+ // a negative `n`).
+ btree_iterator &operator+=(difference_type n) {
+ assert_valid_generation(node_);
+ if (n == 0) return *this;
+ if (n < 0) return decrement_n_slow(-n);
+ return increment_n_slow(n);
+ }
+
+ // Moves the iterator by `n` positions backwards. Values of `n` must not
+ // result in going before the `begin` iterator (for a positive `n`) or past
+ // the `end` iterator (for a negative `n`).
+ btree_iterator &operator-=(difference_type n) {
+ assert_valid_generation(node_);
+ if (n == 0) return *this;
+ if (n < 0) return increment_n_slow(-n);
+ return decrement_n_slow(n);
+ }
+
// Accessors for the key/value the iterator is pointing at.
reference operator*() const {
ABSL_HARDENING_ASSERT(node_ != nullptr);
@@ -1277,6 +1300,7 @@ class btree_iterator : private btree_iterator_generation_info {
increment_slow();
}
void increment_slow();
+ btree_iterator &increment_n_slow(difference_type n);
void decrement() {
assert_valid_generation(node_);
@@ -1286,6 +1310,7 @@ class btree_iterator : private btree_iterator_generation_info {
decrement_slow();
}
void decrement_slow();
+ btree_iterator &decrement_n_slow(difference_type n);
const key_type &key() const {
return node_->key(static_cast(position_));
@@ -2126,50 +2151,128 @@ auto btree_iterator::distance_slow(const_iterator other) const
template
void btree_iterator::increment_slow() {
- if (node_->is_leaf()) {
- assert(position_ >= node_->finish());
- btree_iterator save(*this);
- while (position_ == node_->finish() && !node_->is_root()) {
- assert(node_->parent()->child(node_->position()) == node_);
- position_ = node_->position();
- node_ = node_->parent();
+ N* node = node_;
+ int position = position_;
+ if (node->is_leaf()) {
+ assert(position >= node->finish());
+ while (position == node->finish() && !node->is_root()) {
+ assert(node->parent()->child(node->position()) == node);
+ position = node->position();
+ node = node->parent();
}
// TODO(ezb): assert we aren't incrementing end() instead of handling.
- if (position_ == node_->finish()) {
- *this = save;
+ if (position == node->finish()) {
+ return;
}
} else {
- assert(position_ < node_->finish());
- node_ = node_->child(static_cast(position_ + 1));
- while (node_->is_internal()) {
- node_ = node_->start_child();
+ assert(position < node->finish());
+ node = node->child(static_cast(position + 1));
+ while (node->is_internal()) {
+ node = node->start_child();
}
- position_ = node_->start();
+ position = node->start();
}
+ *this = {node, position};
}
template
void btree_iterator::decrement_slow() {
- if (node_->is_leaf()) {
- assert(position_ <= -1);
- btree_iterator save(*this);
- while (position_ < node_->start() && !node_->is_root()) {
- assert(node_->parent()->child(node_->position()) == node_);
- position_ = node_->position() - 1;
- node_ = node_->parent();
+ N* node = node_;
+ int position = position_;
+ if (node->is_leaf()) {
+ assert(position <= -1);
+ while (position < node->start() && !node->is_root()) {
+ assert(node->parent()->child(node->position()) == node);
+ position = node->position() - 1;
+ node = node->parent();
}
// TODO(ezb): assert we aren't decrementing begin() instead of handling.
- if (position_ < node_->start()) {
- *this = save;
+ if (position < node->start()) {
+ return;
}
} else {
- assert(position_ >= node_->start());
- node_ = node_->child(static_cast(position_));
- while (node_->is_internal()) {
- node_ = node_->child(node_->finish());
+ assert(position >= node->start());
+ node = node->child(static_cast(position));
+ while (node->is_internal()) {
+ node = node->child(node->finish());
}
- position_ = node_->finish() - 1;
+ position = node->finish() - 1;
}
+ *this = {node, position};
+}
+
+template
+btree_iterator &btree_iterator::increment_n_slow(
+ difference_type n) {
+ N *node = node_;
+ int position = position_;
+ ABSL_ASSUME(n > 0);
+ while (n > 0) {
+ if (node->is_leaf()) {
+ if (position + n < node->finish()) {
+ position += n;
+ break;
+ } else {
+ n -= node->finish() - position;
+ position = node->finish();
+ btree_iterator save = {node, position};
+ while (position == node->finish() && !node->is_root()) {
+ position = node->position();
+ node = node->parent();
+ }
+ if (position == node->finish()) {
+ ABSL_HARDENING_ASSERT(n == 0);
+ return *this = save;
+ }
+ }
+ } else {
+ --n;
+ assert(position < node->finish());
+ node = node->child(static_cast(position + 1));
+ while (node->is_internal()) {
+ node = node->start_child();
+ }
+ position = node->start();
+ }
+ }
+ node_ = node;
+ position_ = position;
+ return *this;
+}
+
+template
+btree_iterator &btree_iterator::decrement_n_slow(
+ difference_type n) {
+ N *node = node_;
+ int position = position_;
+ ABSL_ASSUME(n > 0);
+ while (n > 0) {
+ if (node->is_leaf()) {
+ if (position - n >= node->start()) {
+ position -= n;
+ break;
+ } else {
+ n -= 1 + position - node->start();
+ position = node->start() - 1;
+ while (position < node->start() && !node->is_root()) {
+ position = node->position() - 1;
+ node = node->parent();
+ }
+ ABSL_HARDENING_ASSERT(position >= node->start());
+ }
+ } else {
+ --n;
+ assert(position >= node->start());
+ node = node->child(static_cast(position));
+ while (node->is_internal()) {
+ node = node->child(node->finish());
+ }
+ position = node->finish() - 1;
+ }
+ }
+ node_ = node;
+ position_ = position;
+ return *this;
}
////
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h
index a68ce44..21f00ae 100644
--- a/absl/container/internal/btree_container.h
+++ b/absl/container/internal/btree_container.h
@@ -18,12 +18,14 @@
#include
#include
#include
+#include
#include
#include "absl/base/attributes.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/container/internal/btree.h" // IWYU pragma: export
#include "absl/container/internal/common.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
@@ -266,7 +268,8 @@ class btree_container {
for (const auto &v : b) {
h = State::combine(std::move(h), v);
}
- return State::combine(std::move(h), b.size());
+ return State::combine(std::move(h),
+ hash_internal::WeaklyMixedInteger{b.size()});
}
protected:
@@ -451,6 +454,29 @@ class btree_map_container : public btree_set_container {
template
using key_arg = typename super_type::template key_arg;
+ // NOTE: The mess here is to shorten the code for the (very repetitive)
+ // function overloads, and to allow the lifetime-bound overloads to dispatch
+ // to the non-lifetime-bound overloads, to ensure there is a single source of
+ // truth for each overload set.
+ //
+ // Enabled if an assignment from the given type would require the
+ // source object to remain alive for the life of the element.
+ //
+ // TODO(b/402804213): Remove these traits and simplify the overloads whenever
+ // we have a better mechanism available to handle lifetime analysis.
+ template
+ using LifetimeBoundK =
+ HasValue>;
+ template
+ using LifetimeBoundV =
+ HasValue>;
+ template
+ using LifetimeBoundKV =
+ absl::conjunction>,
+ LifetimeBoundV>;
+
public:
using key_type = typename Tree::key_type;
using mapped_type = typename params_type::mapped_type;
@@ -464,85 +490,163 @@ class btree_map_container : public btree_set_container {
using super_type::super_type;
btree_map_container() {}
+ // TODO(b/402804213): Remove these macros whenever we have a better mechanism
+ // available to handle lifetime analysis.
+#define ABSL_INTERNAL_X(Func, Callee, KQual, MQual, KValue, MValue, ...) \
+ template < \
+ typename K = key_type, class M, \
+ ABSL_INTERNAL_IF_##KValue##_NOR_##MValue( \
+ int = (EnableIf::AddPtr, \
+ IfRRef