mirror of https://github.com/mongodb/mongo
SERVER-106442 Upgrade abseil-cpp...with linker fixes (#38534)
GitOrigin-RevId: 2a89994de90be42cc5e4f5cac16c145f0ad10dbd
This commit is contained in:
parent
1b4cb574d1
commit
8a710772c6
|
|
@ -1,4 +1,4 @@
|
|||
[DO NOT MODIFY THIS FILE MANUALLY. It is generated by src/third_party/tools/gen_thirdpartyreadme.py]: #
|
||||
[DO NOT MODIFY THIS FILE MANUALLY. It is generated by src/third_party/scripts/gen_thirdpartyreadme.py]: #
|
||||
|
||||
# MongoDB Third Party Dependencies
|
||||
|
||||
|
|
@ -23,12 +23,12 @@ a notice will be included in
|
|||
|
||||
| Name | License | Vendored Version | Emits persisted data | Distributed in Release Binaries |
|
||||
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------- | -------------------- | ------------------------------- |
|
||||
| [Abseil] | Apache-2.0 | 20230802.1 | | ✗ |
|
||||
| [Abseil] | Apache-2.0 | 20250512.1 | | ✗ |
|
||||
| [arximboldi/immer] | BSL-1.0 | Unknown | | ✗ |
|
||||
| [Asio C++ Library] | BSL-1.0 | 1.12.2 | | ✗ |
|
||||
| [aws-sdk - the AWS SDK client library] | Apache-2.0 | 1.11.471 | | ✗ |
|
||||
| [benchmark] | Apache-2.0 | v1.5.2 | | |
|
||||
| [Boost C++ Libraries - boost] | BSL-1.0 | 1.79.0 | | ✗ |
|
||||
| [Boost C++ Libraries - boost] | BSL-1.0 | 1.88.0 | | ✗ |
|
||||
| [c-ares] | MIT | 1.27.0 | | ✗ |
|
||||
| [concurrencytest] | GPL-3.0-or-later | 0.1.2 | unknown | |
|
||||
| [Cyrus SASL] | BSD-Attribution-HPND-disclaimer | 2.1.28 | unknown | |
|
||||
|
|
@ -36,6 +36,7 @@ a notice will be included in
|
|||
| [derickr/timelib] | MIT | 2022.13 | | ✗ |
|
||||
| [discover] | BSD-3-Clause | 0.4.0 | unknown | |
|
||||
| [fmtlib/fmt] | MIT | 11.1.3 | | ✗ |
|
||||
| [folly] | Apache-2.0 | v2025.04.21.00 | | ✗ |
|
||||
| [google-re2] | BSD-3-Clause | 2023-11-01 | | ✗ |
|
||||
| [google-snappy] | BSD-3-Clause | 1.1.10 | ✗ | ✗ |
|
||||
| [google/s2geometry] | Apache-2.0 | Unknown | ✗ | ✗ |
|
||||
|
|
@ -100,6 +101,7 @@ a notice will be included in
|
|||
[derickr/timelib]: https://github.com/derickr/timelib
|
||||
[discover]: https://pypi.org/project/discover/
|
||||
[fmtlib/fmt]: http://fmtlib.net/
|
||||
[folly]: https://github.com/facebook/folly
|
||||
[google-re2]: https://github.com/google/re2
|
||||
[google-snappy]: https://github.com/google/snappy/releases
|
||||
[google/s2geometry]: https://github.com/google/s2geometry
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ def absl_insert_version_after_absl(cpp_name):
|
|||
"""Insert version inline namespace after the first `absl` namespace found in the given string."""
|
||||
# See more:
|
||||
# https://github.com/abseil/abseil-cpp/blob/929c17cf481222c35ff1652498994871120e832a/absl/base/options.h#L203
|
||||
ABSL_OPTION_INLINE_NAMESPACE_NAME = "lts_20230802"
|
||||
ABSL_OPTION_INLINE_NAMESPACE_NAME = "lts_20250512"
|
||||
|
||||
absl_ns_str = "absl::"
|
||||
absl_ns_start = cpp_name.find(absl_ns_str)
|
||||
|
|
@ -586,7 +586,7 @@ def absl_get_settings(val):
|
|||
if not err.args[0].startswith("No type named "):
|
||||
raise
|
||||
|
||||
# Abseil uses `inline namespace lts_20230802 { ... }` for its container types. This
|
||||
# Abseil uses `inline namespace lts_20250512 { ... }` for its container types. This
|
||||
# can inhibit GDB from resolving type names when the inline namespace appears within
|
||||
# a template argument.
|
||||
common_fields_storage_type = gdb.lookup_type(
|
||||
|
|
@ -603,7 +603,7 @@ def absl_get_settings(val):
|
|||
|
||||
|
||||
def absl_container_size(settings):
|
||||
return settings["compressed_tuple_"]["value"]
|
||||
return settings["size_"]["data_"] >> 17
|
||||
|
||||
|
||||
def absl_get_nodes(val):
|
||||
|
|
@ -615,7 +615,8 @@ def absl_get_nodes(val):
|
|||
return
|
||||
|
||||
capacity = int(settings["capacity_"])
|
||||
ctrl = settings["control_"]
|
||||
heap = settings["heap_or_soo_"]["heap"]
|
||||
ctrl = heap["control"]
|
||||
|
||||
# Derive the underlying type stored in the container.
|
||||
slot_type = lookup_type(str(val.type.strip_typedefs()) + "::slot_type").strip_typedefs()
|
||||
|
|
@ -625,7 +626,7 @@ def absl_get_nodes(val):
|
|||
for item in range(capacity):
|
||||
ctrl_t = int(ctrl[item])
|
||||
if ctrl_t >= 0:
|
||||
yield settings["slots_"].cast(slot_type.pointer())[item]
|
||||
yield heap["slot_array"]["p"].cast(slot_type.pointer())[item]
|
||||
|
||||
|
||||
class AbslHashSetPrinterBase(object):
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
"name": "Organization: github"
|
||||
},
|
||||
"name": "Abseil",
|
||||
"version": "20230802.1",
|
||||
"version": "20250512.1",
|
||||
"licenses": [
|
||||
{
|
||||
"license": {
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"purl": "pkg:github/abseil/abseil-cpp@20230802.1",
|
||||
"purl": "pkg:github/abseil/abseil-cpp@20250512.1",
|
||||
"properties": [
|
||||
{
|
||||
"name": "internal:team_responsible",
|
||||
|
|
|
|||
|
|
@ -56,7 +56,14 @@ class ReplicaSetChangeNotifier {
|
|||
public:
|
||||
using Key = std::string;
|
||||
class Listener;
|
||||
struct State;
|
||||
|
||||
struct State {
|
||||
ConnectionString connStr;
|
||||
HostAndPort primary;
|
||||
std::set<HostAndPort> passives;
|
||||
|
||||
int64_t generation = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
ReplicaSetChangeNotifier() = default;
|
||||
|
|
@ -166,12 +173,4 @@ private:
|
|||
Notifier* _notifier = nullptr;
|
||||
};
|
||||
|
||||
struct ReplicaSetChangeNotifier::State {
|
||||
ConnectionString connStr;
|
||||
HostAndPort primary;
|
||||
std::set<HostAndPort> passives;
|
||||
|
||||
int64_t generation = 0;
|
||||
};
|
||||
|
||||
} // namespace mongo
|
||||
|
|
|
|||
|
|
@ -138,7 +138,8 @@ public:
|
|||
opCtx, fromNs, AcquisitionPrerequisites::OperationType::kWrite),
|
||||
CollectionAcquisitionRequest::fromOpCtx(
|
||||
opCtx, toNs, AcquisitionPrerequisites::OperationType::kWrite)};
|
||||
auto acquisitions = acquireCollections(opCtx, acquisitionRequests, LockMode::MODE_X);
|
||||
[[maybe_unused]] auto acquisitions =
|
||||
acquireCollections(opCtx, acquisitionRequests, LockMode::MODE_X);
|
||||
|
||||
if (!repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(opCtx, toNs)) {
|
||||
uasserted(ErrorCodes::NotWritablePrimary,
|
||||
|
|
|
|||
|
|
@ -2212,7 +2212,7 @@ TEST_F(ShardRoleTest, RestoreChangesReadSourceAfterStepUp) {
|
|||
shard_role_details::getRecoveryUnit(operationContext())->getTimestampReadSource());
|
||||
|
||||
PlacementConcern placementConcern{dbVersionTestDb, ShardVersion::UNSHARDED()};
|
||||
const auto acquisitions =
|
||||
[[maybe_unused]] const auto acquisitions =
|
||||
acquireCollectionsOrViewsMaybeLockFree(operationContext(),
|
||||
{{
|
||||
nssUnshardedCollection1,
|
||||
|
|
|
|||
|
|
@ -5097,7 +5097,7 @@ TEST_F(
|
|||
measurementsAndRolloverReason.end(),
|
||||
{std::make_pair(nonSchemaChangeBucketVec, RolloverReason::kSchemaChange),
|
||||
std::make_pair(schemaChangeVec, RolloverReason::kSchemaChange)});
|
||||
absl::InlinedVector<Bucket*, 8> buckets =
|
||||
[[maybe_unused]] absl::InlinedVector<Bucket*, 8> buckets =
|
||||
_generateBucketsWithMeasurements(_ns1, _uuid1, measurementsAndRolloverReason);
|
||||
|
||||
// Inserting a batch of measurements with meta field values into a collection with a meta field.
|
||||
|
|
@ -5311,7 +5311,7 @@ TEST_F(
|
|||
std::make_pair(measurement1Vec, RolloverReason::kSchemaChange),
|
||||
std::make_pair(measurement1Vec, RolloverReason::kSchemaChange),
|
||||
});
|
||||
absl::InlinedVector<Bucket*, 8> buckets =
|
||||
[[maybe_unused]] absl::InlinedVector<Bucket*, 8> buckets =
|
||||
_generateBucketsWithMeasurements(_nsNoMeta, _uuidNoMeta, measurementsAndRolloverReason);
|
||||
|
||||
// Inserting a batch of measurements without meta field values into a collection without a meta
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@
|
|||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include <absl/hash/hash.h>
|
||||
|
||||
// IWYU pragma: no_include "cxxabi.h"
|
||||
#include "mongo/base/data_range.h"
|
||||
#include "mongo/base/init.h" // IWYU pragma: keep
|
||||
#include "mongo/base/initializer.h"
|
||||
|
|
@ -61,6 +58,8 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <absl/hash/hash.h>
|
||||
|
||||
#if defined(MONGO_CONFIG_HAVE_HEADER_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
|
@ -77,6 +76,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(_POSIX_VERSION) && defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE)
|
||||
#include <cxxabi.h>
|
||||
#include <dlfcn.h>
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,15 +29,16 @@
|
|||
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/printf.h> // IWYU pragma: keep
|
||||
// IWYU pragma: no_include "cxxabi.h"
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <cxxabi.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/printf.h> // IWYU pragma: keep
|
||||
|
||||
// IWYU pragma: no_include "libunwind-x86_64.h"
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <cxxabi.h>
|
||||
// IWYU pragma: no_include "libunwind-x86_64.h"
|
||||
|
||||
#include "mongo/base/init.h" // IWYU pragma: keep
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/base/config.h",
|
||||
"dist/absl/base/const_init.h",
|
||||
"dist/absl/base/dynamic_annotations.h",
|
||||
"dist/absl/base/fast_type_id.h",
|
||||
"dist/absl/base/internal/atomic_hook.h",
|
||||
"dist/absl/base/internal/atomic_hook_test_helper.h",
|
||||
"dist/absl/base/internal/cycleclock.h",
|
||||
|
|
@ -23,17 +24,15 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/base/internal/errno_saver.h",
|
||||
"dist/absl/base/internal/exception_safety_testing.h",
|
||||
"dist/absl/base/internal/exception_testing.h",
|
||||
"dist/absl/base/internal/fast_type_id.h",
|
||||
"dist/absl/base/internal/hide_ptr.h",
|
||||
"dist/absl/base/internal/identity.h",
|
||||
"dist/absl/base/internal/inline_variable.h",
|
||||
"dist/absl/base/internal/inline_variable_testing.h",
|
||||
"dist/absl/base/internal/invoke.h",
|
||||
"dist/absl/base/internal/iterator_traits.h",
|
||||
"dist/absl/base/internal/iterator_traits_test_helper.h",
|
||||
"dist/absl/base/internal/low_level_alloc.h",
|
||||
"dist/absl/base/internal/low_level_scheduling.h",
|
||||
"dist/absl/base/internal/nullability_impl.h",
|
||||
"dist/absl/base/internal/nullability_deprecated.h",
|
||||
"dist/absl/base/internal/per_thread_tls.h",
|
||||
"dist/absl/base/internal/prefetch.h",
|
||||
"dist/absl/base/internal/poison.h",
|
||||
"dist/absl/base/internal/pretty_function.h",
|
||||
"dist/absl/base/internal/raw_logging.h",
|
||||
"dist/absl/base/internal/scheduling_mode.h",
|
||||
|
|
@ -46,15 +45,16 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/base/internal/spinlock_win32.inc",
|
||||
"dist/absl/base/internal/strerror.h",
|
||||
"dist/absl/base/internal/sysinfo.h",
|
||||
"dist/absl/base/internal/thread_annotations.h",
|
||||
"dist/absl/base/internal/thread_identity.h",
|
||||
"dist/absl/base/internal/throw_delegate.h",
|
||||
"dist/absl/base/internal/tracing.h",
|
||||
"dist/absl/base/internal/tsan_mutex_interface.h",
|
||||
"dist/absl/base/internal/unaligned_access.h",
|
||||
"dist/absl/base/internal/unscaledcycleclock.h",
|
||||
"dist/absl/base/internal/unscaledcycleclock_config.h",
|
||||
"dist/absl/base/log_severity.h",
|
||||
"dist/absl/base/macros.h",
|
||||
"dist/absl/base/no_destructor.h",
|
||||
"dist/absl/base/nullability.h",
|
||||
"dist/absl/base/optimization.h",
|
||||
"dist/absl/base/options.h",
|
||||
|
|
@ -70,6 +70,7 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/container/fixed_array.h",
|
||||
"dist/absl/container/flat_hash_map.h",
|
||||
"dist/absl/container/flat_hash_set.h",
|
||||
"dist/absl/container/hash_container_defaults.h",
|
||||
"dist/absl/container/inlined_vector.h",
|
||||
"dist/absl/container/internal/btree.h",
|
||||
"dist/absl/container/internal/btree_container.h",
|
||||
|
|
@ -77,11 +78,11 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/container/internal/common_policy_traits.h",
|
||||
"dist/absl/container/internal/compressed_tuple.h",
|
||||
"dist/absl/container/internal/container_memory.h",
|
||||
"dist/absl/container/internal/counting_allocator.h",
|
||||
"dist/absl/container/internal/hash_function_defaults.h",
|
||||
"dist/absl/container/internal/hash_generator_testing.h",
|
||||
"dist/absl/container/internal/hash_policy_testing.h",
|
||||
"dist/absl/container/internal/hash_policy_traits.h",
|
||||
"dist/absl/container/internal/hashtable_control_bytes.h",
|
||||
"dist/absl/container/internal/hashtable_debug.h",
|
||||
"dist/absl/container/internal/hashtable_debug_hooks.h",
|
||||
"dist/absl/container/internal/hashtablez_sampler.h",
|
||||
|
|
@ -90,6 +91,8 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/container/internal/node_slot_policy.h",
|
||||
"dist/absl/container/internal/raw_hash_map.h",
|
||||
"dist/absl/container/internal/raw_hash_set.h",
|
||||
"dist/absl/container/internal/raw_hash_set_resize_impl.h",
|
||||
"dist/absl/container/internal/test_allocator.h",
|
||||
"dist/absl/container/internal/test_instance_tracker.h",
|
||||
"dist/absl/container/internal/tracked.h",
|
||||
"dist/absl/container/internal/unordered_map_constructor_test.h",
|
||||
|
|
@ -115,14 +118,17 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/crc/internal/non_temporal_memcpy.h",
|
||||
"dist/absl/debugging/failure_signal_handler.h",
|
||||
"dist/absl/debugging/internal/address_is_readable.h",
|
||||
"dist/absl/debugging/internal/addresses.h",
|
||||
"dist/absl/debugging/internal/bounded_utf8_length_sequence.h",
|
||||
"dist/absl/debugging/internal/decode_rust_punycode.h",
|
||||
"dist/absl/debugging/internal/demangle.h",
|
||||
"dist/absl/debugging/internal/demangle_rust.h",
|
||||
"dist/absl/debugging/internal/elf_mem_image.h",
|
||||
"dist/absl/debugging/internal/examine_stack.h",
|
||||
"dist/absl/debugging/internal/stack_consumption.h",
|
||||
"dist/absl/debugging/internal/stacktrace_aarch64-inl.inc",
|
||||
"dist/absl/debugging/internal/stacktrace_arm-inl.inc",
|
||||
"dist/absl/debugging/internal/stacktrace_config.h",
|
||||
"dist/absl/debugging/internal/stacktrace_emscripten-inl.inc",
|
||||
"dist/absl/debugging/internal/stacktrace_generic-inl.inc",
|
||||
"dist/absl/debugging/internal/stacktrace_powerpc-inl.inc",
|
||||
"dist/absl/debugging/internal/stacktrace_riscv-inl.inc",
|
||||
|
|
@ -130,6 +136,7 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/debugging/internal/stacktrace_win32-inl.inc",
|
||||
"dist/absl/debugging/internal/stacktrace_x86-inl.inc",
|
||||
"dist/absl/debugging/internal/symbolize.h",
|
||||
"dist/absl/debugging/internal/utf8_for_code_point.h",
|
||||
"dist/absl/debugging/internal/vdso_support.h",
|
||||
"dist/absl/debugging/leak_check.h",
|
||||
"dist/absl/debugging/stacktrace.h",
|
||||
|
|
@ -145,7 +152,6 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/flags/flag.h",
|
||||
"dist/absl/flags/internal/commandlineflag.h",
|
||||
"dist/absl/flags/internal/flag.h",
|
||||
"dist/absl/flags/internal/flag_msvc.inc",
|
||||
"dist/absl/flags/internal/parse.h",
|
||||
"dist/absl/flags/internal/path_util.h",
|
||||
"dist/absl/flags/internal/private_handle_accessor.h",
|
||||
|
|
@ -164,6 +170,7 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/functional/internal/any_invocable.h",
|
||||
"dist/absl/functional/internal/front_binder.h",
|
||||
"dist/absl/functional/internal/function_ref.h",
|
||||
"dist/absl/functional/overload.h",
|
||||
"dist/absl/hash/hash.h",
|
||||
"dist/absl/hash/hash_testing.h",
|
||||
"dist/absl/hash/internal/city.h",
|
||||
|
|
@ -171,8 +178,11 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/hash/internal/hash_test.h",
|
||||
"dist/absl/hash/internal/low_level_hash.h",
|
||||
"dist/absl/hash/internal/spy_hash_state.h",
|
||||
"dist/absl/hash/internal/weakly_mixed_integer.h",
|
||||
"dist/absl/log/absl_check.h",
|
||||
"dist/absl/log/absl_log.h",
|
||||
"dist/absl/log/absl_vlog_is_on.h",
|
||||
"dist/absl/log/log_basic_test_impl.inc",
|
||||
"dist/absl/log/check.h",
|
||||
"dist/absl/log/check_test_impl.inc",
|
||||
"dist/absl/log/die_if_null.h",
|
||||
|
|
@ -185,6 +195,7 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/log/internal/conditions.h",
|
||||
"dist/absl/log/internal/config.h",
|
||||
"dist/absl/log/internal/flags.h",
|
||||
"dist/absl/log/internal/fnmatch.h",
|
||||
"dist/absl/log/internal/globals.h",
|
||||
"dist/absl/log/internal/log_format.h",
|
||||
"dist/absl/log/internal/log_impl.h",
|
||||
|
|
@ -195,18 +206,20 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/log/internal/proto.h",
|
||||
"dist/absl/log/internal/strip.h",
|
||||
"dist/absl/log/internal/structured.h",
|
||||
"dist/absl/log/internal/structured_proto.h",
|
||||
"dist/absl/log/internal/test_actions.h",
|
||||
"dist/absl/log/internal/test_helpers.h",
|
||||
"dist/absl/log/internal/test_matchers.h",
|
||||
"dist/absl/log/internal/vlog_config.h",
|
||||
"dist/absl/log/internal/voidify.h",
|
||||
"dist/absl/log/log.h",
|
||||
"dist/absl/log/log_basic_test_impl.inc",
|
||||
"dist/absl/log/log_entry.h",
|
||||
"dist/absl/log/log_sink.h",
|
||||
"dist/absl/log/log_sink_registry.h",
|
||||
"dist/absl/log/log_streamer.h",
|
||||
"dist/absl/log/scoped_mock_log.h",
|
||||
"dist/absl/log/structured.h",
|
||||
"dist/absl/log/vlog_is_on.h",
|
||||
"dist/absl/memory/memory.h",
|
||||
"dist/absl/meta/type_traits.h",
|
||||
"dist/absl/numeric/bits.h",
|
||||
|
|
@ -228,6 +241,7 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/random/internal/chi_square.h",
|
||||
"dist/absl/random/internal/distribution_caller.h",
|
||||
"dist/absl/random/internal/distribution_test_util.h",
|
||||
"dist/absl/random/internal/entropy_pool.h",
|
||||
"dist/absl/random/internal/explicit_seed_seq.h",
|
||||
"dist/absl/random/internal/fast_uniform_bits.h",
|
||||
"dist/absl/random/internal/fastmath.h",
|
||||
|
|
@ -235,11 +249,11 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/random/internal/iostream_state_saver.h",
|
||||
"dist/absl/random/internal/mock_helpers.h",
|
||||
"dist/absl/random/internal/mock_overload_set.h",
|
||||
"dist/absl/random/internal/mock_validators.h",
|
||||
"dist/absl/random/internal/nanobenchmark.h",
|
||||
"dist/absl/random/internal/nonsecure_base.h",
|
||||
"dist/absl/random/internal/pcg_engine.h",
|
||||
"dist/absl/random/internal/platform.h",
|
||||
"dist/absl/random/internal/pool_urbg.h",
|
||||
"dist/absl/random/internal/randen.h",
|
||||
"dist/absl/random/internal/randen_detect.h",
|
||||
"dist/absl/random/internal/randen_engine.h",
|
||||
|
|
@ -263,19 +277,23 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/random/uniform_real_distribution.h",
|
||||
"dist/absl/random/zipf_distribution.h",
|
||||
"dist/absl/status/internal/status_internal.h",
|
||||
"dist/absl/status/internal/status_matchers.h",
|
||||
"dist/absl/status/internal/statusor_internal.h",
|
||||
"dist/absl/status/status.h",
|
||||
"dist/absl/status/status_matchers.h",
|
||||
"dist/absl/status/status_payload_printer.h",
|
||||
"dist/absl/status/statusor.h",
|
||||
"dist/absl/strings/ascii.h",
|
||||
"dist/absl/strings/charconv.h",
|
||||
"dist/absl/strings/charset.h",
|
||||
"dist/absl/strings/cord.h",
|
||||
"dist/absl/strings/cord_analysis.h",
|
||||
"dist/absl/strings/cord_buffer.h",
|
||||
"dist/absl/strings/cord_test_helpers.h",
|
||||
"dist/absl/strings/cordz_test_helpers.h",
|
||||
"dist/absl/strings/escaping.h",
|
||||
"dist/absl/strings/internal/char_map.h",
|
||||
"dist/absl/strings/has_absl_stringify.h",
|
||||
"dist/absl/strings/has_ostream_operator.h",
|
||||
"dist/absl/strings/internal/charconv_bigint.h",
|
||||
"dist/absl/strings/internal/charconv_parse.h",
|
||||
"dist/absl/strings/internal/cord_data_edge.h",
|
||||
|
|
@ -286,8 +304,6 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/strings/internal/cord_rep_consume.h",
|
||||
"dist/absl/strings/internal/cord_rep_crc.h",
|
||||
"dist/absl/strings/internal/cord_rep_flat.h",
|
||||
"dist/absl/strings/internal/cord_rep_ring.h",
|
||||
"dist/absl/strings/internal/cord_rep_ring_reader.h",
|
||||
"dist/absl/strings/internal/cord_rep_test_util.h",
|
||||
"dist/absl/strings/internal/cordz_functions.h",
|
||||
"dist/absl/strings/internal/cordz_handle.h",
|
||||
|
|
@ -299,7 +315,6 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/strings/internal/damerau_levenshtein_distance.h",
|
||||
"dist/absl/strings/internal/escaping.h",
|
||||
"dist/absl/strings/internal/escaping_test_common.h",
|
||||
"dist/absl/strings/internal/has_absl_stringify.h",
|
||||
"dist/absl/strings/internal/memutil.h",
|
||||
"dist/absl/strings/internal/numbers_test_common.h",
|
||||
"dist/absl/strings/internal/ostringstream.h",
|
||||
|
|
@ -364,24 +379,11 @@ ABSEIL_HEADERS = [
|
|||
"dist/absl/time/internal/test_util.h",
|
||||
"dist/absl/time/time.h",
|
||||
"dist/absl/types/any.h",
|
||||
"dist/absl/types/bad_any_cast.h",
|
||||
"dist/absl/types/bad_optional_access.h",
|
||||
"dist/absl/types/bad_variant_access.h",
|
||||
"dist/absl/types/compare.h",
|
||||
"dist/absl/types/internal/conformance_aliases.h",
|
||||
"dist/absl/types/internal/conformance_archetype.h",
|
||||
"dist/absl/types/internal/conformance_profile.h",
|
||||
"dist/absl/types/internal/conformance_testing.h",
|
||||
"dist/absl/types/internal/conformance_testing_helpers.h",
|
||||
"dist/absl/types/internal/optional.h",
|
||||
"dist/absl/types/internal/parentheses.h",
|
||||
"dist/absl/types/internal/span.h",
|
||||
"dist/absl/types/internal/transform_args.h",
|
||||
"dist/absl/types/internal/variant.h",
|
||||
"dist/absl/types/optional.h",
|
||||
"dist/absl/types/span.h",
|
||||
"dist/absl/types/variant.h",
|
||||
"dist/absl/utility/internal/if_constexpr.h",
|
||||
"dist/absl/utility/utility.h",
|
||||
]
|
||||
|
||||
|
|
@ -395,7 +397,6 @@ mongo_cc_library(
|
|||
"@com_google_absl//absl/base:config",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/base:dynamic_annotations",
|
||||
"@com_google_absl//absl/base:endian",
|
||||
"@com_google_absl//absl/base:log_severity",
|
||||
"@com_google_absl//absl/base:malloc_internal",
|
||||
"@com_google_absl//absl/base:nullability",
|
||||
|
|
@ -473,14 +474,10 @@ mongo_cc_library(
|
|||
"@com_google_absl//absl/time/internal/cctz:civil_time",
|
||||
"@com_google_absl//absl/time/internal/cctz:time_zone",
|
||||
"@com_google_absl//absl/types:any",
|
||||
"@com_google_absl//absl/types:bad_any_cast",
|
||||
"@com_google_absl//absl/types:bad_optional_access",
|
||||
"@com_google_absl//absl/types:bad_variant_access",
|
||||
"@com_google_absl//absl/types:compare",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
"@com_google_absl//absl/types:span",
|
||||
"@com_google_absl//absl/types:variant",
|
||||
"@com_google_absl//absl/utility:if_constexpr",
|
||||
"@com_google_absl//absl/utility:utility",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
|
|
@ -618,8 +615,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -715,7 +710,7 @@ mongo_cc_library(
|
|||
srcs = [
|
||||
"dist/absl/crc/crc32c.cc",
|
||||
"dist/absl/crc/internal/crc_memcpy_fallback.cc",
|
||||
"dist/absl/crc/internal/crc_memcpy_x86_64.cc",
|
||||
"dist/absl/crc/internal/crc_memcpy_x86_arm_combined.cc",
|
||||
"dist/absl/crc/internal/crc_non_temporal_memcpy.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
|
|
@ -866,7 +861,10 @@ mongo_cc_library(
|
|||
mongo_cc_library(
|
||||
name = "absl_demangle_internal",
|
||||
srcs = [
|
||||
"dist/absl/debugging/internal/decode_rust_punycode.cc",
|
||||
"dist/absl/debugging/internal/demangle.cc",
|
||||
"dist/absl/debugging/internal/demangle_rust.cc",
|
||||
"dist/absl/debugging/internal/utf8_for_code_point.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
|
|
@ -962,7 +960,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_int128",
|
||||
":absl_log_severity",
|
||||
|
|
@ -976,65 +973,6 @@ mongo_cc_library(
|
|||
],
|
||||
)
|
||||
|
||||
# absl_flags is an explicit dependency to the server build
|
||||
mongo_cc_library(
|
||||
name = "absl_flags",
|
||||
srcs = [
|
||||
"dist/absl/flags/flag.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
":absl_cord",
|
||||
":absl_cord_internal",
|
||||
":absl_cordz_functions",
|
||||
":absl_cordz_handle",
|
||||
":absl_cordz_info",
|
||||
":absl_crc32c",
|
||||
":absl_crc_cord_state",
|
||||
":absl_crc_cpu_detect",
|
||||
":absl_crc_internal",
|
||||
":absl_debugging_internal",
|
||||
":absl_demangle_internal",
|
||||
":absl_exponential_biased",
|
||||
":absl_flags_commandlineflag",
|
||||
":absl_flags_commandlineflag_internal",
|
||||
":absl_flags_config",
|
||||
":absl_flags_internal",
|
||||
":absl_flags_marshalling",
|
||||
":absl_flags_private_handle_accessor",
|
||||
":absl_flags_program_name",
|
||||
":absl_flags_reflection",
|
||||
":absl_graphcycles_internal",
|
||||
":absl_hash",
|
||||
":absl_hashtablez_sampler",
|
||||
":absl_int128",
|
||||
":absl_kernel_timeout_internal",
|
||||
":absl_log_severity",
|
||||
":absl_low_level_hash",
|
||||
":absl_malloc_internal",
|
||||
":absl_raw_hash_set",
|
||||
":absl_raw_logging_internal",
|
||||
":absl_spinlock_wait",
|
||||
":absl_stacktrace",
|
||||
":absl_str_format_internal",
|
||||
":absl_string_view",
|
||||
":absl_strings",
|
||||
":absl_strings_internal",
|
||||
":absl_symbolize",
|
||||
":absl_synchronization",
|
||||
":absl_throw_delegate",
|
||||
":absl_time",
|
||||
":absl_time_zone",
|
||||
],
|
||||
)
|
||||
|
||||
# absl_flags_private_handle_accessor added as a dependency of other abseil libraries
|
||||
mongo_cc_library(
|
||||
name = "absl_flags_private_handle_accessor",
|
||||
|
|
@ -1045,7 +983,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_flags_commandlineflag",
|
||||
":absl_flags_commandlineflag_internal",
|
||||
|
|
@ -1081,7 +1018,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_flags_commandlineflag_internal",
|
||||
":absl_int128",
|
||||
|
|
@ -1138,8 +1074,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1194,7 +1128,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_civil_time",
|
||||
":absl_debugging_internal",
|
||||
|
|
@ -1234,8 +1167,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1251,7 +1182,6 @@ mongo_cc_library(
|
|||
":absl_debugging_internal",
|
||||
":absl_demangle_internal",
|
||||
":absl_exponential_biased",
|
||||
":absl_flags",
|
||||
":absl_flags_commandlineflag",
|
||||
":absl_flags_commandlineflag_internal",
|
||||
":absl_flags_config",
|
||||
|
|
@ -1295,8 +1225,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1312,7 +1240,6 @@ mongo_cc_library(
|
|||
":absl_debugging_internal",
|
||||
":absl_demangle_internal",
|
||||
":absl_exponential_biased",
|
||||
":absl_flags",
|
||||
":absl_flags_commandlineflag",
|
||||
":absl_flags_commandlineflag_internal",
|
||||
":absl_flags_config",
|
||||
|
|
@ -1355,8 +1282,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1372,7 +1297,6 @@ mongo_cc_library(
|
|||
":absl_debugging_internal",
|
||||
":absl_demangle_internal",
|
||||
":absl_exponential_biased",
|
||||
":absl_flags",
|
||||
":absl_flags_commandlineflag",
|
||||
":absl_flags_commandlineflag_internal",
|
||||
":absl_flags_config",
|
||||
|
|
@ -1452,8 +1376,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_int128",
|
||||
|
|
@ -1478,8 +1400,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1490,7 +1410,6 @@ mongo_cc_library(
|
|||
":absl_hash",
|
||||
":absl_int128",
|
||||
":absl_kernel_timeout_internal",
|
||||
":absl_log_entry",
|
||||
":absl_log_globals",
|
||||
":absl_log_internal_conditions",
|
||||
":absl_log_internal_format",
|
||||
|
|
@ -1524,13 +1443,12 @@ mongo_cc_library(
|
|||
name = "absl_log_internal_message",
|
||||
srcs = [
|
||||
"dist/absl/log/internal/log_message.cc",
|
||||
"dist/absl/log/internal/structured_proto.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1541,7 +1459,6 @@ mongo_cc_library(
|
|||
":absl_hash",
|
||||
":absl_int128",
|
||||
":absl_kernel_timeout_internal",
|
||||
":absl_log_entry",
|
||||
":absl_log_globals",
|
||||
":absl_log_internal_format",
|
||||
":absl_log_internal_globals",
|
||||
|
|
@ -1614,8 +1531,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1625,7 +1540,6 @@ mongo_cc_library(
|
|||
":absl_hash",
|
||||
":absl_int128",
|
||||
":absl_kernel_timeout_internal",
|
||||
":absl_log_entry",
|
||||
":absl_log_globals",
|
||||
":absl_log_internal_globals",
|
||||
":absl_log_severity",
|
||||
|
|
@ -1668,31 +1582,6 @@ mongo_cc_library(
|
|||
],
|
||||
)
|
||||
|
||||
# absl_log_entry added as a dependency of other abseil libraries
|
||||
mongo_cc_library(
|
||||
name = "absl_log_entry",
|
||||
srcs = [
|
||||
"dist/absl/log/log_entry.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_base",
|
||||
":absl_civil_time",
|
||||
":absl_int128",
|
||||
":absl_log_severity",
|
||||
":absl_raw_logging_internal",
|
||||
":absl_spinlock_wait",
|
||||
":absl_string_view",
|
||||
":absl_strings",
|
||||
":absl_strings_internal",
|
||||
":absl_throw_delegate",
|
||||
":absl_time",
|
||||
":absl_time_zone",
|
||||
],
|
||||
)
|
||||
|
||||
# absl_log_internal_format added as a dependency of other abseil libraries
|
||||
mongo_cc_library(
|
||||
name = "absl_log_internal_format",
|
||||
|
|
@ -1730,8 +1619,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1742,7 +1629,7 @@ mongo_cc_library(
|
|||
":absl_hash",
|
||||
":absl_int128",
|
||||
":absl_kernel_timeout_internal",
|
||||
":absl_log_entry",
|
||||
":absl_leak_check",
|
||||
":absl_log_globals",
|
||||
":absl_log_internal_format",
|
||||
":absl_log_internal_globals",
|
||||
|
|
@ -1797,8 +1684,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1832,7 +1717,6 @@ mongo_cc_library(
|
|||
":absl_base",
|
||||
":absl_civil_time",
|
||||
":absl_int128",
|
||||
":absl_log_entry",
|
||||
":absl_log_severity",
|
||||
":absl_raw_logging_internal",
|
||||
":absl_spinlock_wait",
|
||||
|
|
@ -1855,8 +1739,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_hash",
|
||||
|
|
@ -1877,13 +1759,13 @@ mongo_cc_library(
|
|||
name = "absl_log_flags",
|
||||
srcs = [
|
||||
"dist/absl/log/flags.cc",
|
||||
"dist/absl/log/internal/fnmatch.cc",
|
||||
"dist/absl/log/internal/vlog_config.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_city",
|
||||
":absl_civil_time",
|
||||
|
|
@ -1899,7 +1781,6 @@ mongo_cc_library(
|
|||
":absl_debugging_internal",
|
||||
":absl_demangle_internal",
|
||||
":absl_exponential_biased",
|
||||
":absl_flags",
|
||||
":absl_flags_commandlineflag",
|
||||
":absl_flags_commandlineflag_internal",
|
||||
":absl_flags_config",
|
||||
|
|
@ -1994,7 +1875,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_int128",
|
||||
":absl_log_severity",
|
||||
|
|
@ -2032,36 +1912,6 @@ mongo_cc_library(
|
|||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
)
|
||||
|
||||
# absl_random_internal_pool_urbg is an explicit dependency to the server build
|
||||
mongo_cc_library(
|
||||
name = "absl_random_internal_pool_urbg",
|
||||
srcs = [
|
||||
"dist/absl/random/internal/pool_urbg.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_int128",
|
||||
":absl_log_severity",
|
||||
":absl_random_internal_platform",
|
||||
":absl_random_internal_randen",
|
||||
":absl_random_internal_randen_hwaes",
|
||||
":absl_random_internal_randen_hwaes_impl",
|
||||
":absl_random_internal_randen_slow",
|
||||
":absl_random_internal_seed_material",
|
||||
":absl_random_seed_gen_exception",
|
||||
":absl_raw_logging_internal",
|
||||
":absl_spinlock_wait",
|
||||
":absl_string_view",
|
||||
":absl_strings",
|
||||
":absl_strings_internal",
|
||||
":absl_throw_delegate",
|
||||
],
|
||||
)
|
||||
|
||||
# absl_random_distributions is an explicit dependency to the server build
|
||||
mongo_cc_library(
|
||||
name = "absl_random_distributions",
|
||||
|
|
@ -2107,18 +1957,17 @@ mongo_cc_library(
|
|||
mongo_cc_library(
|
||||
name = "absl_random_seed_sequences",
|
||||
srcs = [
|
||||
"dist/absl/random/internal/entropy_pool.cc",
|
||||
"dist/absl/random/seed_sequences.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_int128",
|
||||
":absl_log_severity",
|
||||
":absl_random_internal_platform",
|
||||
":absl_random_internal_pool_urbg",
|
||||
":absl_random_internal_randen",
|
||||
":absl_random_internal_randen_hwaes",
|
||||
":absl_random_internal_randen_hwaes_impl",
|
||||
|
|
@ -2196,8 +2045,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_bad_variant_access",
|
||||
":absl_base",
|
||||
":absl_civil_time",
|
||||
":absl_cord",
|
||||
|
|
@ -2238,6 +2085,7 @@ mongo_cc_library(
|
|||
mongo_cc_library(
|
||||
name = "absl_status",
|
||||
srcs = [
|
||||
"dist/absl/status/internal/status_internal.cc",
|
||||
"dist/absl/status/status.cc",
|
||||
"dist/absl/status/status_payload_printer.cc",
|
||||
],
|
||||
|
|
@ -2245,7 +2093,6 @@ mongo_cc_library(
|
|||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_civil_time",
|
||||
":absl_cord",
|
||||
|
|
@ -2263,6 +2110,7 @@ mongo_cc_library(
|
|||
":absl_graphcycles_internal",
|
||||
":absl_int128",
|
||||
":absl_kernel_timeout_internal",
|
||||
":absl_leak_check",
|
||||
":absl_log_severity",
|
||||
":absl_malloc_internal",
|
||||
":absl_raw_logging_internal",
|
||||
|
|
@ -2287,13 +2135,11 @@ mongo_cc_library(
|
|||
srcs = [
|
||||
"dist/absl/strings/cord.cc",
|
||||
"dist/absl/strings/cord_analysis.cc",
|
||||
"dist/absl/strings/cord_buffer.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_bad_optional_access",
|
||||
":absl_base",
|
||||
":absl_civil_time",
|
||||
":absl_cord_internal",
|
||||
|
|
@ -2470,7 +2316,6 @@ mongo_cc_library(
|
|||
"dist/absl/strings/internal/cord_rep_btree_reader.cc",
|
||||
"dist/absl/strings/internal/cord_rep_consume.cc",
|
||||
"dist/absl/strings/internal/cord_rep_crc.cc",
|
||||
"dist/absl/strings/internal/cord_rep_ring.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
|
|
@ -2600,6 +2445,7 @@ mongo_cc_library(
|
|||
mongo_cc_library(
|
||||
name = "absl_synchronization",
|
||||
srcs = [
|
||||
"dist/absl/base/internal/tracing.cc",
|
||||
"dist/absl/synchronization/barrier.cc",
|
||||
"dist/absl/synchronization/blocking_counter.cc",
|
||||
"dist/absl/synchronization/internal/create_thread_identity.cc",
|
||||
|
|
@ -2739,48 +2585,3 @@ mongo_cc_library(
|
|||
":absl_time_zone",
|
||||
],
|
||||
)
|
||||
|
||||
# absl_bad_any_cast_impl added as a dependency of other abseil libraries
|
||||
mongo_cc_library(
|
||||
name = "absl_bad_any_cast_impl",
|
||||
srcs = [
|
||||
"dist/absl/types/bad_any_cast.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_log_severity",
|
||||
":absl_raw_logging_internal",
|
||||
],
|
||||
)
|
||||
|
||||
# absl_bad_optional_access is an explicit dependency to the server build
|
||||
mongo_cc_library(
|
||||
name = "absl_bad_optional_access",
|
||||
srcs = [
|
||||
"dist/absl/types/bad_optional_access.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_log_severity",
|
||||
":absl_raw_logging_internal",
|
||||
],
|
||||
)
|
||||
|
||||
# absl_bad_variant_access is an explicit dependency to the server build
|
||||
mongo_cc_library(
|
||||
name = "absl_bad_variant_access",
|
||||
srcs = [
|
||||
"dist/absl/types/bad_variant_access.cc",
|
||||
],
|
||||
hdrs = ABSEIL_HEADERS,
|
||||
includes = ["dist"],
|
||||
skip_global_deps = ABSEIL_SKIP_GLOBAL_DEPS,
|
||||
deps = [
|
||||
":absl_log_severity",
|
||||
":absl_raw_logging_internal",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#
|
||||
# Copyright 2020 The Abseil Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -23,3 +22,14 @@ exports_files([
|
|||
"AUTHORS",
|
||||
"LICENSE",
|
||||
])
|
||||
|
||||
# For building with clang-cl.
|
||||
# https://bazel.build/configure/windows#clang
|
||||
platform(
|
||||
name = "x64_windows-clang-cl",
|
||||
constraint_values = [
|
||||
"@platforms//cpu:x86_64",
|
||||
"@platforms//os:windows",
|
||||
"@bazel_tools//tools/cpp:clang-cl",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"base/config.h"
|
||||
"base/const_init.h"
|
||||
"base/dynamic_annotations.h"
|
||||
"base/fast_type_id.h"
|
||||
"base/internal/atomic_hook.h"
|
||||
"base/internal/cycleclock.cc"
|
||||
"base/internal/cycleclock.h"
|
||||
|
|
@ -18,17 +19,16 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"base/internal/dynamic_annotations.h"
|
||||
"base/internal/endian.h"
|
||||
"base/internal/errno_saver.h"
|
||||
"base/internal/fast_type_id.h"
|
||||
"base/internal/hide_ptr.h"
|
||||
"base/internal/identity.h"
|
||||
"base/internal/invoke.h"
|
||||
"base/internal/inline_variable.h"
|
||||
"base/internal/iterator_traits.h"
|
||||
"base/internal/low_level_alloc.cc"
|
||||
"base/internal/low_level_alloc.h"
|
||||
"base/internal/low_level_scheduling.h"
|
||||
"base/internal/nullability_impl.h"
|
||||
"base/internal/nullability_deprecated.h"
|
||||
"base/internal/per_thread_tls.h"
|
||||
"base/internal/prefetch.h"
|
||||
"base/internal/poison.cc"
|
||||
"base/internal/poison.h"
|
||||
"base/prefetch.h"
|
||||
"base/internal/pretty_function.h"
|
||||
"base/internal/raw_logging.cc"
|
||||
|
|
@ -44,11 +44,12 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"base/internal/spinlock_wait.h"
|
||||
"base/internal/sysinfo.cc"
|
||||
"base/internal/sysinfo.h"
|
||||
"base/internal/thread_annotations.h"
|
||||
"base/internal/thread_identity.cc"
|
||||
"base/internal/thread_identity.h"
|
||||
"base/internal/throw_delegate.cc"
|
||||
"base/internal/throw_delegate.h"
|
||||
"base/internal/tracing.cc"
|
||||
"base/internal/tracing.h"
|
||||
"base/internal/tsan_mutex_interface.h"
|
||||
"base/internal/unaligned_access.h"
|
||||
"base/internal/unscaledcycleclock.cc"
|
||||
|
|
@ -57,6 +58,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"base/log_severity.cc"
|
||||
"base/log_severity.h"
|
||||
"base/macros.h"
|
||||
"base/no_destructor.h"
|
||||
"base/nullability.h"
|
||||
"base/optimization.h"
|
||||
"base/options.h"
|
||||
|
|
@ -67,6 +69,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"cleanup/internal/cleanup.h"
|
||||
"container/btree_map.h"
|
||||
"container/btree_set.h"
|
||||
"container/hash_container_defaults.h"
|
||||
"container/fixed_array.h"
|
||||
"container/flat_hash_map.h"
|
||||
"container/flat_hash_set.h"
|
||||
|
|
@ -77,9 +80,9 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"container/internal/common_policy_traits.h"
|
||||
"container/internal/compressed_tuple.h"
|
||||
"container/internal/container_memory.h"
|
||||
"container/internal/counting_allocator.h"
|
||||
"container/internal/hash_function_defaults.h"
|
||||
"container/internal/hash_policy_traits.h"
|
||||
"container/internal/hashtable_control_bytes.h"
|
||||
"container/internal/hashtable_debug.h"
|
||||
"container/internal/hashtable_debug_hooks.h"
|
||||
"container/internal/hashtablez_sampler.cc"
|
||||
|
|
@ -91,6 +94,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"container/internal/raw_hash_map.h"
|
||||
"container/internal/raw_hash_set.cc"
|
||||
"container/internal/raw_hash_set.h"
|
||||
"container/internal/raw_hash_set_resize_impl.h"
|
||||
"container/internal/tracked.h"
|
||||
"container/node_hash_map.h"
|
||||
"container/node_hash_set.h"
|
||||
|
|
@ -109,7 +113,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"crc/internal/crc_x86_arm_combined.cc"
|
||||
"crc/internal/crc_memcpy_fallback.cc"
|
||||
"crc/internal/crc_memcpy.h"
|
||||
"crc/internal/crc_memcpy_x86_64.cc"
|
||||
"crc/internal/crc_memcpy_x86_arm_combined.cc"
|
||||
"crc/internal/crc_non_temporal_memcpy.cc"
|
||||
"crc/internal/crc_x86_arm_combined.cc"
|
||||
"crc/internal/non_temporal_arm_intrinsics.h"
|
||||
|
|
@ -123,8 +127,14 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"debugging/symbolize.h"
|
||||
"debugging/internal/address_is_readable.cc"
|
||||
"debugging/internal/address_is_readable.h"
|
||||
"debugging/internal/addresses.h"
|
||||
"debugging/internal/bounded_utf8_length_sequence.h"
|
||||
"debugging/internal/decode_rust_punycode.cc"
|
||||
"debugging/internal/decode_rust_punycode.h"
|
||||
"debugging/internal/demangle.cc"
|
||||
"debugging/internal/demangle.h"
|
||||
"debugging/internal/demangle_rust.cc"
|
||||
"debugging/internal/demangle_rust.h"
|
||||
"debugging/internal/elf_mem_image.cc"
|
||||
"debugging/internal/elf_mem_image.h"
|
||||
"debugging/internal/examine_stack.cc"
|
||||
|
|
@ -133,6 +143,8 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"debugging/internal/stack_consumption.h"
|
||||
"debugging/internal/stacktrace_config.h"
|
||||
"debugging/internal/symbolize.h"
|
||||
"debugging/internal/utf8_for_code_point.cc"
|
||||
"debugging/internal/utf8_for_code_point.h"
|
||||
"debugging/internal/vdso_support.cc"
|
||||
"debugging/internal/vdso_support.h"
|
||||
"functional/any_invocable.h"
|
||||
|
|
@ -141,6 +153,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"functional/function_ref.h"
|
||||
"functional/internal/any_invocable.h"
|
||||
"functional/internal/function_ref.h"
|
||||
"functional/overload.h"
|
||||
"hash/hash.h"
|
||||
"hash/internal/city.h"
|
||||
"hash/internal/city.cc"
|
||||
|
|
@ -149,8 +162,10 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"hash/internal/spy_hash_state.h"
|
||||
"hash/internal/low_level_hash.h"
|
||||
"hash/internal/low_level_hash.cc"
|
||||
"hash/internal/weakly_mixed_integer.h"
|
||||
"log/absl_check.h"
|
||||
"log/absl_log.h"
|
||||
"log/absl_vlog_is_on.h"
|
||||
"log/check.h"
|
||||
"log/die_if_null.cc"
|
||||
"log/die_if_null.h"
|
||||
|
|
@ -163,6 +178,8 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"log/internal/conditions.cc"
|
||||
"log/internal/conditions.h"
|
||||
"log/internal/config.h"
|
||||
"log/internal/fnmatch.h"
|
||||
"log/internal/fnmatch.cc"
|
||||
"log/internal/globals.cc"
|
||||
"log/internal/globals.h"
|
||||
"log/internal/log_format.cc"
|
||||
|
|
@ -179,17 +196,21 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"log/internal/proto.cc"
|
||||
"log/internal/strip.h"
|
||||
"log/internal/structured.h"
|
||||
"log/internal/structured_proto.cc"
|
||||
"log/internal/structured_proto.h"
|
||||
"log/internal/vlog_config.cc"
|
||||
"log/internal/vlog_config.h"
|
||||
"log/internal/voidify.h"
|
||||
"log/initialize.cc"
|
||||
"log/initialize.h"
|
||||
"log/log.h"
|
||||
"log/log_entry.cc"
|
||||
"log/log_entry.h"
|
||||
"log/log_sink.cc"
|
||||
"log/log_sink.h"
|
||||
"log/log_sink_registry.h"
|
||||
"log/log_streamer.h"
|
||||
"log/structured.h"
|
||||
"log/vlog_is_on.h"
|
||||
"memory/memory.h"
|
||||
"meta/type_traits.h"
|
||||
"numeric/bits.h"
|
||||
|
|
@ -219,8 +240,8 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"random/internal/nonsecure_base.h"
|
||||
"random/internal/pcg_engine.h"
|
||||
"random/internal/platform.h"
|
||||
"random/internal/pool_urbg.cc"
|
||||
"random/internal/pool_urbg.h"
|
||||
"random/internal/entropy_pool.cc"
|
||||
"random/internal/entropy_pool.h"
|
||||
"random/internal/randen.cc"
|
||||
"random/internal/randen.h"
|
||||
"random/internal/randen_detect.cc"
|
||||
|
|
@ -250,6 +271,7 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"random/uniform_real_distribution.h"
|
||||
"random/zipf_distribution.h"
|
||||
"status/internal/status_internal.h"
|
||||
"status/internal/status_internal.cc"
|
||||
"status/internal/statusor_internal.h"
|
||||
"status/status.h"
|
||||
"status/status.cc"
|
||||
|
|
@ -261,11 +283,11 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"strings/ascii.h"
|
||||
"strings/charconv.cc"
|
||||
"strings/charconv.h"
|
||||
"strings/charset.h"
|
||||
"strings/cord.cc"
|
||||
"strings/cord.h"
|
||||
"strings/cord_analysis.cc"
|
||||
"strings/cord_analysis.h"
|
||||
"strings/cord_buffer.cc"
|
||||
"strings/cord_buffer.h"
|
||||
"strings/escaping.cc"
|
||||
"strings/escaping.h"
|
||||
|
|
@ -287,9 +309,6 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"strings/internal/cord_rep_consume.h"
|
||||
"strings/internal/cord_rep_consume.cc"
|
||||
"strings/internal/cord_rep_flat.h"
|
||||
"strings/internal/cord_rep_ring.cc"
|
||||
"strings/internal/cord_rep_ring.h"
|
||||
"strings/internal/cord_rep_ring_reader.h"
|
||||
"strings/internal/cordz_functions.cc"
|
||||
"strings/internal/cordz_functions.h"
|
||||
"strings/internal/cordz_handle.cc"
|
||||
|
|
@ -307,7 +326,8 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"strings/internal/string_constant.h"
|
||||
"strings/internal/stringify_sink.h"
|
||||
"strings/internal/stringify_sink.cc"
|
||||
"strings/internal/has_absl_stringify.h"
|
||||
"strings/has_absl_stringify.h"
|
||||
"strings/has_ostream_operator.h"
|
||||
"strings/match.cc"
|
||||
"strings/match.h"
|
||||
"strings/numbers.cc"
|
||||
|
|
@ -325,7 +345,6 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"strings/strip.h"
|
||||
"strings/substitute.cc"
|
||||
"strings/substitute.h"
|
||||
"strings/internal/char_map.h"
|
||||
"strings/internal/escaping.h"
|
||||
"strings/internal/escaping.cc"
|
||||
"strings/internal/memutil.cc"
|
||||
|
|
@ -414,41 +433,61 @@ set(ABSL_INTERNAL_DLL_FILES
|
|||
"time/internal/cctz/src/tzfile.h"
|
||||
"time/internal/cctz/src/zone_info_source.cc"
|
||||
"types/any.h"
|
||||
"types/bad_any_cast.cc"
|
||||
"types/bad_any_cast.h"
|
||||
"types/bad_optional_access.cc"
|
||||
"types/bad_optional_access.h"
|
||||
"types/bad_variant_access.cc"
|
||||
"types/bad_variant_access.h"
|
||||
"types/compare.h"
|
||||
"types/internal/conformance_aliases.h"
|
||||
"types/internal/conformance_archetype.h"
|
||||
"types/internal/conformance_profile.h"
|
||||
"types/internal/parentheses.h"
|
||||
"types/internal/transform_args.h"
|
||||
"types/internal/variant.h"
|
||||
"types/optional.h"
|
||||
"types/internal/optional.h"
|
||||
"types/span.h"
|
||||
"types/internal/span.h"
|
||||
"types/variant.h"
|
||||
"utility/internal/if_constexpr.h"
|
||||
"utility/utility.h"
|
||||
"debugging/leak_check.cc"
|
||||
)
|
||||
|
||||
if(NOT MSVC)
|
||||
list(APPEND ABSL_INTERNAL_DLL_FILES
|
||||
"flags/commandlineflag.cc"
|
||||
"flags/commandlineflag.h"
|
||||
"flags/config.h"
|
||||
"flags/declare.h"
|
||||
"flags/flag.h"
|
||||
"flags/internal/commandlineflag.cc"
|
||||
"flags/internal/commandlineflag.h"
|
||||
"flags/internal/flag.cc"
|
||||
"flags/internal/flag.h"
|
||||
"flags/internal/parse.h"
|
||||
"flags/internal/path_util.h"
|
||||
"flags/internal/private_handle_accessor.cc"
|
||||
"flags/internal/private_handle_accessor.h"
|
||||
"flags/internal/program_name.cc"
|
||||
"flags/internal/program_name.h"
|
||||
"flags/internal/registry.h"
|
||||
"flags/internal/sequence_lock.h"
|
||||
"flags/internal/usage.cc"
|
||||
"flags/internal/usage.h"
|
||||
"flags/marshalling.cc"
|
||||
"flags/marshalling.h"
|
||||
"flags/parse.cc"
|
||||
"flags/parse.h"
|
||||
"flags/reflection.cc"
|
||||
"flags/reflection.h"
|
||||
"flags/usage.cc"
|
||||
"flags/usage.h"
|
||||
"flags/usage_config.cc"
|
||||
"flags/usage_config.h"
|
||||
"log/flags.cc"
|
||||
"log/flags.h"
|
||||
"log/internal/flags.h"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(ABSL_INTERNAL_DLL_TARGETS
|
||||
"absl_check"
|
||||
"absl_log"
|
||||
"absl_vlog_is_on"
|
||||
"algorithm"
|
||||
"algorithm_container"
|
||||
"any"
|
||||
"any_invocable"
|
||||
"atomic_hook"
|
||||
"bad_any_cast"
|
||||
"bad_any_cast_impl"
|
||||
"bad_optional_access"
|
||||
"bad_variant_access"
|
||||
"base"
|
||||
"base_internal"
|
||||
"bind_front"
|
||||
|
|
@ -505,6 +544,7 @@ set(ABSL_INTERNAL_DLL_TARGETS
|
|||
"log_internal_check_op"
|
||||
"log_internal_conditions"
|
||||
"log_internal_config"
|
||||
"log_internal_fnmatch"
|
||||
"log_internal_format"
|
||||
"log_internal_globals"
|
||||
"log_internal_log_impl"
|
||||
|
|
@ -584,6 +624,7 @@ set(ABSL_INTERNAL_DLL_TARGETS
|
|||
"strerror"
|
||||
"strings"
|
||||
"strings_internal"
|
||||
"string_view"
|
||||
"symbolize"
|
||||
"synchronization"
|
||||
"thread_pool"
|
||||
|
|
@ -594,8 +635,30 @@ set(ABSL_INTERNAL_DLL_TARGETS
|
|||
"type_traits"
|
||||
"utility"
|
||||
"variant"
|
||||
"vlog_config_internal"
|
||||
"vlog_is_on"
|
||||
)
|
||||
|
||||
if(NOT MSVC)
|
||||
list(APPEND ABSL_INTERNAL_DLL_TARGETS
|
||||
"flags"
|
||||
"flags_commandlineflag"
|
||||
"flags_commandlineflag_internal"
|
||||
"flags_config"
|
||||
"flags_internal"
|
||||
"flags_marshalling"
|
||||
"flags_parse"
|
||||
"flags_path_util"
|
||||
"flags_private_handle_accessor"
|
||||
"flags_program_name"
|
||||
"flags_reflection"
|
||||
"flags_usage"
|
||||
"flags_usage_internal"
|
||||
"log_internal_flags"
|
||||
"log_flags"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(ABSL_INTERNAL_TEST_DLL_FILES
|
||||
"hash/hash_testing.h"
|
||||
"log/scoped_mock_log.cc"
|
||||
|
|
@ -608,6 +671,9 @@ set(ABSL_INTERNAL_TEST_DLL_FILES
|
|||
"random/internal/mock_overload_set.h"
|
||||
"random/mocking_bit_gen.h"
|
||||
"random/mock_distributions.h"
|
||||
"status/status_matchers.h"
|
||||
"status/internal/status_matchers.cc"
|
||||
"status/internal/status_matchers.h"
|
||||
"strings/cordz_test_helpers.h"
|
||||
"strings/cord_test_helpers.h"
|
||||
)
|
||||
|
|
@ -620,6 +686,7 @@ set(ABSL_INTERNAL_TEST_DLL_TARGETS
|
|||
"random_internal_distribution_test_util"
|
||||
"random_internal_mock_overload_set"
|
||||
"scoped_mock_log"
|
||||
"status_matchers"
|
||||
)
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
|
@ -627,20 +694,33 @@ include(CheckCXXSourceCompiles)
|
|||
check_cxx_source_compiles(
|
||||
[==[
|
||||
#ifdef _MSC_VER
|
||||
# if _MSVC_LANG < 201700L
|
||||
# if _MSVC_LANG < 201703L
|
||||
# error "The compiler defaults or is configured for C++ < 17"
|
||||
# endif
|
||||
#elif __cplusplus < 201700L
|
||||
#elif __cplusplus < 201703L
|
||||
# error "The compiler defaults or is configured for C++ < 17"
|
||||
#endif
|
||||
int main() { return 0; }
|
||||
]==]
|
||||
ABSL_INTERNAL_AT_LEAST_CXX17)
|
||||
|
||||
if(ABSL_INTERNAL_AT_LEAST_CXX17)
|
||||
set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17)
|
||||
check_cxx_source_compiles(
|
||||
[==[
|
||||
#ifdef _MSC_VER
|
||||
# if _MSVC_LANG < 202002L
|
||||
# error "The compiler defaults or is configured for C++ < 20"
|
||||
# endif
|
||||
#elif __cplusplus < 202002L
|
||||
# error "The compiler defaults or is configured for C++ < 20"
|
||||
#endif
|
||||
int main() { return 0; }
|
||||
]==]
|
||||
ABSL_INTERNAL_AT_LEAST_CXX20)
|
||||
|
||||
if(ABSL_INTERNAL_AT_LEAST_CXX20)
|
||||
set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_20)
|
||||
else()
|
||||
set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_14)
|
||||
set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17)
|
||||
endif()
|
||||
|
||||
function(absl_internal_dll_contains)
|
||||
|
|
@ -653,12 +733,7 @@ function(absl_internal_dll_contains)
|
|||
|
||||
STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_DLL_TARGET})
|
||||
|
||||
list(FIND
|
||||
ABSL_INTERNAL_DLL_TARGETS
|
||||
"${_target}"
|
||||
_index)
|
||||
|
||||
if (${_index} GREATER -1)
|
||||
if (_target IN_LIST ABSL_INTERNAL_DLL_TARGETS)
|
||||
set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE)
|
||||
else()
|
||||
set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE)
|
||||
|
|
@ -675,12 +750,7 @@ function(absl_internal_test_dll_contains)
|
|||
|
||||
STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_TEST_DLL_TARGET})
|
||||
|
||||
list(FIND
|
||||
ABSL_INTERNAL_TEST_DLL_TARGETS
|
||||
"${_target}"
|
||||
_index)
|
||||
|
||||
if (${_index} GREATER -1)
|
||||
if (_target IN_LIST ABSL_INTERNAL_TEST_DLL_TARGETS)
|
||||
set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 1 PARENT_SCOPE)
|
||||
else()
|
||||
set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 0 PARENT_SCOPE)
|
||||
|
|
@ -732,7 +802,12 @@ function(absl_make_dll)
|
|||
else()
|
||||
set(_dll "abseil_dll")
|
||||
set(_dll_files ${ABSL_INTERNAL_DLL_FILES})
|
||||
set(_dll_libs "")
|
||||
set(_dll_libs
|
||||
Threads::Threads
|
||||
# TODO(#1495): Use $<LINK_LIBRARY:FRAMEWORK,CoreFoundation> once our
|
||||
# minimum CMake version >= 3.24
|
||||
$<$<PLATFORM_ID:Darwin>:-Wl,-framework,CoreFoundation>
|
||||
)
|
||||
set(_dll_compile_definitions "")
|
||||
set(_dll_includes "")
|
||||
set(_dll_consume "ABSL_CONSUME_DLL")
|
||||
|
|
@ -749,8 +824,12 @@ function(absl_make_dll)
|
|||
PRIVATE
|
||||
${_dll_libs}
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
$<$<BOOL:${ANDROID}>:-llog>
|
||||
)
|
||||
set_target_properties(${_dll} PROPERTIES
|
||||
LINKER_LANGUAGE "CXX"
|
||||
SOVERSION ${ABSL_SOVERSION}
|
||||
)
|
||||
set_property(TARGET ${_dll} PROPERTY LINKER_LANGUAGE "CXX")
|
||||
target_include_directories(
|
||||
${_dll}
|
||||
PUBLIC
|
||||
|
|
@ -806,9 +885,9 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
|
|||
)
|
||||
|
||||
if(ABSL_PROPAGATE_CXX_STD)
|
||||
# Abseil libraries require C++14 as the current minimum standard. When
|
||||
# compiled with C++17 (either because it is the compiler's default or
|
||||
# explicitly requested), then Abseil requires C++17.
|
||||
# Abseil libraries require C++17 as the current minimum standard. When
|
||||
# compiled with a higher minimum (either because it is the compiler's
|
||||
# default or explicitly requested), then Abseil requires that standard.
|
||||
target_compile_features(${_dll} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ endif()
|
|||
# absl::fantastic_lib
|
||||
# )
|
||||
#
|
||||
# TODO: Implement "ALWAYSLINK"
|
||||
# TODO(b/320467376): Implement "ALWAYSLINK".
|
||||
function(absl_cc_library)
|
||||
cmake_parse_arguments(ABSL_CC_LIB
|
||||
"DISABLE_INSTALL;PUBLIC;TESTONLY"
|
||||
|
|
@ -187,7 +187,15 @@ function(absl_cc_library)
|
|||
endif()
|
||||
endforeach()
|
||||
foreach(cflag ${ABSL_CC_LIB_COPTS})
|
||||
if(${cflag} MATCHES "^(-Wno|/wd)")
|
||||
# Strip out the CMake-specific `SHELL:` prefix, which is used to construct
|
||||
# a group of space-separated options.
|
||||
# https://cmake.org/cmake/help/v3.30/command/target_compile_options.html#option-de-duplication
|
||||
string(REGEX REPLACE "^SHELL:" "" cflag "${cflag}")
|
||||
if(${cflag} MATCHES "^-Xarch_")
|
||||
# An -Xarch_ flag implies that its successor only applies to the
|
||||
# specified platform. Such option groups are each specified in a single
|
||||
# `SHELL:`-prefixed string in the COPTS list, which we simply ignore.
|
||||
elseif(${cflag} MATCHES "^(-Wno-|/wd)")
|
||||
# These flags are needed to suppress warnings that might fire in our headers.
|
||||
set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
|
||||
elseif(${cflag} MATCHES "^(-W|/w[1234eo])")
|
||||
|
|
@ -250,6 +258,13 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
|
|||
elseif(_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
|
||||
add_library(${_NAME} "")
|
||||
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
|
||||
if(APPLE)
|
||||
set_target_properties(${_NAME} PROPERTIES
|
||||
INSTALL_RPATH "@loader_path")
|
||||
elseif(UNIX)
|
||||
set_target_properties(${_NAME} PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN")
|
||||
endif()
|
||||
target_link_libraries(${_NAME}
|
||||
PUBLIC ${ABSL_CC_LIB_DEPS}
|
||||
PRIVATE
|
||||
|
|
@ -286,9 +301,9 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
|
|||
endif()
|
||||
|
||||
if(ABSL_PROPAGATE_CXX_STD)
|
||||
# Abseil libraries require C++14 as the current minimum standard. When
|
||||
# compiled with C++17 (either because it is the compiler's default or
|
||||
# explicitly requested), then Abseil requires C++17.
|
||||
# Abseil libraries require C++17 as the current minimum standard. When
|
||||
# compiled with a higher standard (either because it is the compiler's
|
||||
# default or explicitly requested), then Abseil requires that standard.
|
||||
target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})
|
||||
endif()
|
||||
|
||||
|
|
@ -298,7 +313,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
|
|||
if(ABSL_ENABLE_INSTALL)
|
||||
set_target_properties(${_NAME} PROPERTIES
|
||||
OUTPUT_NAME "absl_${_NAME}"
|
||||
SOVERSION "2308.0.0"
|
||||
SOVERSION "${ABSL_SOVERSION}"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
|
|
@ -323,7 +338,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
|
|||
target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
|
||||
|
||||
if(ABSL_PROPAGATE_CXX_STD)
|
||||
# Abseil libraries require C++14 as the current minimum standard.
|
||||
# Abseil libraries require C++17 as the current minimum standard.
|
||||
# Top-level application CMake projects should ensure a consistent C++
|
||||
# standard for all compiled sources by setting CMAKE_CXX_STANDARD.
|
||||
target_compile_features(${_NAME} INTERFACE ${ABSL_INTERNAL_CXX_STD_FEATURE})
|
||||
|
|
@ -435,7 +450,7 @@ function(absl_cc_test)
|
|||
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
|
||||
|
||||
if(ABSL_PROPAGATE_CXX_STD)
|
||||
# Abseil libraries require C++14 as the current minimum standard.
|
||||
# Abseil libraries require C++17 as the current minimum standard.
|
||||
# Top-level application CMake projects should ensure a consistent C++
|
||||
# standard for all compiled sources by setting CMAKE_CXX_STANDARD.
|
||||
target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(googletest-external NONE)
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,12 @@ section of your executable or of your library.<br>
|
|||
Here is a short CMakeLists.txt example of an application project using Abseil.
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(my_app_project)
|
||||
|
||||
# Pick the C++ standard to compile with.
|
||||
# Abseil currently supports C++14, C++17, and C++20.
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
# Abseil currently supports C++17 and C++20.
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_subdirectory(abseil-cpp)
|
||||
|
|
@ -62,7 +62,7 @@ will control Abseil library targets) is set to at least that minimum. For
|
|||
example:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(my_lib_project)
|
||||
|
||||
# Leave C++ standard up to the root application, so set it only if this is the
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
# A simple CMakeLists.txt for testing cmake installation
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(absl_cmake_testing CXX)
|
||||
|
||||
add_executable(simple simple.cc)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ set -euox pipefail
|
|||
absl_dir=/abseil-cpp
|
||||
absl_build_dir=/buildfs
|
||||
googletest_builddir=/googletest_builddir
|
||||
project_dir="${absl_dir}"/CMake/install_test_project
|
||||
googletest_archive="googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz"
|
||||
project_dir="${absl_dir}/CMake/install_test_project"
|
||||
project_build_dir=/buildfs/project-build
|
||||
|
||||
build_shared_libs="OFF"
|
||||
|
|
@ -33,9 +34,9 @@ fi
|
|||
# Build and install GoogleTest
|
||||
mkdir "${googletest_builddir}"
|
||||
pushd "${googletest_builddir}"
|
||||
curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${ABSL_GOOGLETEST_COMMIT}".zip
|
||||
unzip "${ABSL_GOOGLETEST_COMMIT}".zip
|
||||
pushd "googletest-${ABSL_GOOGLETEST_COMMIT}"
|
||||
curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${googletest_archive}"
|
||||
tar -xz -f "${googletest_archive}"
|
||||
pushd "googletest-${ABSL_GOOGLETEST_VERSION}"
|
||||
mkdir build
|
||||
pushd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="${build_shared_libs}" ..
|
||||
|
|
|
|||
|
|
@ -15,45 +15,16 @@
|
|||
#
|
||||
|
||||
# https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md
|
||||
# As of 2022-09-06, CMake 3.10 is the minimum supported version.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Compiler id for Apple Clang is now AppleClang.
|
||||
if (POLICY CMP0025)
|
||||
cmake_policy(SET CMP0025 NEW)
|
||||
endif (POLICY CMP0025)
|
||||
|
||||
# if command can use IN_LIST
|
||||
if (POLICY CMP0057)
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
endif (POLICY CMP0057)
|
||||
|
||||
# Project version variables are the empty string if version is unspecified
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
# option() honor variables
|
||||
if (POLICY CMP0077)
|
||||
cmake_policy(SET CMP0077 NEW)
|
||||
endif (POLICY CMP0077)
|
||||
|
||||
# Allow the user to specify the MSVC runtime
|
||||
if (POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif (POLICY CMP0091)
|
||||
|
||||
# try_compile() honors the CMAKE_CXX_STANDARD value
|
||||
if (POLICY CMP0067)
|
||||
cmake_policy(SET CMP0067 NEW)
|
||||
endif (POLICY CMP0067)
|
||||
# As of 2024-07-01, CMake 3.16 is the minimum supported version.
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# Allow the user to specify the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
||||
if (POLICY CMP0141)
|
||||
cmake_policy(SET CMP0141 NEW)
|
||||
endif (POLICY CMP0141)
|
||||
|
||||
project(absl LANGUAGES CXX VERSION 20230802)
|
||||
project(absl LANGUAGES CXX VERSION 20250512)
|
||||
set(ABSL_SOVERSION "2505.0.0")
|
||||
include(CTest)
|
||||
|
||||
# Output directory is correct by default for most build setups. However, when
|
||||
|
|
@ -70,12 +41,13 @@ else()
|
|||
option(ABSL_ENABLE_INSTALL "Enable install rule" ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN")
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
|
||||
set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
|
||||
|
||||
option(ABSL_PROPAGATE_CXX_STD
|
||||
"Use CMake C++ standard meta features (e.g. cxx_std_14) that propagate to targets that link to Abseil"
|
||||
OFF) # TODO: Default to ON for CMake 3.8 and greater.
|
||||
if(NOT ABSL_PROPAGATE_CXX_STD)
|
||||
message(WARNING "A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake 3.8 and up. We recommend enabling this option to ensure your project still builds correctly.")
|
||||
endif()
|
||||
"Use CMake C++ standard meta features (e.g. cxx_std_17) that propagate to targets that link to Abseil"
|
||||
ON)
|
||||
|
||||
option(ABSL_USE_SYSTEM_INCLUDES
|
||||
"Silence warnings in Abseil headers by marking them as SYSTEM includes"
|
||||
|
|
@ -86,6 +58,15 @@ list(APPEND CMAKE_MODULE_PATH
|
|||
${CMAKE_CURRENT_LIST_DIR}/absl/copts
|
||||
)
|
||||
|
||||
option(ABSL_MSVC_STATIC_RUNTIME
|
||||
"Link static runtime libraries"
|
||||
OFF)
|
||||
if(ABSL_MSVC_STATIC_RUNTIME)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
else()
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
include(AbseilDll)
|
||||
|
|
@ -144,6 +125,14 @@ set(ABSL_LOCAL_GOOGLETEST_DIR "/usr/src/googletest" CACHE PATH
|
|||
"If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout."
|
||||
)
|
||||
|
||||
option(ABSL_BUILD_MONOLITHIC_SHARED_LIBS
|
||||
"Build Abseil as a single shared library (always enabled for Windows)"
|
||||
OFF
|
||||
)
|
||||
if(NOT BUILD_SHARED_LIBS AND ABSL_BUILD_MONOLITHIC_SHARED_LIBS)
|
||||
message(WARNING "Not building a shared library because BUILD_SHARED_LIBS is not set. Ignoring ABSL_BUILD_MONOLITHIC_SHARED_LIBS.")
|
||||
endif()
|
||||
|
||||
if((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS)
|
||||
if (ABSL_USE_EXTERNAL_GOOGLETEST)
|
||||
if (ABSL_FIND_GOOGLETEST)
|
||||
|
|
@ -212,30 +201,67 @@ if(ABSL_ENABLE_INSTALL)
|
|||
)
|
||||
endif() # absl_VERSION
|
||||
|
||||
# Install the headers except for "options.h" which is installed separately.
|
||||
install(DIRECTORY absl
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING
|
||||
PATTERN "*.inc"
|
||||
PATTERN "*.h"
|
||||
PATTERN "options.h" EXCLUDE
|
||||
PATTERN "copts" EXCLUDE
|
||||
PATTERN "testdata" EXCLUDE
|
||||
)
|
||||
|
||||
# Rewrite options.h to use the compiled ABI.
|
||||
file(READ "absl/base/options.h" ABSL_INTERNAL_OPTIONS_H_CONTENTS)
|
||||
if (ABSL_INTERNAL_AT_LEAST_CXX17)
|
||||
string(REGEX REPLACE
|
||||
"#define ABSL_OPTION_USE_STD_([^ ]*) 2"
|
||||
"#define ABSL_OPTION_USE_STD_\\1 1"
|
||||
ABSL_INTERNAL_OPTIONS_H_PINNED
|
||||
"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}")
|
||||
else()
|
||||
string(REGEX REPLACE
|
||||
"#define ABSL_OPTION_USE_STD_([^ ]*) 2"
|
||||
"#define ABSL_OPTION_USE_STD_\\1 0"
|
||||
|
||||
# Handle features that require at least C++20.
|
||||
if (ABSL_INTERNAL_AT_LEAST_CXX20)
|
||||
foreach(FEATURE "ORDERING")
|
||||
string(REPLACE
|
||||
"#define ABSL_OPTION_USE_STD_${FEATURE} 2"
|
||||
"#define ABSL_OPTION_USE_STD_${FEATURE} 1"
|
||||
ABSL_INTERNAL_OPTIONS_H_PINNED
|
||||
"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}")
|
||||
set(ABSL_INTERNAL_OPTIONS_H_CONTENTS "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Handle features that require at least C++17.
|
||||
if (ABSL_INTERNAL_AT_LEAST_CXX17)
|
||||
foreach(FEATURE "ANY" "OPTIONAL" "STRING_VIEW" "VARIANT")
|
||||
string(REPLACE
|
||||
"#define ABSL_OPTION_USE_STD_${FEATURE} 2"
|
||||
"#define ABSL_OPTION_USE_STD_${FEATURE} 1"
|
||||
ABSL_INTERNAL_OPTIONS_H_PINNED
|
||||
"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}")
|
||||
set(ABSL_INTERNAL_OPTIONS_H_CONTENTS "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Any feature that still has the value of 2 (because it was not handled above)
|
||||
# should be set to 0.
|
||||
string(REGEX REPLACE
|
||||
"#define ABSL_OPTION_USE_STD_([^ ]*) 2"
|
||||
"#define ABSL_OPTION_USE_STD_\\1 0"
|
||||
ABSL_INTERNAL_OPTIONS_H_PINNED
|
||||
"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}")
|
||||
|
||||
# If the file already exists, check if it matches the new contents.
|
||||
# This avoids writing the file if it is already up-to-date when the CMake
|
||||
# generation is triggered and triggering unnecessary rebuilds.
|
||||
set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE TRUE)
|
||||
if (EXISTS "${CMAKE_BINARY_DIR}/options-pinned.h")
|
||||
file(READ "${CMAKE_BINARY_DIR}/options-pinned.h" ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS)
|
||||
if ("${ABSL_INTERNAL_OPTIONS_H_PINNED}" STREQUAL "${ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS}")
|
||||
set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If the file needs an update, generate it.
|
||||
if (ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE)
|
||||
file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/options-pinned.h" CONTENT "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
|
||||
endif()
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/options-pinned.h" "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
|
||||
|
||||
install(FILES "${CMAKE_BINARY_DIR}/options-pinned.h"
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/absl/base
|
||||
|
|
|
|||
|
|
@ -1,8 +1,25 @@
|
|||
"""Module definition for Abseil LTS 20230802.1."""
|
||||
# Copyright 2024 The Abseil Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# https://bazel.build/external/overview#bzlmod
|
||||
|
||||
module(
|
||||
name = "abseil-cpp",
|
||||
version = "20250512.1",
|
||||
compatibility_level = 1,
|
||||
)
|
||||
|
||||
bazel_dep(name = "bazel_skylib", version = "1.4.1")
|
||||
bazel_dep(name = "platforms", version = "0.0.7")
|
||||
bazel_dep(name = "rules_cc", version = "0.0.9")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
||||
bazel_dep(name = "platforms", version = "0.0.11")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array/>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# Abseil - C++ Common Libraries
|
||||
|
||||
The repository contains the Abseil C++ library code. Abseil is an open-source
|
||||
collection of C++ code (compliant to C++14) designed to augment the C++
|
||||
collection of C++ code (compliant to C++17) designed to augment the C++
|
||||
standard library.
|
||||
|
||||
## Table of Contents
|
||||
|
|
@ -99,8 +99,8 @@ Abseil contains the following C++ library components:
|
|||
<br /> The `memory` library contains memory management facilities that augment
|
||||
C++'s `<memory>` library.
|
||||
* [`meta`](absl/meta/)
|
||||
<br /> The `meta` library contains compatible versions of type checks
|
||||
available within C++14 and C++17 versions of the C++ `<type_traits>` library.
|
||||
<br /> The `meta` library contains type checks
|
||||
similar to those available in the C++ `<type_traits>` library.
|
||||
* [`numeric`](absl/numeric/)
|
||||
<br /> The `numeric` library contains 128-bit integer types as well as
|
||||
implementations of C++20's bitwise math functions.
|
||||
|
|
@ -108,15 +108,14 @@ Abseil contains the following C++ library components:
|
|||
<br /> The `profiling` library contains utility code for profiling C++
|
||||
entities. It is currently a private dependency of other Abseil libraries.
|
||||
* [`random`](absl/random/)
|
||||
<br /> The `random` library contains functions for generating psuedorandom
|
||||
<br /> The `random` library contains functions for generating pseudorandom
|
||||
values.
|
||||
* [`status`](absl/status/)
|
||||
<br /> The `status` library contains abstractions for error handling,
|
||||
specifically `absl::Status` and `absl::StatusOr<T>`.
|
||||
* [`strings`](absl/strings/)
|
||||
<br /> The `strings` library contains a variety of strings routines and
|
||||
utilities, including a C++14-compatible version of the C++17
|
||||
`std::string_view` type.
|
||||
utilities.
|
||||
* [`synchronization`](absl/synchronization/)
|
||||
<br /> The `synchronization` library contains concurrency primitives (Abseil's
|
||||
`absl::Mutex` class, an alternative to `std::mutex`) and a variety of
|
||||
|
|
@ -126,8 +125,7 @@ Abseil contains the following C++ library components:
|
|||
points in time, durations of time, and formatting and parsing time within
|
||||
time zones.
|
||||
* [`types`](absl/types/)
|
||||
<br /> The `types` library contains non-container utility types, like a
|
||||
C++14-compatible version of the C++17 `std::optional` type.
|
||||
<br /> The `types` library contains non-container utility types.
|
||||
* [`utility`](absl/utility/)
|
||||
<br /> The `utility` library contains utility and helper code.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
#
|
||||
# Copyright 2019 The Abseil Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
workspace(name = "com_google_absl")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# GoogleTest/GoogleMock framework. Used by most unit-tests.
|
||||
http_archive(
|
||||
name = "com_google_googletest", # 2023-08-02T16:45:10Z
|
||||
sha256 = "1f357c27ca988c3f7c6b4bf68a9395005ac6761f034046e9dde0896e3aba00e4",
|
||||
strip_prefix = "googletest-1.14.0",
|
||||
# Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh.
|
||||
urls = ["https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip"],
|
||||
)
|
||||
|
||||
# RE2 (the regular expression library used by GoogleTest)
|
||||
http_archive(
|
||||
name = "com_googlesource_code_re2", # 2023-03-17T11:36:51Z
|
||||
sha256 = "cb8b5312a65f2598954545a76e8bce913f35fbb3a21a5c88797a4448e9f9b9d9",
|
||||
strip_prefix = "re2-578843a516fd1da7084ae46209a75f3613b6065e",
|
||||
urls = ["https://github.com/google/re2/archive/578843a516fd1da7084ae46209a75f3613b6065e.zip"],
|
||||
)
|
||||
|
||||
# Google benchmark.
|
||||
http_archive(
|
||||
name = "com_github_google_benchmark", # 2023-08-01T07:47:09Z
|
||||
sha256 = "db1e39ee71dc38aa7e57ed007f2c8b3bb59e13656435974781a9dc0617d75cc9",
|
||||
strip_prefix = "benchmark-02a354f3f323ae8256948e1dc77ddcb1dfc297da",
|
||||
urls = ["https://github.com/google/benchmark/archive/02a354f3f323ae8256948e1dc77ddcb1dfc297da.zip"],
|
||||
)
|
||||
|
||||
# Bazel Skylib.
|
||||
http_archive(
|
||||
name = "bazel_skylib", # 2023-05-31T19:24:07Z
|
||||
sha256 = "08c0386f45821ce246bbbf77503c973246ed6ee5c3463e41efc197fa9bc3a7f4",
|
||||
strip_prefix = "bazel-skylib-288731ef9f7f688932bd50e704a91a45ec185f9b",
|
||||
urls = ["https://github.com/bazelbuild/bazel-skylib/archive/288731ef9f7f688932bd50e704a91a45ec185f9b.zip"],
|
||||
)
|
||||
|
||||
# Bazel platform rules.
|
||||
http_archive(
|
||||
name = "platforms", # 2023-07-28T19:44:27Z
|
||||
sha256 = "40eb313613ff00a5c03eed20aba58890046f4d38dec7344f00bb9a8867853526",
|
||||
strip_prefix = "platforms-4ad40ef271da8176d4fc0194d2089b8a76e19d7b",
|
||||
urls = ["https://github.com/bazelbuild/platforms/archive/4ad40ef271da8176d4fc0194d2089b8a76e19d7b.zip"],
|
||||
)
|
||||
|
|
@ -28,14 +28,6 @@ config_setting(
|
|||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "gcc_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "gcc",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "mingw_unspecified_compiler",
|
||||
flag_values = {
|
||||
|
|
@ -52,92 +44,11 @@ config_setting(
|
|||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "msvc_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "msvc-cl",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "clang-cl_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "clang-cl",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "osx",
|
||||
constraint_values = [
|
||||
"@platforms//os:osx",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "ios",
|
||||
constraint_values = [
|
||||
"@platforms//os:ios",
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "ppc",
|
||||
values = {
|
||||
"cpu": "ppc",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "cpu_wasm",
|
||||
values = {
|
||||
"cpu": "wasm",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "cpu_wasm32",
|
||||
values = {
|
||||
"cpu": "wasm32",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "platforms_wasm32",
|
||||
constraint_values = [
|
||||
"@platforms//cpu:wasm32",
|
||||
],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "platforms_wasm64",
|
||||
constraint_values = [
|
||||
"@platforms//cpu:wasm64",
|
||||
],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
selects.config_setting_group(
|
||||
name = "wasm",
|
||||
match_any = [
|
||||
":cpu_wasm",
|
||||
":cpu_wasm32",
|
||||
":platforms_wasm32",
|
||||
":platforms_wasm64",
|
||||
],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "fuchsia",
|
||||
values = {
|
||||
"cpu": "fuchsia",
|
||||
},
|
||||
constraint_values = [
|
||||
"@platforms//os:fuchsia",
|
||||
],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ add_subdirectory(time)
|
|||
add_subdirectory(types)
|
||||
add_subdirectory(utility)
|
||||
|
||||
if (${ABSL_BUILD_DLL})
|
||||
if (ABSL_BUILD_DLL)
|
||||
absl_make_dll()
|
||||
if (${ABSL_BUILD_TEST_HELPERS})
|
||||
if ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS)
|
||||
absl_make_dll(TEST ON)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ Pod::Spec.new do |s|
|
|||
:git => 'https://github.com/abseil/abseil-cpp.git',
|
||||
:tag => '${tag}',
|
||||
}
|
||||
s.resource_bundles = {
|
||||
s.module_name => 'PrivacyInfo.xcprivacy',
|
||||
}
|
||||
s.module_name = 'absl'
|
||||
s.header_mappings_dir = 'absl'
|
||||
s.header_dir = 'absl'
|
||||
|
|
@ -40,10 +43,16 @@ Pod::Spec.new do |s|
|
|||
'USE_HEADERMAP' => 'NO',
|
||||
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
|
||||
}
|
||||
s.ios.deployment_target = '9.0'
|
||||
s.osx.deployment_target = '10.10'
|
||||
s.tvos.deployment_target = '9.0'
|
||||
s.watchos.deployment_target = '2.0'
|
||||
s.ios.deployment_target = '12.0'
|
||||
s.osx.deployment_target = '10.13'
|
||||
s.tvos.deployment_target = '12.0'
|
||||
s.watchos.deployment_target = '4.0'
|
||||
s.visionos.deployment_target = '1.0'
|
||||
s.subspec 'xcprivacy' do |ss|
|
||||
ss.resource_bundles = {
|
||||
ss.module_name => 'PrivacyInfo.xcprivacy',
|
||||
}
|
||||
end
|
||||
"""
|
||||
|
||||
# Rule object representing the rule of Bazel BUILD.
|
||||
|
|
@ -188,6 +197,12 @@ def write_podspec_rule(f, rule, depth):
|
|||
name = get_spec_name(dep.replace(":", "/"))
|
||||
f.write("{indent}{var}.dependency '{dep}'\n".format(
|
||||
indent=indent, var=spec_var, dep=name))
|
||||
# Writes dependency to xcprivacy
|
||||
f.write(
|
||||
"{indent}{var}.dependency '{dep}'\n".format(
|
||||
indent=indent, var=spec_var, dep="abseil/xcprivacy"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def write_indented_list(f, leading, values):
|
||||
|
|
|
|||
|
|
@ -21,7 +21,14 @@ load(
|
|||
"ABSL_TEST_COPTS",
|
||||
)
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
features = [
|
||||
"header_modules",
|
||||
"layering_check",
|
||||
"parse_headers",
|
||||
],
|
||||
)
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
|
|
@ -44,21 +51,8 @@ cc_test(
|
|||
deps = [
|
||||
":algorithm",
|
||||
"//absl/base:config",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "algorithm_benchmark",
|
||||
testonly = 1,
|
||||
srcs = ["equal_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
deps = [
|
||||
":algorithm",
|
||||
"//absl/base:core_headers",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -71,7 +65,9 @@ cc_library(
|
|||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":algorithm",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:nullability",
|
||||
"//absl/meta:type_traits",
|
||||
],
|
||||
)
|
||||
|
|
@ -84,9 +80,12 @@ cc_test(
|
|||
deps = [
|
||||
":container",
|
||||
"//absl/base",
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/memory",
|
||||
"//absl/random",
|
||||
"//absl/types:span",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@ absl_cc_library(
|
|||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::algorithm
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::meta
|
||||
absl::nullability
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
|
|
@ -63,8 +65,10 @@ absl_cc_test(
|
|||
DEPS
|
||||
absl::algorithm_container
|
||||
absl::base
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::memory
|
||||
absl::random_random
|
||||
absl::span
|
||||
GTest::gmock_main
|
||||
)
|
||||
|
|
|
|||
|
|
@ -31,92 +31,17 @@
|
|||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
namespace algorithm_internal {
|
||||
|
||||
// Performs comparisons with operator==, similar to C++14's `std::equal_to<>`.
|
||||
struct EqualTo {
|
||||
template <typename T, typename U>
|
||||
bool operator()(const T& a, const U& b) const {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename InputIter1, typename InputIter2, typename Pred>
|
||||
bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2,
|
||||
InputIter2 last2, Pred pred, std::input_iterator_tag,
|
||||
std::input_iterator_tag) {
|
||||
while (true) {
|
||||
if (first1 == last1) return first2 == last2;
|
||||
if (first2 == last2) return false;
|
||||
if (!pred(*first1, *first2)) return false;
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputIter1, typename InputIter2, typename Pred>
|
||||
bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2,
|
||||
InputIter2 last2, Pred&& pred, std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag) {
|
||||
return (last1 - first1 == last2 - first2) &&
|
||||
std::equal(first1, last1, first2, std::forward<Pred>(pred));
|
||||
}
|
||||
|
||||
// When we are using our own internal predicate that just applies operator==, we
|
||||
// forward to the non-predicate form of std::equal. This enables an optimization
|
||||
// in libstdc++ that can result in std::memcmp being used for integer types.
|
||||
template <typename InputIter1, typename InputIter2>
|
||||
bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2,
|
||||
InputIter2 last2, algorithm_internal::EqualTo /* unused */,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag) {
|
||||
return (last1 - first1 == last2 - first2) &&
|
||||
std::equal(first1, last1, first2);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
It RotateImpl(It first, It middle, It last, std::true_type) {
|
||||
return std::rotate(first, middle, last);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
It RotateImpl(It first, It middle, It last, std::false_type) {
|
||||
std::rotate(first, middle, last);
|
||||
return std::next(first, std::distance(middle, last));
|
||||
}
|
||||
|
||||
} // namespace algorithm_internal
|
||||
|
||||
// equal()
|
||||
// rotate()
|
||||
//
|
||||
// Compares the equality of two ranges specified by pairs of iterators, using
|
||||
// the given predicate, returning true iff for each corresponding iterator i1
|
||||
// and i2 in the first and second range respectively, pred(*i1, *i2) == true
|
||||
// Historical note: Abseil once provided implementations of these algorithms
|
||||
// prior to their adoption in C++14. New code should prefer to use the std
|
||||
// variants.
|
||||
//
|
||||
// This comparison takes at most min(`last1` - `first1`, `last2` - `first2`)
|
||||
// invocations of the predicate. Additionally, if InputIter1 and InputIter2 are
|
||||
// both random-access iterators, and `last1` - `first1` != `last2` - `first2`,
|
||||
// then the predicate is never invoked and the function returns false.
|
||||
//
|
||||
// This is a C++11-compatible implementation of C++14 `std::equal`. See
|
||||
// https://en.cppreference.com/w/cpp/algorithm/equal for more information.
|
||||
template <typename InputIter1, typename InputIter2, typename Pred>
|
||||
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
|
||||
InputIter2 last2, Pred&& pred) {
|
||||
return algorithm_internal::EqualImpl(
|
||||
first1, last1, first2, last2, std::forward<Pred>(pred),
|
||||
typename std::iterator_traits<InputIter1>::iterator_category{},
|
||||
typename std::iterator_traits<InputIter2>::iterator_category{});
|
||||
}
|
||||
|
||||
// Overload of equal() that performs comparison of two ranges specified by pairs
|
||||
// of iterators using operator==.
|
||||
template <typename InputIter1, typename InputIter2>
|
||||
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
|
||||
InputIter2 last2) {
|
||||
return absl::equal(first1, last1, first2, last2,
|
||||
algorithm_internal::EqualTo{});
|
||||
}
|
||||
// See the documentation for the STL <algorithm> header for more information:
|
||||
// https://en.cppreference.com/w/cpp/header/algorithm
|
||||
using std::equal;
|
||||
using std::rotate;
|
||||
|
||||
// linear_search()
|
||||
//
|
||||
|
|
@ -128,31 +53,11 @@ bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
|
|||
// n = (`last` - `first`) comparisons. A linear search over short containers
|
||||
// may be faster than a binary search, even when the container is sorted.
|
||||
template <typename InputIterator, typename EqualityComparable>
|
||||
bool linear_search(InputIterator first, InputIterator last,
|
||||
const EqualityComparable& value) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search(
|
||||
InputIterator first, InputIterator last, const EqualityComparable& value) {
|
||||
return std::find(first, last, value) != last;
|
||||
}
|
||||
|
||||
// rotate()
|
||||
//
|
||||
// Performs a left rotation on a range of elements (`first`, `last`) such that
|
||||
// `middle` is now the first element. `rotate()` returns an iterator pointing to
|
||||
// the first element before rotation. This function is exactly the same as
|
||||
// `std::rotate`, but fixes a bug in gcc
|
||||
// <= 4.9 where `std::rotate` returns `void` instead of an iterator.
|
||||
//
|
||||
// The complexity of this algorithm is the same as that of `std::rotate`, but if
|
||||
// `ForwardIterator` is not a random-access iterator, then `absl::rotate`
|
||||
// performs an additional pass over the range to construct the return value.
|
||||
template <typename ForwardIterator>
|
||||
ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
|
||||
ForwardIterator last) {
|
||||
return algorithm_internal::RotateImpl(
|
||||
first, middle, last,
|
||||
std::is_same<decltype(std::rotate(first, middle, last)),
|
||||
ForwardIterator>());
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
|
|
|||
|
|
@ -14,147 +14,14 @@
|
|||
|
||||
#include "absl/algorithm/algorithm.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(EqualTest, DefaultComparisonRandomAccess) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<int> v2 = v1;
|
||||
std::vector<int> v3 = {1, 2};
|
||||
std::vector<int> v4 = {1, 2, 4};
|
||||
|
||||
EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, DefaultComparison) {
|
||||
std::list<int> lst1{1, 2, 3};
|
||||
std::list<int> lst2 = lst1;
|
||||
std::list<int> lst3{1, 2};
|
||||
std::list<int> lst4{1, 2, 4};
|
||||
|
||||
EXPECT_TRUE(absl::equal(lst1.begin(), lst1.end(), lst2.begin(), lst2.end()));
|
||||
EXPECT_FALSE(absl::equal(lst1.begin(), lst1.end(), lst3.begin(), lst3.end()));
|
||||
EXPECT_FALSE(absl::equal(lst1.begin(), lst1.end(), lst4.begin(), lst4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, EmptyRange) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<int> empty1;
|
||||
std::vector<int> empty2;
|
||||
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105705
|
||||
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnonnull"
|
||||
#endif
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), empty1.begin(), empty1.end()));
|
||||
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
EXPECT_FALSE(absl::equal(empty1.begin(), empty1.end(), v1.begin(), v1.end()));
|
||||
EXPECT_TRUE(
|
||||
absl::equal(empty1.begin(), empty1.end(), empty2.begin(), empty2.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, MixedIterTypes) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::list<int> lst1{v1.begin(), v1.end()};
|
||||
std::list<int> lst2{1, 2, 4};
|
||||
std::list<int> lst3{1, 2};
|
||||
|
||||
EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), lst1.begin(), lst1.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), lst2.begin(), lst2.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), lst3.begin(), lst3.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, MixedValueTypes) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<char> v2{1, 2, 3};
|
||||
std::vector<char> v3{1, 2};
|
||||
std::vector<char> v4{1, 2, 4};
|
||||
|
||||
EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, WeirdIterators) {
|
||||
std::vector<bool> v1{true, false};
|
||||
std::vector<bool> v2 = v1;
|
||||
std::vector<bool> v3{true};
|
||||
std::vector<bool> v4{true, true, true};
|
||||
|
||||
EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, CustomComparison) {
|
||||
int n[] = {1, 2, 3, 4};
|
||||
std::vector<int*> v1{&n[0], &n[1], &n[2]};
|
||||
std::vector<int*> v2 = v1;
|
||||
std::vector<int*> v3{&n[0], &n[1], &n[3]};
|
||||
std::vector<int*> v4{&n[0], &n[1]};
|
||||
|
||||
auto eq = [](int* a, int* b) { return *a == *b; };
|
||||
|
||||
EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), eq));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end(), eq));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end(), eq));
|
||||
}
|
||||
|
||||
TEST(EqualTest, MoveOnlyPredicate) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<int> v2{4, 5, 6};
|
||||
|
||||
// move-only equality predicate
|
||||
struct Eq {
|
||||
Eq() = default;
|
||||
Eq(Eq &&) = default;
|
||||
Eq(const Eq &) = delete;
|
||||
Eq &operator=(const Eq &) = delete;
|
||||
bool operator()(const int a, const int b) const { return a == b; }
|
||||
};
|
||||
|
||||
EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v1.begin(), v1.end(), Eq()));
|
||||
EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), Eq()));
|
||||
}
|
||||
|
||||
struct CountingTrivialPred {
|
||||
int* count;
|
||||
bool operator()(int, int) const {
|
||||
++*count;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(EqualTest, RandomAccessComplexity) {
|
||||
std::vector<int> v1{1, 1, 3};
|
||||
std::vector<int> v2 = v1;
|
||||
std::vector<int> v3{1, 2};
|
||||
|
||||
do {
|
||||
int count = 0;
|
||||
absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(),
|
||||
CountingTrivialPred{&count});
|
||||
EXPECT_LE(count, 3);
|
||||
} while (std::next_permutation(v2.begin(), v2.end()));
|
||||
|
||||
int count = 0;
|
||||
absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end(),
|
||||
CountingTrivialPred{&count});
|
||||
EXPECT_EQ(count, 0);
|
||||
}
|
||||
|
||||
class LinearSearchTest : public testing::Test {
|
||||
protected:
|
||||
LinearSearchTest() : container_{1, 2, 3} {}
|
||||
|
|
@ -178,14 +45,16 @@ TEST_F(LinearSearchTest, linear_searchConst) {
|
|||
absl::linear_search(const_container->begin(), const_container->end(), 4));
|
||||
}
|
||||
|
||||
TEST(RotateTest, Rotate) {
|
||||
std::vector<int> v{0, 1, 2, 3, 4};
|
||||
EXPECT_EQ(*absl::rotate(v.begin(), v.begin() + 2, v.end()), 0);
|
||||
EXPECT_THAT(v, testing::ElementsAreArray({2, 3, 4, 0, 1}));
|
||||
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
|
||||
std::list<int> l{0, 1, 2, 3, 4};
|
||||
EXPECT_EQ(*absl::rotate(l.begin(), std::next(l.begin(), 3), l.end()), 0);
|
||||
EXPECT_THAT(l, testing::ElementsAreArray({3, 4, 0, 1, 2}));
|
||||
TEST_F(LinearSearchTest, Constexpr) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::linear_search(kArray.begin(), kArray.end(), 3));
|
||||
static_assert(!absl::linear_search(kArray.begin(), kArray.end(), 4));
|
||||
}
|
||||
|
||||
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
|
||||
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@
|
|||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/algorithm.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
|
||||
namespace absl {
|
||||
|
|
@ -73,8 +75,8 @@ using ContainerIter = decltype(begin(std::declval<C&>()));
|
|||
// An MSVC bug involving template parameter substitution requires us to use
|
||||
// decltype() here instead of just std::pair.
|
||||
template <typename C1, typename C2>
|
||||
using ContainerIterPairType =
|
||||
decltype(std::make_pair(ContainerIter<C1>(), ContainerIter<C2>()));
|
||||
using ContainerIterPairType = decltype(std::make_pair(
|
||||
std::declval<ContainerIter<C1>>(), std::declval<ContainerIter<C2>>()));
|
||||
|
||||
template <typename C>
|
||||
using ContainerDifferenceType = decltype(std::distance(
|
||||
|
|
@ -91,17 +93,17 @@ using ContainerPointerType =
|
|||
// using std::end;
|
||||
// std::foo(begin(c), end(c));
|
||||
// becomes
|
||||
// std::foo(container_algorithm_internal::begin(c),
|
||||
// container_algorithm_internal::end(c));
|
||||
// std::foo(container_algorithm_internal::c_begin(c),
|
||||
// container_algorithm_internal::c_end(c));
|
||||
// These are meant for internal use only.
|
||||
|
||||
template <typename C>
|
||||
ContainerIter<C> c_begin(C& c) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
|
||||
return begin(c);
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
ContainerIter<C> c_end(C& c) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
|
||||
return end(c);
|
||||
}
|
||||
|
||||
|
|
@ -116,18 +118,6 @@ template <class Key, class Hash, class KeyEqual, class Allocator>
|
|||
struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
|
||||
: std::true_type {};
|
||||
|
||||
// container_algorithm_internal::c_size. It is meant for internal use only.
|
||||
|
||||
template <class C>
|
||||
auto c_size(C& c) -> decltype(c.size()) {
|
||||
return c.size();
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
constexpr std::size_t c_size(T (&)[N]) {
|
||||
return N;
|
||||
}
|
||||
|
||||
} // namespace container_algorithm_internal
|
||||
|
||||
// PUBLIC API
|
||||
|
|
@ -140,11 +130,14 @@ constexpr std::size_t c_size(T (&)[N]) {
|
|||
//
|
||||
// Container-based version of absl::linear_search() for performing a linear
|
||||
// search within a container.
|
||||
//
|
||||
// For a generalization that uses a predicate, see absl::c_any_of().
|
||||
template <typename C, typename EqualityComparable>
|
||||
bool c_linear_search(const C& c, EqualityComparable&& value) {
|
||||
return linear_search(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<EqualityComparable>(value));
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search(
|
||||
const C& c, EqualityComparable&& value) {
|
||||
return absl::linear_search(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<EqualityComparable>(value));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -156,8 +149,9 @@ bool c_linear_search(const C& c, EqualityComparable&& value) {
|
|||
// Container-based version of the <iterator> `std::distance()` function to
|
||||
// return the number of elements within a container.
|
||||
template <typename C>
|
||||
container_algorithm_internal::ContainerDifferenceType<const C> c_distance(
|
||||
const C& c) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
container_algorithm_internal::ContainerDifferenceType<const C>
|
||||
c_distance(const C& c) {
|
||||
return std::distance(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c));
|
||||
}
|
||||
|
|
@ -171,7 +165,7 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_distance(
|
|||
// Container-based version of the <algorithm> `std::all_of()` function to
|
||||
// test if all elements within a container satisfy a condition.
|
||||
template <typename C, typename Pred>
|
||||
bool c_all_of(const C& c, Pred&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) {
|
||||
return std::all_of(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Pred>(pred));
|
||||
|
|
@ -182,7 +176,7 @@ bool c_all_of(const C& c, Pred&& pred) {
|
|||
// Container-based version of the <algorithm> `std::any_of()` function to
|
||||
// test if any element in a container fulfills a condition.
|
||||
template <typename C, typename Pred>
|
||||
bool c_any_of(const C& c, Pred&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) {
|
||||
return std::any_of(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Pred>(pred));
|
||||
|
|
@ -193,7 +187,7 @@ bool c_any_of(const C& c, Pred&& pred) {
|
|||
// Container-based version of the <algorithm> `std::none_of()` function to
|
||||
// test if no elements in a container fulfill a condition.
|
||||
template <typename C, typename Pred>
|
||||
bool c_none_of(const C& c, Pred&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) {
|
||||
return std::none_of(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Pred>(pred));
|
||||
|
|
@ -204,7 +198,8 @@ bool c_none_of(const C& c, Pred&& pred) {
|
|||
// Container-based version of the <algorithm> `std::for_each()` function to
|
||||
// apply a function to a container's elements.
|
||||
template <typename C, typename Function>
|
||||
decay_t<Function> c_for_each(C&& c, Function&& f) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> c_for_each(C&& c,
|
||||
Function&& f) {
|
||||
return std::for_each(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Function>(f));
|
||||
|
|
@ -215,18 +210,33 @@ decay_t<Function> c_for_each(C&& c, Function&& f) {
|
|||
// Container-based version of the <algorithm> `std::find()` function to find
|
||||
// the first element containing the passed value within a container value.
|
||||
template <typename C, typename T>
|
||||
container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<C>
|
||||
c_find(C& c, T&& value) {
|
||||
return std::find(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<T>(value));
|
||||
}
|
||||
|
||||
// c_contains()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::ranges::contains()` C++23
|
||||
// function to search a container for a value.
|
||||
template <typename Sequence, typename T>
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence,
|
||||
T&& value) {
|
||||
return absl::c_find(sequence, std::forward<T>(value)) !=
|
||||
container_algorithm_internal::c_end(sequence);
|
||||
}
|
||||
|
||||
// c_find_if()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::find_if()` function to find
|
||||
// the first element in a container matching the given condition.
|
||||
template <typename C, typename Pred>
|
||||
container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<C>
|
||||
c_find_if(C& c, Pred&& pred) {
|
||||
return std::find_if(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Pred>(pred));
|
||||
|
|
@ -237,8 +247,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
|
|||
// Container-based version of the <algorithm> `std::find_if_not()` function to
|
||||
// find the first element in a container not matching the given condition.
|
||||
template <typename C, typename Pred>
|
||||
container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
|
||||
Pred&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<C>
|
||||
c_find_if_not(C& c, Pred&& pred) {
|
||||
return std::find_if_not(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Pred>(pred));
|
||||
|
|
@ -249,8 +260,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
|
|||
// Container-based version of the <algorithm> `std::find_end()` function to
|
||||
// find the last subsequence within a container.
|
||||
template <typename Sequence1, typename Sequence2>
|
||||
container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
|
||||
Sequence1& sequence, Sequence2& subsequence) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence1>
|
||||
c_find_end(Sequence1& sequence, Sequence2& subsequence) {
|
||||
return std::find_end(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
container_algorithm_internal::c_begin(subsequence),
|
||||
|
|
@ -260,8 +272,10 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
|
|||
// Overload of c_find_end() for using a predicate evaluation other than `==` as
|
||||
// the function's test condition.
|
||||
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
|
||||
container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
|
||||
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence1>
|
||||
c_find_end(Sequence1& sequence, Sequence2& subsequence,
|
||||
BinaryPredicate&& pred) {
|
||||
return std::find_end(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
container_algorithm_internal::c_begin(subsequence),
|
||||
|
|
@ -275,8 +289,9 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
|
|||
// find the first element within the container that is also within the options
|
||||
// container.
|
||||
template <typename C1, typename C2>
|
||||
container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
|
||||
C2& options) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<C1>
|
||||
c_find_first_of(C1& container, const C2& options) {
|
||||
return std::find_first_of(container_algorithm_internal::c_begin(container),
|
||||
container_algorithm_internal::c_end(container),
|
||||
container_algorithm_internal::c_begin(options),
|
||||
|
|
@ -286,8 +301,9 @@ container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
|
|||
// Overload of c_find_first_of() for using a predicate evaluation other than
|
||||
// `==` as the function's test condition.
|
||||
template <typename C1, typename C2, typename BinaryPredicate>
|
||||
container_algorithm_internal::ContainerIter<C1> c_find_first_of(
|
||||
C1& container, C2& options, BinaryPredicate&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<C1>
|
||||
c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) {
|
||||
return std::find_first_of(container_algorithm_internal::c_begin(container),
|
||||
container_algorithm_internal::c_end(container),
|
||||
container_algorithm_internal::c_begin(options),
|
||||
|
|
@ -300,8 +316,9 @@ container_algorithm_internal::ContainerIter<C1> c_find_first_of(
|
|||
// Container-based version of the <algorithm> `std::adjacent_find()` function to
|
||||
// find equal adjacent elements within a container.
|
||||
template <typename Sequence>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
|
||||
Sequence& sequence) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_adjacent_find(Sequence& sequence) {
|
||||
return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence));
|
||||
}
|
||||
|
|
@ -309,8 +326,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
|
|||
// Overload of c_adjacent_find() for using a predicate evaluation other than
|
||||
// `==` as the function's test condition.
|
||||
template <typename Sequence, typename BinaryPredicate>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
|
||||
Sequence& sequence, BinaryPredicate&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) {
|
||||
return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<BinaryPredicate>(pred));
|
||||
|
|
@ -321,8 +339,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
|
|||
// Container-based version of the <algorithm> `std::count()` function to count
|
||||
// values that match within a container.
|
||||
template <typename C, typename T>
|
||||
container_algorithm_internal::ContainerDifferenceType<const C> c_count(
|
||||
const C& c, T&& value) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerDifferenceType<const C>
|
||||
c_count(const C& c, T&& value) {
|
||||
return std::count(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<T>(value));
|
||||
|
|
@ -333,8 +352,9 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count(
|
|||
// Container-based version of the <algorithm> `std::count_if()` function to
|
||||
// count values matching a condition within a container.
|
||||
template <typename C, typename Pred>
|
||||
container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
|
||||
const C& c, Pred&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerDifferenceType<const C>
|
||||
c_count_if(const C& c, Pred&& pred) {
|
||||
return std::count_if(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<Pred>(pred));
|
||||
|
|
@ -346,80 +366,50 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
|
|||
// return the first element where two ordered containers differ. Applies `==` to
|
||||
// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
|
||||
template <typename C1, typename C2>
|
||||
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
|
||||
C2& c2) {
|
||||
auto first1 = container_algorithm_internal::c_begin(c1);
|
||||
auto last1 = container_algorithm_internal::c_end(c1);
|
||||
auto first2 = container_algorithm_internal::c_begin(c2);
|
||||
auto last2 = container_algorithm_internal::c_end(c2);
|
||||
|
||||
for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
|
||||
// Negates equality because Cpp17EqualityComparable doesn't require clients
|
||||
// to overload both `operator==` and `operator!=`.
|
||||
if (!(*first1 == *first2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(first1, first2);
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIterPairType<C1, C2>
|
||||
c_mismatch(C1& c1, C2& c2) {
|
||||
return std::mismatch(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2));
|
||||
}
|
||||
|
||||
// Overload of c_mismatch() for using a predicate evaluation other than `==` as
|
||||
// the function's test condition. Applies `pred`to the first N elements of `c1`
|
||||
// and `c2`, where N = min(size(c1), size(c2)).
|
||||
template <typename C1, typename C2, typename BinaryPredicate>
|
||||
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
|
||||
C1& c1, C2& c2, BinaryPredicate pred) {
|
||||
auto first1 = container_algorithm_internal::c_begin(c1);
|
||||
auto last1 = container_algorithm_internal::c_end(c1);
|
||||
auto first2 = container_algorithm_internal::c_begin(c2);
|
||||
auto last2 = container_algorithm_internal::c_end(c2);
|
||||
|
||||
for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
|
||||
if (!pred(*first1, *first2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(first1, first2);
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIterPairType<C1, C2>
|
||||
c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
|
||||
return std::mismatch(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2), pred);
|
||||
}
|
||||
|
||||
// c_equal()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::equal()` function to
|
||||
// test whether two containers are equal.
|
||||
//
|
||||
// NOTE: the semantics of c_equal() are slightly different than those of
|
||||
// equal(): while the latter iterates over the second container only up to the
|
||||
// size of the first container, c_equal() also checks whether the container
|
||||
// sizes are equal. This better matches expectations about c_equal() based on
|
||||
// its signature.
|
||||
//
|
||||
// Example:
|
||||
// vector v1 = <1, 2, 3>;
|
||||
// vector v2 = <1, 2, 3, 4>;
|
||||
// equal(std::begin(v1), std::end(v1), std::begin(v2)) returns true
|
||||
// c_equal(v1, v2) returns false
|
||||
|
||||
template <typename C1, typename C2>
|
||||
bool c_equal(const C1& c1, const C2& c2) {
|
||||
return ((container_algorithm_internal::c_size(c1) ==
|
||||
container_algorithm_internal::c_size(c2)) &&
|
||||
std::equal(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2)));
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) {
|
||||
return std::equal(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2));
|
||||
}
|
||||
|
||||
// Overload of c_equal() for using a predicate evaluation other than `==` as
|
||||
// the function's test condition.
|
||||
template <typename C1, typename C2, typename BinaryPredicate>
|
||||
bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
|
||||
return ((container_algorithm_internal::c_size(c1) ==
|
||||
container_algorithm_internal::c_size(c2)) &&
|
||||
std::equal(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
std::forward<BinaryPredicate>(pred)));
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2,
|
||||
BinaryPredicate&& pred) {
|
||||
return std::equal(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2),
|
||||
std::forward<BinaryPredicate>(pred));
|
||||
}
|
||||
|
||||
// c_is_permutation()
|
||||
|
|
@ -427,21 +417,23 @@ bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
|
|||
// Container-based version of the <algorithm> `std::is_permutation()` function
|
||||
// to test whether a container is a permutation of another.
|
||||
template <typename C1, typename C2>
|
||||
bool c_is_permutation(const C1& c1, const C2& c2) {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return c1.size() == c2.size() &&
|
||||
std::is_permutation(begin(c1), end(c1), begin(c2));
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1,
|
||||
const C2& c2) {
|
||||
return std::is_permutation(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2));
|
||||
}
|
||||
|
||||
// Overload of c_is_permutation() for using a predicate evaluation other than
|
||||
// `==` as the function's test condition.
|
||||
template <typename C1, typename C2, typename BinaryPredicate>
|
||||
bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return c1.size() == c2.size() &&
|
||||
std::is_permutation(begin(c1), end(c1), begin(c2),
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(
|
||||
const C1& c1, const C2& c2, BinaryPredicate&& pred) {
|
||||
return std::is_permutation(container_algorithm_internal::c_begin(c1),
|
||||
container_algorithm_internal::c_end(c1),
|
||||
container_algorithm_internal::c_begin(c2),
|
||||
container_algorithm_internal::c_end(c2),
|
||||
std::forward<BinaryPredicate>(pred));
|
||||
}
|
||||
|
||||
|
|
@ -450,8 +442,9 @@ bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
|
|||
// Container-based version of the <algorithm> `std::search()` function to search
|
||||
// a container for a subsequence.
|
||||
template <typename Sequence1, typename Sequence2>
|
||||
container_algorithm_internal::ContainerIter<Sequence1> c_search(
|
||||
Sequence1& sequence, Sequence2& subsequence) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence1>
|
||||
c_search(Sequence1& sequence, Sequence2& subsequence) {
|
||||
return std::search(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
container_algorithm_internal::c_begin(subsequence),
|
||||
|
|
@ -461,8 +454,10 @@ container_algorithm_internal::ContainerIter<Sequence1> c_search(
|
|||
// Overload of c_search() for using a predicate evaluation other than
|
||||
// `==` as the function's test condition.
|
||||
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
|
||||
container_algorithm_internal::ContainerIter<Sequence1> c_search(
|
||||
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence1>
|
||||
c_search(Sequence1& sequence, Sequence2& subsequence,
|
||||
BinaryPredicate&& pred) {
|
||||
return std::search(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
container_algorithm_internal::c_begin(subsequence),
|
||||
|
|
@ -470,13 +465,35 @@ container_algorithm_internal::ContainerIter<Sequence1> c_search(
|
|||
std::forward<BinaryPredicate>(pred));
|
||||
}
|
||||
|
||||
// c_contains_subrange()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::ranges::contains_subrange()`
|
||||
// C++23 function to search a container for a subsequence.
|
||||
template <typename Sequence1, typename Sequence2>
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
|
||||
Sequence1& sequence, Sequence2& subsequence) {
|
||||
return absl::c_search(sequence, subsequence) !=
|
||||
container_algorithm_internal::c_end(sequence);
|
||||
}
|
||||
|
||||
// Overload of c_contains_subrange() for using a predicate evaluation other than
|
||||
// `==` as the function's test condition.
|
||||
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
|
||||
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
|
||||
return absl::c_search(sequence, subsequence,
|
||||
std::forward<BinaryPredicate>(pred)) !=
|
||||
container_algorithm_internal::c_end(sequence);
|
||||
}
|
||||
|
||||
// c_search_n()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::search_n()` function to
|
||||
// search a container for the first sequence of N elements.
|
||||
template <typename Sequence, typename Size, typename T>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_search_n(
|
||||
Sequence& sequence, Size count, T&& value) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_search_n(Sequence& sequence, Size count, T&& value) {
|
||||
return std::search_n(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence), count,
|
||||
std::forward<T>(value));
|
||||
|
|
@ -486,8 +503,10 @@ container_algorithm_internal::ContainerIter<Sequence> c_search_n(
|
|||
// `==` as the function's test condition.
|
||||
template <typename Sequence, typename Size, typename T,
|
||||
typename BinaryPredicate>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_search_n(
|
||||
Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_search_n(Sequence& sequence, Size count, T&& value,
|
||||
BinaryPredicate&& pred) {
|
||||
return std::search_n(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence), count,
|
||||
std::forward<T>(value),
|
||||
|
|
@ -818,6 +837,20 @@ void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) {
|
|||
std::forward<UniformRandomBitGenerator>(gen));
|
||||
}
|
||||
|
||||
// c_sample()
|
||||
//
|
||||
// Container-based version of the <algorithm> `std::sample()` function to
|
||||
// randomly sample elements from the container without replacement using a
|
||||
// `gen()` uniform random number generator and write them to an iterator range.
|
||||
template <typename C, typename OutputIterator, typename Distance,
|
||||
typename UniformRandomBitGenerator>
|
||||
OutputIterator c_sample(const C& c, OutputIterator result, Distance n,
|
||||
UniformRandomBitGenerator&& gen) {
|
||||
return std::sample(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c), result, n,
|
||||
std::forward<UniformRandomBitGenerator>(gen));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <algorithm> Partition functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -1514,8 +1547,9 @@ c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
|
|||
// to return an iterator pointing to the element with the smallest value, using
|
||||
// `operator<` to make the comparisons.
|
||||
template <typename Sequence>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
|
||||
Sequence& sequence) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_min_element(Sequence& sequence) {
|
||||
return std::min_element(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence));
|
||||
}
|
||||
|
|
@ -1523,8 +1557,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
|
|||
// Overload of c_min_element() for performing a `comp` comparison other than
|
||||
// `operator<`.
|
||||
template <typename Sequence, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
|
||||
Sequence& sequence, LessThan&& comp) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_min_element(Sequence& sequence, LessThan&& comp) {
|
||||
return std::min_element(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<LessThan>(comp));
|
||||
|
|
@ -1536,8 +1571,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
|
|||
// to return an iterator pointing to the element with the largest value, using
|
||||
// `operator<` to make the comparisons.
|
||||
template <typename Sequence>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
|
||||
Sequence& sequence) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_max_element(Sequence& sequence) {
|
||||
return std::max_element(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence));
|
||||
}
|
||||
|
|
@ -1545,8 +1581,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
|
|||
// Overload of c_max_element() for performing a `comp` comparison other than
|
||||
// `operator<`.
|
||||
template <typename Sequence, typename LessThan>
|
||||
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
|
||||
Sequence& sequence, LessThan&& comp) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
container_algorithm_internal::ContainerIter<Sequence>
|
||||
c_max_element(Sequence& sequence, LessThan&& comp) {
|
||||
return std::max_element(container_algorithm_internal::c_begin(sequence),
|
||||
container_algorithm_internal::c_end(sequence),
|
||||
std::forward<LessThan>(comp));
|
||||
|
|
@ -1559,8 +1596,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
|
|||
// smallest and largest values, respectively, using `operator<` to make the
|
||||
// comparisons.
|
||||
template <typename C>
|
||||
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
|
||||
C& c) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
container_algorithm_internal::ContainerIterPairType<C, C>
|
||||
c_minmax_element(C& c) {
|
||||
return std::minmax_element(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c));
|
||||
}
|
||||
|
|
@ -1568,8 +1606,9 @@ container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
|
|||
// Overload of c_minmax_element() for performing `comp` comparisons other than
|
||||
// `operator<`.
|
||||
template <typename C, typename LessThan>
|
||||
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
|
||||
C& c, LessThan&& comp) {
|
||||
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
container_algorithm_internal::ContainerIterPairType<C, C>
|
||||
c_minmax_element(C& c, LessThan&& comp) {
|
||||
return std::minmax_element(container_algorithm_internal::c_begin(c),
|
||||
container_algorithm_internal::c_end(c),
|
||||
std::forward<LessThan>(comp));
|
||||
|
|
@ -1657,7 +1696,7 @@ bool c_prev_permutation(C& c, LessThan&& comp) {
|
|||
//
|
||||
// Container-based version of the <numeric> `std::iota()` function
|
||||
// to compute successive values of `value`, as if incremented with `++value`
|
||||
// after each element is written. and write them to the container.
|
||||
// after each element is written, and write them to the container.
|
||||
template <typename Sequence, typename T>
|
||||
void c_iota(Sequence& sequence, const T& value) {
|
||||
std::iota(container_algorithm_internal::c_begin(sequence),
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
#include "absl/algorithm/container.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
|
|
@ -30,8 +33,10 @@
|
|||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/casts.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/random/random.h"
|
||||
#include "absl/types/span.h"
|
||||
|
||||
namespace {
|
||||
|
|
@ -40,8 +45,10 @@ using ::testing::Each;
|
|||
using ::testing::ElementsAre;
|
||||
using ::testing::Gt;
|
||||
using ::testing::IsNull;
|
||||
using ::testing::IsSubsetOf;
|
||||
using ::testing::Lt;
|
||||
using ::testing::Pointee;
|
||||
using ::testing::SizeIs;
|
||||
using ::testing::Truly;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
|
||||
|
|
@ -110,6 +117,11 @@ TEST_F(NonMutatingTest, FindReturnsCorrectType) {
|
|||
absl::c_find(absl::implicit_cast<const std::list<int>&>(sequence_), 3);
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, Contains) {
|
||||
EXPECT_TRUE(absl::c_contains(container_, 3));
|
||||
EXPECT_FALSE(absl::c_contains(container_, 4));
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, FindIf) { absl::c_find_if(container_, Predicate); }
|
||||
|
||||
TEST_F(NonMutatingTest, FindIfNot) {
|
||||
|
|
@ -129,11 +141,13 @@ TEST_F(NonMutatingTest, FindEndWithPredicate) {
|
|||
TEST_F(NonMutatingTest, FindFirstOf) {
|
||||
absl::c_find_first_of(container_, sequence_);
|
||||
absl::c_find_first_of(sequence_, container_);
|
||||
absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2});
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, FindFirstOfWithPredicate) {
|
||||
absl::c_find_first_of(container_, sequence_, BinPredicate);
|
||||
absl::c_find_first_of(sequence_, container_, BinPredicate);
|
||||
absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2}, BinPredicate);
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, AdjacentFind) { absl::c_adjacent_find(sequence_); }
|
||||
|
|
@ -302,6 +316,17 @@ TEST_F(NonMutatingTest, SearchWithPredicate) {
|
|||
absl::c_search(vector_, sequence_, BinPredicate);
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, ContainsSubrange) {
|
||||
EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_));
|
||||
EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_));
|
||||
EXPECT_TRUE(absl::c_contains_subrange(array_, sequence_));
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, ContainsSubrangeWithPredicate) {
|
||||
EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_, Equals));
|
||||
EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_, Equals));
|
||||
}
|
||||
|
||||
TEST_F(NonMutatingTest, SearchN) { absl::c_search_n(sequence_, 3, 1); }
|
||||
|
||||
TEST_F(NonMutatingTest, SearchNWithPredicate) {
|
||||
|
|
@ -965,10 +990,18 @@ TEST(MutatingTest, RotateCopy) {
|
|||
|
||||
TEST(MutatingTest, Shuffle) {
|
||||
std::vector<int> actual = {1, 2, 3, 4, 5};
|
||||
absl::c_shuffle(actual, std::random_device());
|
||||
absl::c_shuffle(actual, absl::InsecureBitGen());
|
||||
EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5));
|
||||
}
|
||||
|
||||
TEST(MutatingTest, Sample) {
|
||||
std::vector<int> actual;
|
||||
absl::c_sample(std::vector<int>{1, 2, 3, 4, 5}, std::back_inserter(actual), 3,
|
||||
absl::InsecureBitGen());
|
||||
EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5}));
|
||||
EXPECT_THAT(actual, SizeIs(3));
|
||||
}
|
||||
|
||||
TEST(MutatingTest, PartialSort) {
|
||||
std::vector<int> sequence{5, 3, 42, 0};
|
||||
absl::c_partial_sort(sequence, sequence.begin() + 2);
|
||||
|
|
@ -1124,4 +1157,258 @@ TEST(MutatingTest, PermutationOperations) {
|
|||
EXPECT_EQ(initial, permuted);
|
||||
}
|
||||
|
||||
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
|
||||
TEST(ConstexprTest, Distance) {
|
||||
// Works at compile time with constexpr containers.
|
||||
static_assert(absl::c_distance(std::array<int, 3>()) == 3);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, MinElement) {
|
||||
constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(*absl::c_min_element(kArray) == 1);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, MinElementWithPredicate) {
|
||||
constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(*absl::c_min_element(kArray, std::greater<int>()) == 3);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, MaxElement) {
|
||||
constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(*absl::c_max_element(kArray) == 3);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, MaxElementWithPredicate) {
|
||||
constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(*absl::c_max_element(kArray, std::greater<int>()) == 1);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, MinMaxElement) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
constexpr auto kMinMaxPair = absl::c_minmax_element(kArray);
|
||||
static_assert(*kMinMaxPair.first == 1);
|
||||
static_assert(*kMinMaxPair.second == 3);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, MinMaxElementWithPredicate) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
constexpr auto kMinMaxPair =
|
||||
absl::c_minmax_element(kArray, std::greater<int>());
|
||||
static_assert(*kMinMaxPair.first == 3);
|
||||
static_assert(*kMinMaxPair.second == 1);
|
||||
}
|
||||
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
|
||||
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
|
||||
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
|
||||
TEST(ConstexprTest, LinearSearch) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_linear_search(kArray, 3));
|
||||
static_assert(!absl::c_linear_search(kArray, 4));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, AllOf) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(!absl::c_all_of(kArray, [](int x) { return x > 1; }));
|
||||
static_assert(absl::c_all_of(kArray, [](int x) { return x > 0; }));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, AnyOf) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_any_of(kArray, [](int x) { return x > 2; }));
|
||||
static_assert(!absl::c_any_of(kArray, [](int x) { return x > 5; }));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, NoneOf) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(!absl::c_none_of(kArray, [](int x) { return x > 2; }));
|
||||
static_assert(absl::c_none_of(kArray, [](int x) { return x > 5; }));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, ForEach) {
|
||||
static constexpr std::array<int, 3> kArray = [] {
|
||||
std::array<int, 3> array = {1, 2, 3};
|
||||
absl::c_for_each(array, [](int& x) { x += 1; });
|
||||
return array;
|
||||
}();
|
||||
static_assert(kArray == std::array{2, 3, 4});
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, Find) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_find(kArray, 1) == kArray.begin());
|
||||
static_assert(absl::c_find(kArray, 4) == kArray.end());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, Contains) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_contains(kArray, 1));
|
||||
static_assert(!absl::c_contains(kArray, 4));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, FindIf) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_find_if(kArray, [](int x) { return x > 2; }) ==
|
||||
kArray.begin() + 2);
|
||||
static_assert(absl::c_find_if(kArray, [](int x) { return x > 5; }) ==
|
||||
kArray.end());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, FindIfNot) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 1; }) ==
|
||||
kArray.begin());
|
||||
static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 0; }) ==
|
||||
kArray.end());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, FindEnd) {
|
||||
static constexpr std::array<int, 5> kHaystack = {1, 2, 3, 2, 3};
|
||||
static constexpr std::array<int, 2> kNeedle = {2, 3};
|
||||
static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, FindFirstOf) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, AdjacentFind) {
|
||||
static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
|
||||
static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, AdjacentFindWithPredicate) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_adjacent_find(kArray, std::less<int>()) ==
|
||||
kArray.begin());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, Count) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_count(kArray, 1) == 1);
|
||||
static_assert(absl::c_count(kArray, 2) == 1);
|
||||
static_assert(absl::c_count(kArray, 3) == 1);
|
||||
static_assert(absl::c_count(kArray, 4) == 0);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, CountIf) {
|
||||
static constexpr std::array<int, 3> kArray = {1, 2, 3};
|
||||
static_assert(absl::c_count_if(kArray, [](int x) { return x > 0; }) == 3);
|
||||
static_assert(absl::c_count_if(kArray, [](int x) { return x > 1; }) == 2);
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, Mismatch) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_mismatch(kArray1, kArray2) ==
|
||||
std::pair{kArray1.end(), kArray2.end()});
|
||||
static_assert(absl::c_mismatch(kArray1, kArray3) ==
|
||||
std::pair{kArray1.begin(), kArray3.begin()});
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, MismatchWithPredicate) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to<int>()) ==
|
||||
std::pair{kArray1.begin(), kArray2.begin()});
|
||||
static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to<int>()) ==
|
||||
std::pair{kArray1.end(), kArray3.end()});
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, Equal) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_equal(kArray1, kArray2));
|
||||
static_assert(!absl::c_equal(kArray1, kArray3));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, EqualWithPredicate) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to<int>()));
|
||||
static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to<int>()));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, IsPermutation) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_is_permutation(kArray1, kArray2));
|
||||
static_assert(!absl::c_is_permutation(kArray1, kArray3));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, IsPermutationWithPredicate) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to<int>()));
|
||||
static_assert(
|
||||
!absl::c_is_permutation(kArray1, kArray3, std::equal_to<int>()));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, Search) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_search(kArray1, kArray2) == kArray1.begin());
|
||||
static_assert(absl::c_search(kArray1, kArray3) == kArray1.end());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, SearchWithPredicate) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to<int>()) ==
|
||||
kArray1.end());
|
||||
static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to<int>()) ==
|
||||
kArray1.begin());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, ContainsSubrange) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(absl::c_contains_subrange(kArray1, kArray2));
|
||||
static_assert(!absl::c_contains_subrange(kArray1, kArray3));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, ContainsSubrangeWithPredicate) {
|
||||
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
|
||||
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
|
||||
static_assert(
|
||||
!absl::c_contains_subrange(kArray1, kArray2, std::not_equal_to<>()));
|
||||
static_assert(
|
||||
absl::c_contains_subrange(kArray1, kArray3, std::not_equal_to<>()));
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, SearchN) {
|
||||
static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
|
||||
static_assert(absl::c_search_n(kArray, 1, 1) == kArray.begin());
|
||||
static_assert(absl::c_search_n(kArray, 2, 2) == kArray.begin() + 1);
|
||||
static_assert(absl::c_search_n(kArray, 1, 4) == kArray.end());
|
||||
}
|
||||
|
||||
TEST(ConstexprTest, SearchNWithPredicate) {
|
||||
static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
|
||||
static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to<int>()) ==
|
||||
kArray.begin() + 1);
|
||||
static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to<int>()) ==
|
||||
kArray.end());
|
||||
static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to<int>()) ==
|
||||
kArray.begin());
|
||||
}
|
||||
|
||||
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
|
||||
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "absl/algorithm/algorithm.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// The range of sequence sizes to benchmark.
|
||||
constexpr int kMinBenchmarkSize = 1024;
|
||||
constexpr int kMaxBenchmarkSize = 8 * 1024 * 1024;
|
||||
|
||||
// A user-defined type for use in equality benchmarks. Note that we expect
|
||||
// std::memcmp to win for this type: libstdc++'s std::equal only defers to
|
||||
// memcmp for integral types. This is because it is not straightforward to
|
||||
// guarantee that std::memcmp would produce a result "as-if" compared by
|
||||
// operator== for other types (example gotchas: NaN floats, structs with
|
||||
// padding).
|
||||
struct EightBits {
|
||||
explicit EightBits(int /* unused */) : data(0) {}
|
||||
bool operator==(const EightBits& rhs) const { return data == rhs.data; }
|
||||
uint8_t data;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void BM_absl_equal_benchmark(benchmark::State& state) {
|
||||
std::vector<T> xs(state.range(0), T(0));
|
||||
std::vector<T> ys = xs;
|
||||
while (state.KeepRunning()) {
|
||||
const bool same = absl::equal(xs.begin(), xs.end(), ys.begin(), ys.end());
|
||||
benchmark::DoNotOptimize(same);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BM_std_equal_benchmark(benchmark::State& state) {
|
||||
std::vector<T> xs(state.range(0), T(0));
|
||||
std::vector<T> ys = xs;
|
||||
while (state.KeepRunning()) {
|
||||
const bool same = std::equal(xs.begin(), xs.end(), ys.begin());
|
||||
benchmark::DoNotOptimize(same);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BM_memcmp_benchmark(benchmark::State& state) {
|
||||
std::vector<T> xs(state.range(0), T(0));
|
||||
std::vector<T> ys = xs;
|
||||
while (state.KeepRunning()) {
|
||||
const bool same =
|
||||
std::memcmp(xs.data(), ys.data(), xs.size() * sizeof(T)) == 0;
|
||||
benchmark::DoNotOptimize(same);
|
||||
}
|
||||
}
|
||||
|
||||
// The expectation is that the compiler should be able to elide the equality
|
||||
// comparison altogether for sufficiently simple types.
|
||||
template <typename T>
|
||||
void BM_absl_equal_self_benchmark(benchmark::State& state) {
|
||||
std::vector<T> xs(state.range(0), T(0));
|
||||
while (state.KeepRunning()) {
|
||||
const bool same = absl::equal(xs.begin(), xs.end(), xs.begin(), xs.end());
|
||||
benchmark::DoNotOptimize(same);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint8_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint8_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint8_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint8_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint16_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint16_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint16_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint16_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint32_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint32_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint32_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint32_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint64_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint64_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint64_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint64_t)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, EightBits)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_std_equal_benchmark, EightBits)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_memcmp_benchmark, EightBits)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, EightBits)
|
||||
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
|
||||
|
||||
} // namespace
|
||||
|
|
@ -21,7 +21,14 @@ load(
|
|||
"ABSL_TEST_COPTS",
|
||||
)
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
features = [
|
||||
"header_modules",
|
||||
"layering_check",
|
||||
"parse_headers",
|
||||
],
|
||||
)
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
|
|
@ -62,15 +69,26 @@ cc_library(
|
|||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "no_destructor",
|
||||
hdrs = ["no_destructor.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":nullability",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "nullability",
|
||||
srcs = ["internal/nullability_impl.h"],
|
||||
srcs = ["internal/nullability_deprecated.h"],
|
||||
hdrs = ["nullability.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
"//absl/meta:type_traits",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -160,9 +178,6 @@ cc_library(
|
|||
|
||||
cc_library(
|
||||
name = "core_headers",
|
||||
srcs = [
|
||||
"internal/thread_annotations.h",
|
||||
],
|
||||
hdrs = [
|
||||
"attributes.h",
|
||||
"const_init.h",
|
||||
|
|
@ -191,9 +206,8 @@ cc_library(
|
|||
"//conditions:default": [],
|
||||
}),
|
||||
linkopts = select({
|
||||
"//absl:msvc_compiler": [],
|
||||
"//absl:clang-cl_compiler": [],
|
||||
"//absl:wasm": [],
|
||||
"@rules_cc//cc/compiler:msvc-cl": [],
|
||||
"@rules_cc//cc/compiler:clang-cl": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}) + ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
|
|
@ -214,8 +228,6 @@ cc_library(
|
|||
hdrs = [
|
||||
"internal/hide_ptr.h",
|
||||
"internal/identity.h",
|
||||
"internal/inline_variable.h",
|
||||
"internal/invoke.h",
|
||||
"internal/scheduling_mode.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
|
|
@ -252,17 +264,16 @@ cc_library(
|
|||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = select({
|
||||
"//absl:msvc_compiler": [
|
||||
"@rules_cc//cc/compiler:msvc-cl": [
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
],
|
||||
"//absl:clang-cl_compiler": [
|
||||
"@rules_cc//cc/compiler:clang-cl": [
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
],
|
||||
"//absl:mingw_compiler": [
|
||||
"-DEFAULTLIB:advapi32.lib",
|
||||
"-ladvapi32",
|
||||
],
|
||||
"//absl:wasm": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}) + ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
|
|
@ -273,6 +284,7 @@ cc_library(
|
|||
":cycleclock_internal",
|
||||
":dynamic_annotations",
|
||||
":log_severity",
|
||||
":nullability",
|
||||
":raw_logging_internal",
|
||||
":spinlock_wait",
|
||||
"//absl/meta:type_traits",
|
||||
|
|
@ -281,7 +293,7 @@ cc_library(
|
|||
|
||||
cc_library(
|
||||
name = "atomic_hook_test_helper",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
srcs = ["internal/atomic_hook_test_helper.cc"],
|
||||
hdrs = ["internal/atomic_hook_test_helper.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
|
|
@ -302,7 +314,8 @@ cc_test(
|
|||
":atomic_hook",
|
||||
":atomic_hook_test_helper",
|
||||
":core_headers",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -317,7 +330,35 @@ cc_test(
|
|||
deps = [
|
||||
":base",
|
||||
":core_headers",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "attributes_test",
|
||||
srcs = [
|
||||
"attributes_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "c_header_test",
|
||||
srcs = ["c_header_test.c"],
|
||||
tags = [
|
||||
"no_test_wasm",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -344,7 +385,8 @@ cc_test(
|
|||
deps = [
|
||||
":config",
|
||||
":throw_delegate",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -357,13 +399,14 @@ cc_test(
|
|||
deps = [
|
||||
":errno_saver",
|
||||
":strerror",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "exception_testing",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
hdrs = ["internal/exception_testing.h"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
|
|
@ -372,7 +415,7 @@ cc_library(
|
|||
],
|
||||
deps = [
|
||||
":config",
|
||||
"@com_google_googletest//:gtest",
|
||||
"@googletest//:gtest",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -380,12 +423,14 @@ cc_library(
|
|||
name = "pretty_function",
|
||||
hdrs = ["internal/pretty_function.h"],
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = ["//absl:__subpackages__"],
|
||||
visibility = [
|
||||
"//absl:__subpackages__",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "exception_safety_testing",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
srcs = ["internal/exception_safety_testing.cc"],
|
||||
hdrs = ["internal/exception_safety_testing.h"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
|
|
@ -397,7 +442,7 @@ cc_library(
|
|||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
"//absl/utility",
|
||||
"@com_google_googletest//:gtest",
|
||||
"@googletest//:gtest",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -409,38 +454,8 @@ cc_test(
|
|||
deps = [
|
||||
":exception_safety_testing",
|
||||
"//absl/memory",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "inline_variable_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"inline_variable_test.cc",
|
||||
"inline_variable_test_a.cc",
|
||||
"inline_variable_test_b.cc",
|
||||
"internal/inline_variable_testing.h",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":base_internal",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "invoke_test",
|
||||
size = "small",
|
||||
srcs = ["invoke_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":base_internal",
|
||||
"//absl/memory",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -448,7 +463,7 @@ cc_test(
|
|||
# AbslInternalSpinLockDelay and AbslInternalSpinLockWake.
|
||||
cc_library(
|
||||
name = "spinlock_test_common",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
srcs = ["spinlock_test_common.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
|
|
@ -458,7 +473,7 @@ cc_library(
|
|||
":config",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest",
|
||||
"@googletest//:gtest",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
|
@ -478,13 +493,14 @@ cc_test(
|
|||
":config",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "spinlock_benchmark_common",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
srcs = ["internal/spinlock_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
|
|
@ -494,16 +510,17 @@ cc_library(
|
|||
deps = [
|
||||
":base",
|
||||
":base_internal",
|
||||
":no_destructor",
|
||||
":raw_logging_internal",
|
||||
"//absl/synchronization",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
"@google_benchmark//:benchmark_main",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "spinlock_benchmark",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
|
|
@ -521,10 +538,14 @@ cc_library(
|
|||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":base",
|
||||
":config",
|
||||
":core_headers",
|
||||
":nullability",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -535,7 +556,8 @@ cc_test(
|
|||
deps = [
|
||||
":config",
|
||||
":endian",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -547,7 +569,8 @@ cc_test(
|
|||
deps = [
|
||||
":config",
|
||||
"//absl/synchronization:thread_pool",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -560,7 +583,37 @@ cc_test(
|
|||
":base",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "no_destructor_test",
|
||||
srcs = ["no_destructor_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":no_destructor",
|
||||
":raw_logging_internal",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "no_destructor_benchmark",
|
||||
testonly = True,
|
||||
srcs = ["no_destructor_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
tags = ["benchmark"],
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":no_destructor",
|
||||
":raw_logging_internal",
|
||||
"@google_benchmark//:benchmark_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -570,7 +623,18 @@ cc_test(
|
|||
deps = [
|
||||
":core_headers",
|
||||
":nullability",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "nullability_default_nonnull_test",
|
||||
srcs = ["nullability_default_nonnull_test.cc"],
|
||||
deps = [
|
||||
":nullability",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -582,7 +646,8 @@ cc_test(
|
|||
deps = [
|
||||
":raw_logging_internal",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -595,7 +660,8 @@ cc_test(
|
|||
deps = [
|
||||
":base",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -628,12 +694,14 @@ cc_test(
|
|||
":base",
|
||||
":core_headers",
|
||||
"//absl/synchronization",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
cc_binary(
|
||||
name = "thread_identity_benchmark",
|
||||
testonly = True,
|
||||
srcs = ["internal/thread_identity_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
|
|
@ -642,13 +710,13 @@ cc_test(
|
|||
deps = [
|
||||
":base",
|
||||
"//absl/synchronization",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
"@google_benchmark//:benchmark_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "scoped_set_env",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
srcs = ["internal/scoped_set_env.cc"],
|
||||
hdrs = ["internal/scoped_set_env.h"],
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
|
|
@ -669,7 +737,8 @@ cc_test(
|
|||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":scoped_set_env",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -684,7 +753,8 @@ cc_test(
|
|||
"//absl/flags:flag_internal",
|
||||
"//absl/flags:marshalling",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -713,13 +783,14 @@ cc_test(
|
|||
deps = [
|
||||
":strerror",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "strerror_benchmark",
|
||||
testonly = 1,
|
||||
testonly = True,
|
||||
srcs = ["internal/strerror_benchmark.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
|
|
@ -727,18 +798,15 @@ cc_binary(
|
|||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":strerror",
|
||||
"@com_github_google_benchmark//:benchmark_main",
|
||||
"@google_benchmark//:benchmark_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "fast_type_id",
|
||||
hdrs = ["internal/fast_type_id.h"],
|
||||
hdrs = ["fast_type_id.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
],
|
||||
|
|
@ -747,26 +815,27 @@ cc_library(
|
|||
cc_test(
|
||||
name = "fast_type_id_test",
|
||||
size = "small",
|
||||
srcs = ["internal/fast_type_id_test.cc"],
|
||||
srcs = ["fast_type_id_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":core_headers",
|
||||
":fast_type_id",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "prefetch",
|
||||
hdrs = [
|
||||
"internal/prefetch.h",
|
||||
"prefetch.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers", # TODO(b/265984188): remove
|
||||
":core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -774,14 +843,49 @@ cc_test(
|
|||
name = "prefetch_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"internal/prefetch_test.cc",
|
||||
"prefetch_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":prefetch",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "poison",
|
||||
srcs = [
|
||||
"internal/poison.cc",
|
||||
],
|
||||
hdrs = ["internal/poison.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
":malloc_internal",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "poison_test",
|
||||
size = "small",
|
||||
timeout = "short",
|
||||
srcs = [
|
||||
"internal/poison_test.cc",
|
||||
],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":poison",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -795,7 +899,8 @@ cc_test(
|
|||
deps = [
|
||||
":core_headers",
|
||||
"//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -808,6 +913,81 @@ cc_test(
|
|||
deps = [
|
||||
":core_headers",
|
||||
"//absl/types:optional",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "iterator_traits_internal",
|
||||
hdrs = ["internal/iterator_traits.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
"//absl/meta:type_traits",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "iterator_traits_test",
|
||||
srcs = ["internal/iterator_traits_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":iterator_traits_internal",
|
||||
":iterator_traits_test_helper",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "tracing_internal",
|
||||
srcs = ["internal/tracing.cc"],
|
||||
hdrs = ["internal/tracing.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
visibility = [
|
||||
"//absl:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "iterator_traits_test_helper",
|
||||
hdrs = ["internal/iterator_traits_test_helper.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [":config"],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "tracing_internal_weak_test",
|
||||
srcs = ["internal/tracing_weak_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":tracing_internal",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "tracing_internal_strong_test",
|
||||
srcs = ["internal/tracing_strong_test.cc"],
|
||||
copts = ABSL_TEST_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":config",
|
||||
":core_headers",
|
||||
":tracing_internal",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -49,21 +49,34 @@ absl_cc_library(
|
|||
SRCS
|
||||
"log_severity.cc"
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
no_destructor
|
||||
HDRS
|
||||
"no_destructor.h"
|
||||
DEPS
|
||||
absl::config
|
||||
absl::nullability
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
nullability
|
||||
HDRS
|
||||
"nullability.h"
|
||||
SRCS
|
||||
"internal/nullability_impl.h"
|
||||
"internal/nullability_deprecated.h"
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::type_traits
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
)
|
||||
|
|
@ -81,6 +94,18 @@ absl_cc_test(
|
|||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
nullability_default_nonnull_test
|
||||
SRCS
|
||||
"nullability_default_nonnull_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::nullability
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
|
|
@ -155,7 +180,6 @@ absl_cc_library(
|
|||
"optimization.h"
|
||||
"port.h"
|
||||
"thread_annotations.h"
|
||||
"internal/thread_annotations.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
|
|
@ -191,8 +215,6 @@ absl_cc_library(
|
|||
HDRS
|
||||
"internal/hide_ptr.h"
|
||||
"internal/identity.h"
|
||||
"internal/inline_variable.h"
|
||||
"internal/invoke.h"
|
||||
"internal/scheduling_mode.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
|
|
@ -236,6 +258,7 @@ absl_cc_library(
|
|||
absl::core_headers
|
||||
absl::dynamic_annotations
|
||||
absl::log_severity
|
||||
absl::nullability
|
||||
absl::raw_logging_internal
|
||||
absl::spinlock_wait
|
||||
absl::type_traits
|
||||
|
|
@ -345,6 +368,19 @@ absl_cc_test(
|
|||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
attributes_test
|
||||
SRCS
|
||||
"attributes_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
bit_cast_test
|
||||
|
|
@ -386,36 +422,6 @@ absl_cc_test(
|
|||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
inline_variable_test
|
||||
SRCS
|
||||
"internal/inline_variable_testing.h"
|
||||
"inline_variable_test.cc"
|
||||
"inline_variable_test_a.cc"
|
||||
"inline_variable_test_b.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::base_internal
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
invoke_test
|
||||
SRCS
|
||||
"invoke_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::base_internal
|
||||
absl::memory
|
||||
absl::strings
|
||||
GTest::gmock
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
|
|
@ -464,6 +470,7 @@ absl_cc_library(
|
|||
absl::base
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::nullability
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
|
|
@ -508,6 +515,21 @@ absl_cc_test(
|
|||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
no_destructor_test
|
||||
SRCS
|
||||
"no_destructor_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::no_destructor
|
||||
absl::config
|
||||
absl::raw_logging_internal
|
||||
GTest::gmock
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
raw_logging_test
|
||||
|
|
@ -646,12 +668,11 @@ absl_cc_test(
|
|||
GTest::gtest_main
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
fast_type_id
|
||||
HDRS
|
||||
"internal/fast_type_id.h"
|
||||
"fast_type_id.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
|
|
@ -664,10 +685,11 @@ absl_cc_test(
|
|||
NAME
|
||||
fast_type_id_test
|
||||
SRCS
|
||||
"internal/fast_type_id_test.cc"
|
||||
"fast_type_id_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::core_headers
|
||||
absl::fast_type_id
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
|
@ -677,14 +699,13 @@ absl_cc_library(
|
|||
prefetch
|
||||
HDRS
|
||||
"prefetch.h"
|
||||
"internal/prefetch.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers # TODO(b/265984188): remove
|
||||
absl::core_headers
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
|
|
@ -692,7 +713,6 @@ absl_cc_test(
|
|||
prefetch_test
|
||||
SRCS
|
||||
"prefetch_test.cc"
|
||||
"internal/prefetch_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
|
|
@ -712,3 +732,113 @@ absl_cc_test(
|
|||
absl::optional
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
poison
|
||||
SRCS
|
||||
"internal/poison.cc"
|
||||
HDRS
|
||||
"internal/poison.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::malloc_internal
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
poison_test
|
||||
SRCS
|
||||
"internal/poison_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::poison
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
NAME
|
||||
tracing_internal
|
||||
HDRS
|
||||
"internal/tracing.h"
|
||||
SRCS
|
||||
"internal/tracing.cc"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::base
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
tracing_internal_weak_test
|
||||
SRCS
|
||||
"internal/tracing_weak_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::base
|
||||
absl::tracing_internal
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
tracing_internal_strong_test
|
||||
SRCS
|
||||
"internal/tracing_strong_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::base
|
||||
absl::tracing_internal
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
iterator_traits_internal
|
||||
HDRS
|
||||
"internal/iterator_traits.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::type_traits
|
||||
PUBLIC
|
||||
)
|
||||
|
||||
absl_cc_test(
|
||||
NAME
|
||||
iterator_traits_test
|
||||
SRCS
|
||||
"internal/iterator_traits_test.cc"
|
||||
COPTS
|
||||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
absl::iterator_traits_internal
|
||||
absl::iterator_traits_test_helper_internal
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
iterator_traits_test_helper_internal
|
||||
HDRS
|
||||
"internal/iterator_traits_test_helper.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
PUBLIC
|
||||
)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
// `__has_attribute()` first. If the check fails, we check if we are on GCC and
|
||||
// assume the attribute exists on GCC (which is verified on GCC 4.7).
|
||||
|
||||
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
|
||||
|
||||
#ifndef ABSL_BASE_ATTRIBUTES_H_
|
||||
#define ABSL_BASE_ATTRIBUTES_H_
|
||||
|
||||
|
|
@ -133,12 +135,14 @@
|
|||
// Tags a function as weak for the purposes of compilation and linking.
|
||||
// Weak attributes did not work properly in LLVM's Windows backend before
|
||||
// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
|
||||
// for further information.
|
||||
// for further information. Weak attributes do not work across DLL boundary.
|
||||
// The MinGW compiler doesn't complain about the weak attribute until the link
|
||||
// step, presumably because Windows doesn't use ELF binaries.
|
||||
#if (ABSL_HAVE_ATTRIBUTE(weak) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))) && \
|
||||
(!defined(_WIN32) || (defined(__clang__) && __clang_major__ >= 9)) && \
|
||||
#if (ABSL_HAVE_ATTRIBUTE(weak) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))) && \
|
||||
(!defined(_WIN32) || \
|
||||
(defined(__clang__) && __clang_major__ >= 9 && \
|
||||
!defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \
|
||||
!defined(__MINGW32__)
|
||||
#undef ABSL_ATTRIBUTE_WEAK
|
||||
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
|
||||
|
|
@ -195,6 +199,9 @@
|
|||
// ABSL_ATTRIBUTE_NORETURN
|
||||
//
|
||||
// Tells the compiler that a given function never returns.
|
||||
//
|
||||
// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over
|
||||
// this macro.
|
||||
#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
|
|
@ -332,9 +339,9 @@
|
|||
#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE
|
||||
#ifdef _AIX
|
||||
// __attribute__((section(#name))) on AIX is achieved by using the `.csect`
|
||||
// psudo op which includes an additional integer as part of its syntax indcating
|
||||
// alignment. If data fall under different alignments then you might get a
|
||||
// compilation error indicating a `Section type conflict`.
|
||||
// pseudo op which includes an additional integer as part of its syntax
|
||||
// indicating alignment. If data fall under different alignments then you might
|
||||
// get a compilation error indicating a `Section type conflict`.
|
||||
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
|
||||
|
|
@ -546,12 +553,11 @@
|
|||
//
|
||||
// Prevents the compiler from complaining about variables that appear unused.
|
||||
//
|
||||
// For code or headers that are assured to only build with C++17 and up, prefer
|
||||
// just using the standard '[[maybe_unused]]' directly over this macro.
|
||||
// Deprecated: Use the standard C++17 `[[maybe_unused]` instead.
|
||||
//
|
||||
// Due to differences in positioning requirements between the old, compiler
|
||||
// specific __attribute__ syntax and the now standard [[maybe_unused]], this
|
||||
// macro does not attempt to take advantage of '[[maybe_unused]]'.
|
||||
// specific __attribute__ syntax and the now standard `[[maybe_unused]]`, this
|
||||
// macro does not attempt to take advantage of `[[maybe_unused]]`.
|
||||
#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#undef ABSL_ATTRIBUTE_UNUSED
|
||||
#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))
|
||||
|
|
@ -687,7 +693,7 @@
|
|||
|
||||
// When deprecating Abseil code, it is sometimes necessary to turn off the
|
||||
// warning within Abseil, until the deprecated code is actually removed. The
|
||||
// deprecated code can be surrounded with these directives to acheive that
|
||||
// deprecated code can be surrounded with these directives to achieve that
|
||||
// result.
|
||||
//
|
||||
// class ABSL_DEPRECATED("Use Bar instead") Foo;
|
||||
|
|
@ -702,6 +708,11 @@
|
|||
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
#elif defined(_MSC_VER)
|
||||
#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \
|
||||
_Pragma("warning(push)") _Pragma("warning(disable: 4996)")
|
||||
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \
|
||||
_Pragma("warning(pop)")
|
||||
#else
|
||||
#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
|
||||
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
|
||||
|
|
@ -747,9 +758,122 @@
|
|||
#define ABSL_CONST_INIT
|
||||
#endif
|
||||
|
||||
// These annotations are not available yet due to fear of breaking code.
|
||||
#define ABSL_ATTRIBUTE_PURE_FUNCTION
|
||||
#define ABSL_ATTRIBUTE_CONST_FUNCTION
|
||||
// ABSL_REQUIRE_EXPLICIT_INIT
|
||||
//
|
||||
// ABSL_REQUIRE_EXPLICIT_INIT is placed *after* the data members of an aggregate
|
||||
// type to indicate that the annotated member must be explicitly initialized by
|
||||
// the user whenever the aggregate is constructed. For example:
|
||||
//
|
||||
// struct Coord {
|
||||
// int x ABSL_REQUIRE_EXPLICIT_INIT;
|
||||
// int y ABSL_REQUIRE_EXPLICIT_INIT;
|
||||
// };
|
||||
// Coord coord = {1}; // warning: field 'y' is not explicitly initialized
|
||||
//
|
||||
// Note that usage on C arrays is not supported in C++.
|
||||
// Use a struct (such as std::array) to wrap the array member instead.
|
||||
//
|
||||
// Avoid applying this attribute to the members of non-aggregate types.
|
||||
// The behavior within non-aggregates is unspecified and subject to change.
|
||||
//
|
||||
// Do NOT attempt to suppress or demote the error generated by this attribute.
|
||||
// Just like with a missing function argument, it is a hard error by design.
|
||||
//
|
||||
// See the upstream documentation for more details:
|
||||
// https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
|
||||
#ifdef __cplusplus
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_explicit_initialization)
|
||||
// clang-format off
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
[[clang::require_explicit_initialization]] = \
|
||||
AbslInternal_YouForgotToExplicitlyInitializeAField::v
|
||||
#else
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
= AbslInternal_YouForgotToExplicitlyInitializeAField::v
|
||||
#endif
|
||||
// clang-format on
|
||||
#else
|
||||
// clang-format off
|
||||
#if ABSL_HAVE_ATTRIBUTE(require_explicit_initialization)
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
__attribute__((require_explicit_initialization))
|
||||
#else
|
||||
#define ABSL_REQUIRE_EXPLICIT_INIT \
|
||||
/* No portable fallback for C is available */
|
||||
#endif
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct AbslInternal_YouForgotToExplicitlyInitializeAField {
|
||||
// A portable version of [[clang::require_explicit_initialization]] that
|
||||
// never builds, as a last resort for all toolchains.
|
||||
// The error messages are poor, so we don't rely on this unless we have to.
|
||||
template <class T>
|
||||
#if !defined(SWIG)
|
||||
constexpr
|
||||
#endif
|
||||
operator T() const /* NOLINT */ {
|
||||
const void *volatile deliberately_volatile_ptr = nullptr;
|
||||
// Infinite loop to prevent constexpr compilation
|
||||
for (;;) {
|
||||
// This assignment ensures the 'this' pointer is not optimized away, so
|
||||
// that linking always fails.
|
||||
deliberately_volatile_ptr = this; // Deliberately not constexpr
|
||||
(void)deliberately_volatile_ptr;
|
||||
}
|
||||
}
|
||||
// This is deliberately left undefined to prevent linking
|
||||
static AbslInternal_YouForgotToExplicitlyInitializeAField v;
|
||||
};
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION
|
||||
//
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
|
||||
// functions. A function is pure if its return value is only a function of its
|
||||
// arguments. The pure attribute prohibits a function from modifying the state
|
||||
// of the program that is observable by means other than inspecting the
|
||||
// function's return value. Declaring such functions with the pure attribute
|
||||
// allows the compiler to avoid emitting some calls in repeated invocations of
|
||||
// the function with the same argument values.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t);
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)
|
||||
#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]
|
||||
#elif ABSL_HAVE_ATTRIBUTE(pure)
|
||||
#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))
|
||||
#else
|
||||
// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since
|
||||
// pure functions are useless if its return is ignored.
|
||||
#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_CONST_FUNCTION
|
||||
//
|
||||
// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const"
|
||||
// functions. A const function is similar to a pure function, with one
|
||||
// exception: Pure functions may return value that depend on a non-volatile
|
||||
// object that isn't provided as a function argument, while the const function
|
||||
// is guaranteed to return the same result given the same arguments.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d);
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// Put the MSVC case first since MSVC seems to parse const as a C++ keyword.
|
||||
#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION
|
||||
#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const)
|
||||
#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]]
|
||||
#elif ABSL_HAVE_ATTRIBUTE(const)
|
||||
#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const))
|
||||
#else
|
||||
// Since const functions are more restrictive pure function, we'll fallback to a
|
||||
// pure function if the const attribute is not handled.
|
||||
#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
|
||||
// parameter or implicit object parameter is retained by the return value of the
|
||||
|
|
@ -765,14 +889,89 @@
|
|||
//
|
||||
// See also the upstream documentation:
|
||||
// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
|
||||
// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
|
||||
#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
|
||||
#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound)
|
||||
#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]]
|
||||
#elif ABSL_HAVE_ATTRIBUTE(lifetimebound)
|
||||
#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_LIFETIME_BOUND
|
||||
#endif
|
||||
|
||||
// Internal attribute; name and documentation TBD.
|
||||
//
|
||||
// See the upstream documentation:
|
||||
// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by)
|
||||
#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) \
|
||||
[[clang::lifetime_capture_by(Owner)]]
|
||||
#else
|
||||
#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner)
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it
|
||||
// points to, similarly to a span, string_view, or other non-owning reference
|
||||
// type.
|
||||
// This enables diagnosing certain lifetime issues similar to those enabled by
|
||||
// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
|
||||
//
|
||||
// struct ABSL_ATTRIBUTE_VIEW StringView {
|
||||
// template<class R>
|
||||
// StringView(const R&);
|
||||
// };
|
||||
//
|
||||
// StringView f(std::string s) {
|
||||
// return s; // warning: address of stack memory returned
|
||||
// }
|
||||
//
|
||||
// We disable this on Clang versions < 13 because of the following
|
||||
// false-positive:
|
||||
//
|
||||
// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
|
||||
//
|
||||
// See the following links for details:
|
||||
// https://reviews.llvm.org/D64448
|
||||
// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \
|
||||
(!defined(__clang_major__) || __clang_major__ >= 13)
|
||||
#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]]
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_VIEW
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or
|
||||
// similar class that owns all the data that it points to.
|
||||
// This enables diagnosing certain lifetime issues similar to those enabled by
|
||||
// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
|
||||
//
|
||||
// struct ABSL_ATTRIBUTE_VIEW StringView {
|
||||
// template<class R>
|
||||
// StringView(const R&);
|
||||
// };
|
||||
//
|
||||
// struct ABSL_ATTRIBUTE_OWNER String {};
|
||||
//
|
||||
// StringView f(String s) {
|
||||
// return s; // warning: address of stack memory returned
|
||||
// }
|
||||
//
|
||||
// We disable this on Clang versions < 13 because of the following
|
||||
// false-positive:
|
||||
//
|
||||
// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
|
||||
//
|
||||
// See the following links for details:
|
||||
// https://reviews.llvm.org/D64448
|
||||
// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \
|
||||
(!defined(__clang_major__) || __clang_major__ >= 13)
|
||||
#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]]
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_OWNER
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_TRIVIAL_ABI
|
||||
// Indicates that a type is "trivially relocatable" -- meaning it can be
|
||||
// relocated without invoking the constructor/destructor, using a form of move
|
||||
|
|
@ -800,15 +999,11 @@
|
|||
// See also the upstream documentation:
|
||||
// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
|
||||
//
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::trivial_abi)
|
||||
#define ABSL_ATTRIBUTE_TRIVIAL_ABI [[clang::trivial_abi]]
|
||||
#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
|
||||
#elif ABSL_HAVE_ATTRIBUTE(trivial_abi)
|
||||
#define ABSL_ATTRIBUTE_TRIVIAL_ABI __attribute__((trivial_abi))
|
||||
#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
|
||||
#else
|
||||
// b/321691395 - This is currently disabled in open-source builds since
|
||||
// compiler support differs. If system libraries compiled with GCC are mixed
|
||||
// with libraries compiled with Clang, types will have different ideas about
|
||||
// their ABI, leading to hard to debug crashes.
|
||||
#define ABSL_ATTRIBUTE_TRIVIAL_ABI
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
|
||||
//
|
||||
|
|
@ -832,4 +1027,51 @@
|
|||
#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_UNINITIALIZED
|
||||
//
|
||||
// GCC and Clang support a flag `-ftrivial-auto-var-init=<option>` (<option>
|
||||
// can be "zero" or "pattern") that can be used to initialize automatic stack
|
||||
// variables. Variables with this attribute will be left uninitialized,
|
||||
// overriding the compiler flag.
|
||||
//
|
||||
// See https://clang.llvm.org/docs/AttributeReference.html#uninitialized
|
||||
// and https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-uninitialized-variable-attribute
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::uninitialized)
|
||||
#define ABSL_ATTRIBUTE_UNINITIALIZED [[clang::uninitialized]]
|
||||
#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::uninitialized)
|
||||
#define ABSL_ATTRIBUTE_UNINITIALIZED [[gnu::uninitialized]]
|
||||
#elif ABSL_HAVE_ATTRIBUTE(uninitialized)
|
||||
#define ABSL_ATTRIBUTE_UNINITIALIZED __attribute__((uninitialized))
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_UNINITIALIZED
|
||||
#endif
|
||||
|
||||
// ABSL_ATTRIBUTE_WARN_UNUSED
|
||||
//
|
||||
// Compilers routinely warn about trivial variables that are unused. For
|
||||
// non-trivial types, this warning is suppressed since the
|
||||
// constructor/destructor may be intentional and load-bearing, for example, with
|
||||
// a RAII scoped lock.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// class ABSL_ATTRIBUTE_WARN_UNUSED MyType {
|
||||
// public:
|
||||
// MyType();
|
||||
// ~MyType();
|
||||
// };
|
||||
//
|
||||
// void foo() {
|
||||
// // Warns with ABSL_ATTRIBUTE_WARN_UNUSED attribute present.
|
||||
// MyType unused;
|
||||
// }
|
||||
//
|
||||
// See https://clang.llvm.org/docs/AttributeReference.html#warn-unused and
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-warn_005funused-type-attribute
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::warn_unused)
|
||||
#define ABSL_ATTRIBUTE_WARN_UNUSED [[gnu::warn_unused]]
|
||||
#else
|
||||
#define ABSL_ATTRIBUTE_WARN_UNUSED
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_ATTRIBUTES_H_
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2025 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(Attributes, RequireExplicitInit) {
|
||||
struct Agg {
|
||||
int f1;
|
||||
int f2 ABSL_REQUIRE_EXPLICIT_INIT;
|
||||
};
|
||||
Agg good1 ABSL_ATTRIBUTE_UNUSED = {1, 2};
|
||||
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
Agg good2 ABSL_ATTRIBUTE_UNUSED(1, 2);
|
||||
#endif
|
||||
Agg good3 ABSL_ATTRIBUTE_UNUSED{1, 2};
|
||||
Agg good4 ABSL_ATTRIBUTE_UNUSED = {1, 2};
|
||||
Agg good5 ABSL_ATTRIBUTE_UNUSED = Agg{1, 2};
|
||||
Agg good6[1] ABSL_ATTRIBUTE_UNUSED = {{1, 2}};
|
||||
Agg good7[1] ABSL_ATTRIBUTE_UNUSED = {Agg{1, 2}};
|
||||
union {
|
||||
Agg agg;
|
||||
} good8 ABSL_ATTRIBUTE_UNUSED = {{1, 2}};
|
||||
constexpr Agg good9 ABSL_ATTRIBUTE_UNUSED = {1, 2};
|
||||
constexpr Agg good10 ABSL_ATTRIBUTE_UNUSED{1, 2};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifdef __cplusplus
|
||||
#error This is a C compile test
|
||||
#endif
|
||||
|
||||
// This test ensures that headers that are included in legacy C code are
|
||||
// compatible with C. Abseil is a C++ library. We do not desire to expand C
|
||||
// compatibility or keep C compatibility forever. This test only exists to
|
||||
// ensure C compatibility until it is no longer required. Do not add new code
|
||||
// that requires C compatibility.
|
||||
#include "absl/base/attributes.h" // IWYU pragma: keep
|
||||
#include "absl/base/config.h" // IWYU pragma: keep
|
||||
#include "absl/base/optimization.h" // IWYU pragma: keep
|
||||
#include "absl/base/policy_checks.h" // IWYU pragma: keep
|
||||
#include "absl/base/port.h" // IWYU pragma: keep
|
||||
|
||||
int main() { return 0; }
|
||||
|
|
@ -28,15 +28,18 @@
|
|||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/internal/invoke.h"
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/low_level_scheduling.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/scheduling_mode.h"
|
||||
#include "absl/base/internal/spinlock_wait.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/base/optimization.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
|
|
@ -46,7 +49,8 @@ ABSL_NAMESPACE_BEGIN
|
|||
class once_flag;
|
||||
|
||||
namespace base_internal {
|
||||
std::atomic<uint32_t>* ControlWord(absl::once_flag* flag);
|
||||
std::atomic<uint32_t>* absl_nonnull ControlWord(
|
||||
absl::once_flag* absl_nonnull flag);
|
||||
} // namespace base_internal
|
||||
|
||||
// call_once()
|
||||
|
|
@ -89,7 +93,8 @@ class once_flag {
|
|||
once_flag& operator=(const once_flag&) = delete;
|
||||
|
||||
private:
|
||||
friend std::atomic<uint32_t>* base_internal::ControlWord(once_flag* flag);
|
||||
friend std::atomic<uint32_t>* absl_nonnull base_internal::ControlWord(
|
||||
once_flag* absl_nonnull flag);
|
||||
std::atomic<uint32_t> control_;
|
||||
};
|
||||
|
||||
|
|
@ -103,7 +108,8 @@ namespace base_internal {
|
|||
// Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to
|
||||
// initialize entities used by the scheduler implementation.
|
||||
template <typename Callable, typename... Args>
|
||||
void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args);
|
||||
void LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,
|
||||
Args&&... args);
|
||||
|
||||
// Disables scheduling while on stack when scheduling mode is non-cooperative.
|
||||
// No effect for cooperative scheduling modes.
|
||||
|
|
@ -143,10 +149,10 @@ enum {
|
|||
};
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
void CallOnceImpl(std::atomic<uint32_t>* control,
|
||||
base_internal::SchedulingMode scheduling_mode, Callable&& fn,
|
||||
Args&&... args) {
|
||||
void
|
||||
CallOnceImpl(std::atomic<uint32_t>* absl_nonnull control,
|
||||
base_internal::SchedulingMode scheduling_mode, Callable&& fn,
|
||||
Args&&... args) {
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
uint32_t old_control = control->load(std::memory_order_relaxed);
|
||||
|
|
@ -175,8 +181,7 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
|
|||
std::memory_order_relaxed) ||
|
||||
base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
|
||||
scheduling_mode) == kOnceInit) {
|
||||
base_internal::invoke(std::forward<Callable>(fn),
|
||||
std::forward<Args>(args)...);
|
||||
std::invoke(std::forward<Callable>(fn), std::forward<Args>(args)...);
|
||||
old_control =
|
||||
control->exchange(base_internal::kOnceDone, std::memory_order_release);
|
||||
if (old_control == base_internal::kOnceWaiter) {
|
||||
|
|
@ -185,12 +190,14 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
|
|||
} // else *control is already kOnceDone
|
||||
}
|
||||
|
||||
inline std::atomic<uint32_t>* ControlWord(once_flag* flag) {
|
||||
inline std::atomic<uint32_t>* absl_nonnull ControlWord(
|
||||
once_flag* absl_nonnull flag) {
|
||||
return &flag->control_;
|
||||
}
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args) {
|
||||
void LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,
|
||||
Args&&... args) {
|
||||
std::atomic<uint32_t>* once = base_internal::ControlWord(flag);
|
||||
uint32_t s = once->load(std::memory_order_acquire);
|
||||
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
|
||||
|
|
@ -203,7 +210,8 @@ void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args) {
|
|||
} // namespace base_internal
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
|
||||
void
|
||||
call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
|
||||
std::atomic<uint32_t>* once = base_internal::ControlWord(&flag);
|
||||
uint32_t s = once->load(std::memory_order_acquire);
|
||||
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ ABSL_NAMESPACE_BEGIN
|
|||
//
|
||||
// Such implicit cast chaining may be useful within template logic.
|
||||
template <typename To>
|
||||
constexpr To implicit_cast(typename absl::internal::identity_t<To> to) {
|
||||
constexpr To implicit_cast(typename absl::internal::type_identity_t<To> to) {
|
||||
return to;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@
|
|||
#define ABSL_INTERNAL_CPLUSPLUS_LANG __cplusplus
|
||||
#endif
|
||||
|
||||
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
// Include library feature test macros.
|
||||
#include <version>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED,
|
||||
// __IPHONE_8_0.
|
||||
|
|
@ -111,7 +117,7 @@
|
|||
//
|
||||
// LTS releases can be obtained from
|
||||
// https://github.com/abseil/abseil-cpp/releases.
|
||||
#define ABSL_LTS_RELEASE_VERSION 20230802
|
||||
#define ABSL_LTS_RELEASE_VERSION 20250512
|
||||
#define ABSL_LTS_RELEASE_PATCH_LEVEL 1
|
||||
|
||||
// Helper macro to convert a CPP variable to a string literal.
|
||||
|
|
@ -225,12 +231,11 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
#endif
|
||||
|
||||
// ABSL_HAVE_TLS is defined to 1 when __thread should be supported.
|
||||
// We assume __thread is supported on Linux or Asylo when compiled with Clang or
|
||||
// We assume __thread is supported on Linux when compiled with Clang or
|
||||
// compiled against libstdc++ with _GLIBCXX_HAVE_TLS defined.
|
||||
#ifdef ABSL_HAVE_TLS
|
||||
#error ABSL_HAVE_TLS cannot be directly set
|
||||
#elif (defined(__linux__) || defined(__ASYLO__)) && \
|
||||
(defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
|
||||
#elif (defined(__linux__)) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
|
||||
#define ABSL_HAVE_TLS 1
|
||||
#endif
|
||||
|
||||
|
|
@ -271,50 +276,12 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
|
||||
// ABSL_HAVE_THREAD_LOCAL
|
||||
//
|
||||
// Checks whether C++11's `thread_local` storage duration specifier is
|
||||
// supported.
|
||||
// Checks whether the `thread_local` storage duration specifier is supported.
|
||||
#ifdef ABSL_HAVE_THREAD_LOCAL
|
||||
#error ABSL_HAVE_THREAD_LOCAL cannot be directly set
|
||||
#elif defined(__APPLE__)
|
||||
// Notes:
|
||||
// * Xcode's clang did not support `thread_local` until version 8, and
|
||||
// even then not for all iOS < 9.0.
|
||||
// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
|
||||
// targeting iOS 9.x.
|
||||
// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
|
||||
// making ABSL_HAVE_FEATURE unreliable there.
|
||||
//
|
||||
#if ABSL_HAVE_FEATURE(cxx_thread_local) && \
|
||||
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
|
||||
#elif !defined(__XTENSA__)
|
||||
#define ABSL_HAVE_THREAD_LOCAL 1
|
||||
#endif
|
||||
#else // !defined(__APPLE__)
|
||||
#define ABSL_HAVE_THREAD_LOCAL 1
|
||||
#endif
|
||||
|
||||
// There are platforms for which TLS should not be used even though the compiler
|
||||
// makes it seem like it's supported (Android NDK < r12b for example).
|
||||
// This is primarily because of linker problems and toolchain misconfiguration:
|
||||
// Abseil does not intend to support this indefinitely. Currently, the newest
|
||||
// toolchain that we intend to support that requires this behavior is the
|
||||
// r11 NDK - allowing for a 5 year support window on that means this option
|
||||
// is likely to be removed around June of 2021.
|
||||
// TLS isn't supported until NDK r12b per
|
||||
// https://developer.android.com/ndk/downloads/revision_history.html
|
||||
// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in
|
||||
// <android/ndk-version.h>. For NDK < r16, users should define these macros,
|
||||
// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11.
|
||||
#if defined(__ANDROID__) && defined(__clang__)
|
||||
#if __has_include(<android/ndk-version.h>)
|
||||
#include <android/ndk-version.h>
|
||||
#endif // __has_include(<android/ndk-version.h>)
|
||||
#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \
|
||||
defined(__NDK_MINOR__) && \
|
||||
((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1)))
|
||||
#undef ABSL_HAVE_TLS
|
||||
#undef ABSL_HAVE_THREAD_LOCAL
|
||||
#endif
|
||||
#endif // defined(__ANDROID__) && defined(__clang__)
|
||||
|
||||
// ABSL_HAVE_INTRINSIC_INT128
|
||||
//
|
||||
|
|
@ -332,8 +299,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
#ifdef ABSL_HAVE_INTRINSIC_INT128
|
||||
#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set
|
||||
#elif defined(__SIZEOF_INT128__)
|
||||
#if (defined(__clang__) && !defined(_WIN32)) || \
|
||||
(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \
|
||||
#if (defined(__clang__) && !defined(_WIN32)) || \
|
||||
(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \
|
||||
(defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))
|
||||
#define ABSL_HAVE_INTRINSIC_INT128 1
|
||||
#elif defined(__CUDACC__)
|
||||
|
|
@ -373,9 +340,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
#define ABSL_HAVE_EXCEPTIONS 1
|
||||
#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
|
||||
// Handle remaining special cases and default to exceptions being supported.
|
||||
#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \
|
||||
!(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) && \
|
||||
!defined(__cpp_exceptions)) && \
|
||||
#elif !(defined(__GNUC__) && !defined(__cpp_exceptions)) && \
|
||||
!(defined(_MSC_VER) && !defined(_CPPUNWIND))
|
||||
#define ABSL_HAVE_EXCEPTIONS 1
|
||||
#endif
|
||||
|
|
@ -395,7 +360,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
// Windows _WIN32
|
||||
// NaCL __native_client__
|
||||
// AsmJS __asmjs__
|
||||
// WebAssembly __wasm__
|
||||
// WebAssembly (Emscripten) __EMSCRIPTEN__
|
||||
// Fuchsia __Fuchsia__
|
||||
//
|
||||
// Note that since Android defines both __ANDROID__ and __linux__, one
|
||||
|
|
@ -407,12 +372,12 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
// POSIX.1-2001.
|
||||
#ifdef ABSL_HAVE_MMAP
|
||||
#error ABSL_HAVE_MMAP cannot be directly set
|
||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(_AIX) || defined(__ros__) || defined(__native_client__) || \
|
||||
defined(__asmjs__) || defined(__wasm__) || defined(__Fuchsia__) || \
|
||||
defined(__sun) || defined(__ASYLO__) || defined(__myriad2__) || \
|
||||
defined(__HAIKU__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
|
||||
defined(__QNX__) || defined(__VXWORKS__) || defined(__hexagon__)
|
||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(_AIX) || defined(__ros__) || defined(__native_client__) || \
|
||||
defined(__asmjs__) || defined(__EMSCRIPTEN__) || defined(__Fuchsia__) || \
|
||||
defined(__sun) || defined(__myriad2__) || defined(__HAIKU__) || \
|
||||
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) || \
|
||||
defined(__VXWORKS__) || defined(__hexagon__) || defined(__XTENSA__)
|
||||
#define ABSL_HAVE_MMAP 1
|
||||
#endif
|
||||
|
||||
|
|
@ -484,6 +449,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
// emscripten doesn't support signals
|
||||
#elif defined(__wasi__)
|
||||
// WASI doesn't support signals
|
||||
#elif defined(__Fuchsia__)
|
||||
// Signals don't exist on fuchsia.
|
||||
#elif defined(__native_client__)
|
||||
|
|
@ -499,6 +466,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
//
|
||||
// Checks the endianness of the platform.
|
||||
//
|
||||
// Prefer using `std::endian` in C++20, or `absl::endian` from
|
||||
// absl/numeric/bits.h prior to C++20.
|
||||
//
|
||||
// Notes: uses the built in endian macros provided by GCC (since 4.6) and
|
||||
// Clang (since 3.2); see
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html.
|
||||
|
|
@ -536,106 +506,53 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
// and
|
||||
// https://github.com/llvm/llvm-project/commit/0bc451e7e137c4ccadcd3377250874f641ca514a
|
||||
// The second has the actually correct versions, thus, is what we copy here.
|
||||
#if defined(__APPLE__) && \
|
||||
((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \
|
||||
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
|
||||
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
|
||||
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
|
||||
#if defined(__APPLE__) && \
|
||||
((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \
|
||||
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
|
||||
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
|
||||
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
|
||||
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
|
||||
#else
|
||||
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
|
||||
#endif
|
||||
|
||||
// ABSL_HAVE_STD_ANY
|
||||
//
|
||||
// Checks whether C++17 std::any is available.
|
||||
#ifdef ABSL_HAVE_STD_ANY
|
||||
#error "ABSL_HAVE_STD_ANY cannot be directly set."
|
||||
#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
|
||||
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
// Deprecated macros for polyfill detection.
|
||||
#define ABSL_HAVE_STD_ANY 1
|
||||
#endif
|
||||
|
||||
// ABSL_HAVE_STD_OPTIONAL
|
||||
//
|
||||
// Checks whether C++17 std::optional is available.
|
||||
#ifdef ABSL_HAVE_STD_OPTIONAL
|
||||
#error "ABSL_HAVE_STD_OPTIONAL cannot be directly set."
|
||||
#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
|
||||
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
#define ABSL_USES_STD_ANY 1
|
||||
#define ABSL_HAVE_STD_OPTIONAL 1
|
||||
#endif
|
||||
|
||||
// ABSL_HAVE_STD_VARIANT
|
||||
//
|
||||
// Checks whether C++17 std::variant is available.
|
||||
#ifdef ABSL_HAVE_STD_VARIANT
|
||||
#error "ABSL_HAVE_STD_VARIANT cannot be directly set."
|
||||
#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
|
||||
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
|
||||
#define ABSL_USES_STD_OPTIONAL 1
|
||||
#define ABSL_HAVE_STD_VARIANT 1
|
||||
#endif
|
||||
#define ABSL_USES_STD_VARIANT 1
|
||||
|
||||
// ABSL_HAVE_STD_STRING_VIEW
|
||||
//
|
||||
// Checks whether C++17 std::string_view is available.
|
||||
// Deprecated: always defined to 1.
|
||||
// std::string_view was added in C++17, which means all versions of C++
|
||||
// supported by Abseil have it.
|
||||
#ifdef ABSL_HAVE_STD_STRING_VIEW
|
||||
#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set."
|
||||
#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
#else
|
||||
#define ABSL_HAVE_STD_STRING_VIEW 1
|
||||
#endif
|
||||
|
||||
// ABSL_USES_STD_ANY
|
||||
// ABSL_HAVE_STD_ORDERING
|
||||
//
|
||||
// Indicates whether absl::any is an alias for std::any.
|
||||
#if !defined(ABSL_OPTION_USE_STD_ANY)
|
||||
#error options.h is misconfigured.
|
||||
#elif ABSL_OPTION_USE_STD_ANY == 0 || \
|
||||
(ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY))
|
||||
#undef ABSL_USES_STD_ANY
|
||||
#elif ABSL_OPTION_USE_STD_ANY == 1 || \
|
||||
(ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY))
|
||||
#define ABSL_USES_STD_ANY 1
|
||||
#else
|
||||
#error options.h is misconfigured.
|
||||
#endif
|
||||
|
||||
// ABSL_USES_STD_OPTIONAL
|
||||
// Checks whether C++20 std::{partial,weak,strong}_ordering are available.
|
||||
//
|
||||
// Indicates whether absl::optional is an alias for std::optional.
|
||||
#if !defined(ABSL_OPTION_USE_STD_OPTIONAL)
|
||||
#error options.h is misconfigured.
|
||||
#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \
|
||||
(ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL))
|
||||
#undef ABSL_USES_STD_OPTIONAL
|
||||
#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \
|
||||
(ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL))
|
||||
#define ABSL_USES_STD_OPTIONAL 1
|
||||
#else
|
||||
#error options.h is misconfigured.
|
||||
#endif
|
||||
|
||||
// ABSL_USES_STD_VARIANT
|
||||
//
|
||||
// Indicates whether absl::variant is an alias for std::variant.
|
||||
#if !defined(ABSL_OPTION_USE_STD_VARIANT)
|
||||
#error options.h is misconfigured.
|
||||
#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \
|
||||
(ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT))
|
||||
#undef ABSL_USES_STD_VARIANT
|
||||
#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \
|
||||
(ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT))
|
||||
#define ABSL_USES_STD_VARIANT 1
|
||||
#else
|
||||
#error options.h is misconfigured.
|
||||
// __cpp_lib_three_way_comparison is missing on libc++
|
||||
// (https://github.com/llvm/llvm-project/issues/73953) so treat it as defined
|
||||
// when building in C++20 mode.
|
||||
#ifdef ABSL_HAVE_STD_ORDERING
|
||||
#error "ABSL_HAVE_STD_ORDERING cannot be directly set."
|
||||
#elif (defined(__cpp_lib_three_way_comparison) && \
|
||||
__cpp_lib_three_way_comparison >= 201907L) || \
|
||||
(defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L)
|
||||
#define ABSL_HAVE_STD_ORDERING 1
|
||||
#endif
|
||||
|
||||
// ABSL_USES_STD_STRING_VIEW
|
||||
|
|
@ -643,24 +560,29 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
// Indicates whether absl::string_view is an alias for std::string_view.
|
||||
#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW)
|
||||
#error options.h is misconfigured.
|
||||
#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \
|
||||
(ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \
|
||||
!defined(ABSL_HAVE_STD_STRING_VIEW))
|
||||
#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0
|
||||
#undef ABSL_USES_STD_STRING_VIEW
|
||||
#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \
|
||||
(ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \
|
||||
defined(ABSL_HAVE_STD_STRING_VIEW))
|
||||
ABSL_OPTION_USE_STD_STRING_VIEW == 2
|
||||
#define ABSL_USES_STD_STRING_VIEW 1
|
||||
#else
|
||||
#error options.h is misconfigured.
|
||||
#endif
|
||||
|
||||
// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
|
||||
// SEH exception from emplace for variant<SomeStruct> when constructing the
|
||||
// struct can throw. This defeats some of variant_test and
|
||||
// variant_exception_safety_test.
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG)
|
||||
#define ABSL_INTERNAL_MSVC_2017_DBG_MODE
|
||||
// ABSL_USES_STD_ORDERING
|
||||
//
|
||||
// Indicates whether absl::{partial,weak,strong}_ordering are aliases for the
|
||||
// std:: ordering types.
|
||||
#if !defined(ABSL_OPTION_USE_STD_ORDERING)
|
||||
#error options.h is misconfigured.
|
||||
#elif ABSL_OPTION_USE_STD_ORDERING == 0 || \
|
||||
(ABSL_OPTION_USE_STD_ORDERING == 2 && !defined(ABSL_HAVE_STD_ORDERING))
|
||||
#undef ABSL_USES_STD_ORDERING
|
||||
#elif ABSL_OPTION_USE_STD_ORDERING == 1 || \
|
||||
(ABSL_OPTION_USE_STD_ORDERING == 2 && defined(ABSL_HAVE_STD_ORDERING))
|
||||
#define ABSL_USES_STD_ORDERING 1
|
||||
#else
|
||||
#error options.h is misconfigured.
|
||||
#endif
|
||||
|
||||
// ABSL_INTERNAL_MANGLED_NS
|
||||
|
|
@ -803,45 +725,41 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
|
||||
// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
|
||||
//
|
||||
// Class template argument deduction is a language feature added in C++17.
|
||||
// Deprecated: always defined to 1.
|
||||
// Class template argument deduction is a language feature added in C++17,
|
||||
// which means all versions of C++ supported by Abseil have it.
|
||||
#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
|
||||
#error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set."
|
||||
#elif defined(__cpp_deduction_guides)
|
||||
#else
|
||||
#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1
|
||||
#endif
|
||||
|
||||
// ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
//
|
||||
// Prior to C++17, static constexpr variables defined in classes required a
|
||||
// separate definition outside of the class body, for example:
|
||||
//
|
||||
// class Foo {
|
||||
// static constexpr int kBar = 0;
|
||||
// };
|
||||
// constexpr int Foo::kBar;
|
||||
//
|
||||
// In C++17, these variables defined in classes are considered inline variables,
|
||||
// and the extra declaration is redundant. Since some compilers warn on the
|
||||
// extra declarations, ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL can be used
|
||||
// conditionally ignore them:
|
||||
//
|
||||
// #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
// constexpr int Foo::kBar;
|
||||
// #endif
|
||||
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG < 201703L
|
||||
#define ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
|
||||
#endif
|
||||
|
||||
// `ABSL_INTERNAL_HAS_RTTI` determines whether abseil is being compiled with
|
||||
// RTTI support.
|
||||
#ifdef ABSL_INTERNAL_HAS_RTTI
|
||||
#error ABSL_INTERNAL_HAS_RTTI cannot be directly set
|
||||
#elif (defined(__GNUC__) && defined(__GXX_RTTI)) || \
|
||||
(defined(_MSC_VER) && defined(_CPPRTTI)) || \
|
||||
(!defined(__GNUC__) && !defined(_MSC_VER))
|
||||
#elif ABSL_HAVE_FEATURE(cxx_rtti)
|
||||
#define ABSL_INTERNAL_HAS_RTTI 1
|
||||
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
|
||||
#elif defined(__GNUC__) && defined(__GXX_RTTI)
|
||||
#define ABSL_INTERNAL_HAS_RTTI 1
|
||||
#elif defined(_MSC_VER) && defined(_CPPRTTI)
|
||||
#define ABSL_INTERNAL_HAS_RTTI 1
|
||||
#elif !defined(__GNUC__) && !defined(_MSC_VER)
|
||||
// Unknown compiler, default to RTTI
|
||||
#define ABSL_INTERNAL_HAS_RTTI 1
|
||||
#endif
|
||||
|
||||
// `ABSL_INTERNAL_HAS_CXA_DEMANGLE` determines whether `abi::__cxa_demangle` is
|
||||
// available.
|
||||
#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
|
||||
#error ABSL_INTERNAL_HAS_CXA_DEMANGLE cannot be directly set
|
||||
#elif defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 0
|
||||
#elif defined(__GNUC__)
|
||||
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1
|
||||
#elif defined(__clang__) && !defined(_MSC_VER)
|
||||
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1
|
||||
#endif
|
||||
|
||||
// ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support.
|
||||
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
|
||||
|
|
@ -899,7 +817,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
// https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code
|
||||
#ifdef ABSL_INTERNAL_HAVE_ARM_NEON
|
||||
#error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set
|
||||
#elif defined(__ARM_NEON) && !defined(__CUDA_ARCH__)
|
||||
#elif defined(__ARM_NEON) && !(defined(__NVCC__) && defined(__CUDACC__))
|
||||
#define ABSL_INTERNAL_HAVE_ARM_NEON 1
|
||||
#endif
|
||||
|
||||
|
|
@ -914,6 +832,27 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
#define ABSL_HAVE_CONSTANT_EVALUATED 1
|
||||
#endif
|
||||
|
||||
// ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr
|
||||
// for different C++ versions.
|
||||
//
|
||||
// These macros are an implementation detail and will be unconditionally removed
|
||||
// once the minimum supported C++ version catches up to a given version.
|
||||
//
|
||||
// For this reason, this symbol is considered INTERNAL and code outside of
|
||||
// Abseil must not use it.
|
||||
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr
|
||||
#else
|
||||
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
|
||||
#endif
|
||||
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr
|
||||
#else
|
||||
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
|
||||
#endif
|
||||
|
||||
// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros
|
||||
// into an integer that can be compared against.
|
||||
#ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION
|
||||
|
|
@ -928,8 +867,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
|
|||
#if __EMSCRIPTEN_tiny__ >= 1000
|
||||
#error __EMSCRIPTEN_tiny__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION
|
||||
#endif
|
||||
#define ABSL_INTERNAL_EMSCRIPTEN_VERSION \
|
||||
((__EMSCRIPTEN_major__)*1000000 + (__EMSCRIPTEN_minor__)*1000 + \
|
||||
#define ABSL_INTERNAL_EMSCRIPTEN_VERSION \
|
||||
((__EMSCRIPTEN_major__) * 1000000 + (__EMSCRIPTEN_minor__) * 1000 + \
|
||||
(__EMSCRIPTEN_tiny__))
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -252,25 +252,9 @@ ABSL_INTERNAL_END_EXTERN_C
|
|||
|
||||
#else // !defined(ABSL_HAVE_MEMORY_SANITIZER)
|
||||
|
||||
// TODO(rogeeff): remove this branch
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ABSL_HAVE_MEMORY_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -705,10 +705,6 @@ struct BasicGuaranteeWithExtraContracts : public NonNegative {
|
|||
static constexpr int kExceptionSentinel = 9999;
|
||||
};
|
||||
|
||||
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr int BasicGuaranteeWithExtraContracts::kExceptionSentinel;
|
||||
#endif
|
||||
|
||||
TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {
|
||||
auto tester_with_val =
|
||||
tester.WithInitialValue(BasicGuaranteeWithExtraContracts{});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
//
|
||||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -14,37 +13,33 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
#define ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
#ifndef ABSL_BASE_FAST_TYPE_ID_H_
|
||||
#define ABSL_BASE_FAST_TYPE_ID_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
namespace base_internal {
|
||||
template <typename Type>
|
||||
struct FastTypeTag {
|
||||
constexpr static char dummy_var = 0;
|
||||
static constexpr char kDummyVar = 0;
|
||||
};
|
||||
} // namespace base_internal
|
||||
|
||||
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
template <typename Type>
|
||||
constexpr char FastTypeTag<Type>::dummy_var;
|
||||
#endif
|
||||
|
||||
// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
|
||||
// passed-in type. These are meant to be good match for keys into maps or
|
||||
// straight up comparisons.
|
||||
// The type returned by `absl::FastTypeId<T>()`.
|
||||
using FastTypeIdType = const void*;
|
||||
|
||||
// `absl::FastTypeId<Type>()` evaluates at compile-time to a unique id for the
|
||||
// passed-in type. These are meant to be good match for keys into maps or
|
||||
// straight up comparisons.
|
||||
template <typename Type>
|
||||
constexpr inline FastTypeIdType FastTypeId() {
|
||||
return &FastTypeTag<Type>::dummy_var;
|
||||
constexpr FastTypeIdType FastTypeId() {
|
||||
return &base_internal::FastTypeTag<Type>::kDummyVar;
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
#endif // ABSL_BASE_FAST_TYPE_ID_H_
|
||||
|
|
@ -12,18 +12,19 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/fast_type_id.h"
|
||||
#include "absl/base/fast_type_id.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/macros.h"
|
||||
|
||||
namespace {
|
||||
namespace bi = absl::base_internal;
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
// NOLINTBEGIN(runtime/int)
|
||||
#define PRIM_TYPES(A) \
|
||||
A(bool) \
|
||||
A(short) \
|
||||
|
|
@ -37,28 +38,30 @@ namespace bi = absl::base_internal;
|
|||
A(float) \
|
||||
A(double) \
|
||||
A(long double)
|
||||
// NOLINTEND(runtime/int)
|
||||
|
||||
TEST(FastTypeIdTest, PrimitiveTypes) {
|
||||
bi::FastTypeIdType type_ids[] = {
|
||||
#define A(T) bi::FastTypeId<T>(),
|
||||
// clang-format off
|
||||
constexpr absl::FastTypeIdType kTypeIds[] = {
|
||||
#define A(T) absl::FastTypeId<T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const T>(),
|
||||
#define A(T) absl::FastTypeId<const T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<volatile T>(),
|
||||
#define A(T) absl::FastTypeId<volatile T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const volatile T>(),
|
||||
#define A(T) absl::FastTypeId<const volatile T>(),
|
||||
PRIM_TYPES(A)
|
||||
#undef A
|
||||
};
|
||||
size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
|
||||
// clang-format on
|
||||
|
||||
for (int i = 0; i < total_type_ids; ++i) {
|
||||
EXPECT_EQ(type_ids[i], type_ids[i]);
|
||||
for (int j = 0; j < i; ++j) {
|
||||
EXPECT_NE(type_ids[i], type_ids[j]);
|
||||
for (size_t i = 0; i < ABSL_ARRAYSIZE(kTypeIds); ++i) {
|
||||
EXPECT_EQ(kTypeIds[i], kTypeIds[i]);
|
||||
for (size_t j = 0; j < i; ++j) {
|
||||
EXPECT_NE(kTypeIds[i], kTypeIds[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,41 +77,42 @@ TEST(FastTypeIdTest, PrimitiveTypes) {
|
|||
A(uint64_t)
|
||||
|
||||
TEST(FastTypeIdTest, FixedWidthTypes) {
|
||||
bi::FastTypeIdType type_ids[] = {
|
||||
#define A(T) bi::FastTypeId<T>(),
|
||||
// clang-format off
|
||||
constexpr absl::FastTypeIdType kTypeIds[] = {
|
||||
#define A(T) absl::FastTypeId<T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const T>(),
|
||||
#define A(T) absl::FastTypeId<const T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<volatile T>(),
|
||||
#define A(T) absl::FastTypeId<volatile T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
#define A(T) bi::FastTypeId<const volatile T>(),
|
||||
#define A(T) absl::FastTypeId<const volatile T>(),
|
||||
FIXED_WIDTH_TYPES(A)
|
||||
#undef A
|
||||
};
|
||||
size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
|
||||
// clang-format on
|
||||
|
||||
for (int i = 0; i < total_type_ids; ++i) {
|
||||
EXPECT_EQ(type_ids[i], type_ids[i]);
|
||||
for (int j = 0; j < i; ++j) {
|
||||
EXPECT_NE(type_ids[i], type_ids[j]);
|
||||
for (size_t i = 0; i < ABSL_ARRAYSIZE(kTypeIds); ++i) {
|
||||
EXPECT_EQ(kTypeIds[i], kTypeIds[i]);
|
||||
for (size_t j = 0; j < i; ++j) {
|
||||
EXPECT_NE(kTypeIds[i], kTypeIds[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FastTypeIdTest, AliasTypes) {
|
||||
using int_alias = int;
|
||||
EXPECT_EQ(bi::FastTypeId<int_alias>(), bi::FastTypeId<int>());
|
||||
EXPECT_EQ(absl::FastTypeId<int_alias>(), absl::FastTypeId<int>());
|
||||
}
|
||||
|
||||
TEST(FastTypeIdTest, TemplateSpecializations) {
|
||||
EXPECT_NE(bi::FastTypeId<std::vector<int>>(),
|
||||
bi::FastTypeId<std::vector<long>>());
|
||||
EXPECT_NE(absl::FastTypeId<std::vector<int>>(),
|
||||
absl::FastTypeId<std::vector<long>>()); // NOLINT(runtime/int)
|
||||
|
||||
EXPECT_NE((bi::FastTypeId<std::map<int, float>>()),
|
||||
(bi::FastTypeId<std::map<int, double>>()));
|
||||
EXPECT_NE((absl::FastTypeId<std::map<int, float>>()),
|
||||
(absl::FastTypeId<std::map<int, double>>()));
|
||||
}
|
||||
|
||||
struct Base {};
|
||||
|
|
@ -116,8 +120,8 @@ struct Derived : Base {};
|
|||
struct PDerived : private Base {};
|
||||
|
||||
TEST(FastTypeIdTest, Inheritance) {
|
||||
EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<Derived>());
|
||||
EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<PDerived>());
|
||||
EXPECT_NE(absl::FastTypeId<Base>(), absl::FastTypeId<Derived>());
|
||||
EXPECT_NE(absl::FastTypeId<Base>(), absl::FastTypeId<PDerived>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/internal/inline_variable.h"
|
||||
#include "absl/base/internal/inline_variable_testing.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace inline_variable_testing_internal {
|
||||
namespace {
|
||||
|
||||
TEST(InlineVariableTest, Constexpr) {
|
||||
static_assert(inline_variable_foo.value == 5, "");
|
||||
static_assert(other_inline_variable_foo.value == 5, "");
|
||||
static_assert(inline_variable_int == 5, "");
|
||||
static_assert(other_inline_variable_int == 5, "");
|
||||
}
|
||||
|
||||
TEST(InlineVariableTest, DefaultConstructedIdentityEquality) {
|
||||
EXPECT_EQ(get_foo_a().value, 5);
|
||||
EXPECT_EQ(get_foo_b().value, 5);
|
||||
EXPECT_EQ(&get_foo_a(), &get_foo_b());
|
||||
}
|
||||
|
||||
TEST(InlineVariableTest, DefaultConstructedIdentityInequality) {
|
||||
EXPECT_NE(&inline_variable_foo, &other_inline_variable_foo);
|
||||
}
|
||||
|
||||
TEST(InlineVariableTest, InitializedIdentityEquality) {
|
||||
EXPECT_EQ(get_int_a(), 5);
|
||||
EXPECT_EQ(get_int_b(), 5);
|
||||
EXPECT_EQ(&get_int_a(), &get_int_b());
|
||||
}
|
||||
|
||||
TEST(InlineVariableTest, InitializedIdentityInequality) {
|
||||
EXPECT_NE(&inline_variable_int, &other_inline_variable_int);
|
||||
}
|
||||
|
||||
TEST(InlineVariableTest, FunPtrType) {
|
||||
static_assert(
|
||||
std::is_same<void(*)(),
|
||||
std::decay<decltype(inline_variable_fun_ptr)>::type>::value,
|
||||
"");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace inline_variable_testing_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/inline_variable_testing.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace inline_variable_testing_internal {
|
||||
|
||||
const Foo& get_foo_a() { return inline_variable_foo; }
|
||||
|
||||
const int& get_int_a() { return inline_variable_int; }
|
||||
|
||||
} // namespace inline_variable_testing_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
@ -35,11 +35,6 @@ namespace base_internal {
|
|||
|
||||
#if ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
|
||||
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
constexpr int32_t CycleClock::kShift;
|
||||
constexpr double CycleClock::kFrequencyScale;
|
||||
#endif
|
||||
|
||||
ABSL_CONST_INIT std::atomic<CycleClockSourceFunc>
|
||||
CycleClock::cycle_clock_source_{nullptr};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/inline_variable.h"
|
||||
#include "absl/base/internal/unscaledcycleclock_config.h"
|
||||
|
||||
namespace absl {
|
||||
|
|
@ -31,22 +30,23 @@ namespace base_internal {
|
|||
// Not debug mode and the UnscaledCycleClock frequency is the CPU
|
||||
// frequency. Scale the CycleClock to prevent overflow if someone
|
||||
// tries to represent the time as cycles since the Unix epoch.
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 1);
|
||||
inline constexpr int32_t kCycleClockShift = 1;
|
||||
#else
|
||||
// Not debug mode and the UnscaledCycleClock isn't operating at the
|
||||
// raw CPU frequency. There is no need to do any scaling, so don't
|
||||
// needlessly sacrifice precision.
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 0);
|
||||
inline constexpr int32_t kCycleClockShift = 0;
|
||||
#endif
|
||||
#else // NDEBUG
|
||||
// In debug mode use a different shift to discourage depending on a
|
||||
// particular shift value.
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 2);
|
||||
inline constexpr int32_t kCycleClockShift = 2;
|
||||
#endif // NDEBUG
|
||||
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(double, kCycleClockFrequencyScale,
|
||||
1.0 / (1 << kCycleClockShift));
|
||||
#endif // ABSL_USE_UNSCALED_CYCLECLOC
|
||||
inline constexpr double kCycleClockFrequencyScale =
|
||||
1.0 / (1 << kCycleClockShift);
|
||||
|
||||
#endif // ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// This file is for Abseil internal use only.
|
||||
// See //absl/numeric/bits.h for supported functions related to endian-ness.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
|
||||
#define ABSL_BASE_INTERNAL_ENDIAN_H_
|
||||
|
|
@ -22,49 +24,44 @@
|
|||
#include "absl/base/casts.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/unaligned_access.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
inline uint64_t gbswap_64(uint64_t host_int) {
|
||||
constexpr uint64_t gbswap_64(uint64_t x) {
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
|
||||
return __builtin_bswap64(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_uint64(host_int);
|
||||
return __builtin_bswap64(x);
|
||||
#else
|
||||
return (((host_int & uint64_t{0xFF}) << 56) |
|
||||
((host_int & uint64_t{0xFF00}) << 40) |
|
||||
((host_int & uint64_t{0xFF0000}) << 24) |
|
||||
((host_int & uint64_t{0xFF000000}) << 8) |
|
||||
((host_int & uint64_t{0xFF00000000}) >> 8) |
|
||||
((host_int & uint64_t{0xFF0000000000}) >> 24) |
|
||||
((host_int & uint64_t{0xFF000000000000}) >> 40) |
|
||||
((host_int & uint64_t{0xFF00000000000000}) >> 56));
|
||||
return (((x & uint64_t{0xFF}) << 56) |
|
||||
((x & uint64_t{0xFF00}) << 40) |
|
||||
((x & uint64_t{0xFF0000}) << 24) |
|
||||
((x & uint64_t{0xFF000000}) << 8) |
|
||||
((x & uint64_t{0xFF00000000}) >> 8) |
|
||||
((x & uint64_t{0xFF0000000000}) >> 24) |
|
||||
((x & uint64_t{0xFF000000000000}) >> 40) |
|
||||
((x & uint64_t{0xFF00000000000000}) >> 56));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t gbswap_32(uint32_t host_int) {
|
||||
constexpr uint32_t gbswap_32(uint32_t x) {
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
|
||||
return __builtin_bswap32(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ulong(host_int);
|
||||
return __builtin_bswap32(x);
|
||||
#else
|
||||
return (((host_int & uint32_t{0xFF}) << 24) |
|
||||
((host_int & uint32_t{0xFF00}) << 8) |
|
||||
((host_int & uint32_t{0xFF0000}) >> 8) |
|
||||
((host_int & uint32_t{0xFF000000}) >> 24));
|
||||
return (((x & uint32_t{0xFF}) << 24) |
|
||||
((x & uint32_t{0xFF00}) << 8) |
|
||||
((x & uint32_t{0xFF0000}) >> 8) |
|
||||
((x & uint32_t{0xFF000000}) >> 24));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t gbswap_16(uint16_t host_int) {
|
||||
constexpr uint16_t gbswap_16(uint16_t x) {
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
|
||||
return __builtin_bswap16(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ushort(host_int);
|
||||
return __builtin_bswap16(x);
|
||||
#else
|
||||
return (((host_int & uint16_t{0xFF}) << 8) |
|
||||
((host_int & uint16_t{0xFF00}) >> 8));
|
||||
return (((x & uint16_t{0xFF}) << 8) |
|
||||
((x & uint16_t{0xFF00}) >> 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -160,27 +157,27 @@ inline int64_t ToHost(int64_t x) {
|
|||
}
|
||||
|
||||
// Functions to do unaligned loads and stores in little-endian order.
|
||||
inline uint16_t Load16(const void *p) {
|
||||
inline uint16_t Load16(const void* absl_nonnull p) {
|
||||
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
|
||||
}
|
||||
|
||||
inline void Store16(void *p, uint16_t v) {
|
||||
inline void Store16(void* absl_nonnull p, uint16_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
|
||||
}
|
||||
|
||||
inline uint32_t Load32(const void *p) {
|
||||
inline uint32_t Load32(const void* absl_nonnull p) {
|
||||
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
inline void Store32(void *p, uint32_t v) {
|
||||
inline void Store32(void* absl_nonnull p, uint32_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
|
||||
}
|
||||
|
||||
inline uint64_t Load64(const void *p) {
|
||||
inline uint64_t Load64(const void* absl_nonnull p) {
|
||||
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
inline void Store64(void *p, uint64_t v) {
|
||||
inline void Store64(void* absl_nonnull p, uint64_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
|
||||
}
|
||||
|
||||
|
|
@ -250,27 +247,27 @@ inline int64_t ToHost(int64_t x) {
|
|||
}
|
||||
|
||||
// Functions to do unaligned loads and stores in big-endian order.
|
||||
inline uint16_t Load16(const void *p) {
|
||||
inline uint16_t Load16(const void* absl_nonnull p) {
|
||||
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
|
||||
}
|
||||
|
||||
inline void Store16(void *p, uint16_t v) {
|
||||
inline void Store16(void* absl_nonnull p, uint16_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
|
||||
}
|
||||
|
||||
inline uint32_t Load32(const void *p) {
|
||||
inline uint32_t Load32(const void* absl_nonnull p) {
|
||||
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
inline void Store32(void *p, uint32_t v) {
|
||||
inline void Store32(void* absl_nonnull p, uint32_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
|
||||
}
|
||||
|
||||
inline uint64_t Load64(const void *p) {
|
||||
inline uint64_t Load64(const void* absl_nonnull p) {
|
||||
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
inline void Store64(void *p, uint64_t v) {
|
||||
inline void Store64(void* absl_nonnull p, uint64_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,15 @@ namespace absl {
|
|||
ABSL_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
// This is a back-fill of C++20's `std::type_identity`.
|
||||
template <typename T>
|
||||
struct identity {
|
||||
struct type_identity {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// This is a back-fill of C++20's `std::type_identity_t`.
|
||||
template <typename T>
|
||||
using identity_t = typename identity<T>::type;
|
||||
using type_identity_t = typename type_identity<T>::type;
|
||||
|
||||
} // namespace internal
|
||||
ABSL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
|
||||
#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/internal/identity.h"
|
||||
|
||||
// File:
|
||||
// This file define a macro that allows the creation of or emulation of C++17
|
||||
// inline variables based on whether or not the feature is supported.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Macro: ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init)
|
||||
//
|
||||
// Description:
|
||||
// Expands to the equivalent of an inline constexpr instance of the specified
|
||||
// `type` and `name`, initialized to the value `init`. If the compiler being
|
||||
// used is detected as supporting actual inline variables as a language
|
||||
// feature, then the macro expands to an actual inline variable definition.
|
||||
//
|
||||
// Requires:
|
||||
// `type` is a type that is usable in an extern variable declaration.
|
||||
//
|
||||
// Requires: `name` is a valid identifier
|
||||
//
|
||||
// Requires:
|
||||
// `init` is an expression that can be used in the following definition:
|
||||
// constexpr type name = init;
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// // Equivalent to: `inline constexpr size_t variant_npos = -1;`
|
||||
// ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
|
||||
//
|
||||
// Differences in implementation:
|
||||
// For a direct, language-level inline variable, decltype(name) will be the
|
||||
// type that was specified along with const qualification, whereas for
|
||||
// emulated inline variables, decltype(name) may be different (in practice
|
||||
// it will likely be a reference type).
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cpp_inline_variables
|
||||
|
||||
// Clang's -Wmissing-variable-declarations option erroneously warned that
|
||||
// inline constexpr objects need to be pre-declared. This has now been fixed,
|
||||
// but we will need to support this workaround for people building with older
|
||||
// versions of clang.
|
||||
//
|
||||
// Bug: https://bugs.llvm.org/show_bug.cgi?id=35862
|
||||
//
|
||||
// Note:
|
||||
// identity_t is used here so that the const and name are in the
|
||||
// appropriate place for pointer types, reference types, function pointer
|
||||
// types, etc..
|
||||
#if defined(__clang__)
|
||||
#define ABSL_INTERNAL_EXTERN_DECL(type, name) \
|
||||
extern const ::absl::internal::identity_t<type> name;
|
||||
#else // Otherwise, just define the macro to do nothing.
|
||||
#define ABSL_INTERNAL_EXTERN_DECL(type, name)
|
||||
#endif // defined(__clang__)
|
||||
|
||||
// See above comment at top of file for details.
|
||||
#define ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) \
|
||||
ABSL_INTERNAL_EXTERN_DECL(type, name) \
|
||||
inline constexpr ::absl::internal::identity_t<type> name = init
|
||||
|
||||
#else
|
||||
|
||||
// See above comment at top of file for details.
|
||||
//
|
||||
// Note:
|
||||
// identity_t is used here so that the const and name are in the
|
||||
// appropriate place for pointer types, reference types, function pointer
|
||||
// types, etc..
|
||||
#define ABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \
|
||||
template <class /*AbslInternalDummy*/ = void> \
|
||||
struct AbslInternalInlineVariableHolder##name { \
|
||||
static constexpr ::absl::internal::identity_t<var_type> kInstance = init; \
|
||||
}; \
|
||||
\
|
||||
template <class AbslInternalDummy> \
|
||||
constexpr ::absl::internal::identity_t<var_type> \
|
||||
AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance; \
|
||||
\
|
||||
static constexpr const ::absl::internal::identity_t<var_type>& \
|
||||
name = /* NOLINT */ \
|
||||
AbslInternalInlineVariableHolder##name<>::kInstance; \
|
||||
static_assert(sizeof(void (*)(decltype(name))) != 0, \
|
||||
"Silence unused variable warnings.")
|
||||
|
||||
#endif // __cpp_inline_variables
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
|
||||
#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
|
||||
|
||||
#include "absl/base/internal/inline_variable.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace inline_variable_testing_internal {
|
||||
|
||||
struct Foo {
|
||||
int value = 5;
|
||||
};
|
||||
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, inline_variable_foo, {});
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, other_inline_variable_foo, {});
|
||||
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int, inline_variable_int, 5);
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int, other_inline_variable_int, 5);
|
||||
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(void(*)(), inline_variable_fun_ptr, nullptr);
|
||||
|
||||
const Foo& get_foo_a();
|
||||
const Foo& get_foo_b();
|
||||
|
||||
const int& get_int_a();
|
||||
const int& get_int_b();
|
||||
|
||||
} // namespace inline_variable_testing_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// absl::base_internal::invoke(f, args...) is an implementation of
|
||||
// INVOKE(f, args...) from section [func.require] of the C++ standard.
|
||||
// When compiled as C++17 and later versions, it is implemented as an alias of
|
||||
// std::invoke.
|
||||
//
|
||||
// [func.require]
|
||||
// Define INVOKE (f, t1, t2, ..., tN) as follows:
|
||||
// 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
|
||||
// and t1 is an object of type T or a reference to an object of type T or a
|
||||
// reference to an object of a type derived from T;
|
||||
// 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
|
||||
// class T and t1 is not one of the types described in the previous item;
|
||||
// 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
|
||||
// an object of type T or a reference to an object of type T or a reference
|
||||
// to an object of a type derived from T;
|
||||
// 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
|
||||
// is not one of the types described in the previous item;
|
||||
// 5. f(t1, t2, ..., tN) in all other cases.
|
||||
//
|
||||
// The implementation is SFINAE-friendly: substitution failure within invoke()
|
||||
// isn't an error.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_INVOKE_H_
|
||||
#define ABSL_BASE_INTERNAL_INVOKE_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
using std::invoke;
|
||||
using std::invoke_result_t;
|
||||
using std::is_invocable_r;
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#else // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/meta/type_traits.h"
|
||||
|
||||
// The following code is internal implementation detail. See the comment at the
|
||||
// top of this file for the API documentation.
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// The five classes below each implement one of the clauses from the definition
|
||||
// of INVOKE. The inner class template Accept<F, Args...> checks whether the
|
||||
// clause is applicable; static function template Invoke(f, args...) does the
|
||||
// invocation.
|
||||
//
|
||||
// By separating the clause selection logic from invocation we make sure that
|
||||
// Invoke() does exactly what the standard says.
|
||||
|
||||
template <typename Derived>
|
||||
struct StrippedAccept {
|
||||
template <typename... Args>
|
||||
struct Accept : Derived::template AcceptImpl<typename std::remove_cv<
|
||||
typename std::remove_reference<Args>::type>::type...> {};
|
||||
};
|
||||
|
||||
// (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
|
||||
// and t1 is an object of type T or a reference to an object of type T or a
|
||||
// reference to an object of a type derived from T.
|
||||
struct MemFunAndRef : StrippedAccept<MemFunAndRef> {
|
||||
template <typename... Args>
|
||||
struct AcceptImpl : std::false_type {};
|
||||
|
||||
template <typename MemFunType, typename C, typename Obj, typename... Args>
|
||||
struct AcceptImpl<MemFunType C::*, Obj, Args...>
|
||||
: std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
|
||||
absl::is_function<MemFunType>::value> {
|
||||
};
|
||||
|
||||
template <typename MemFun, typename Obj, typename... Args>
|
||||
static decltype((std::declval<Obj>().*
|
||||
std::declval<MemFun>())(std::declval<Args>()...))
|
||||
Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) {
|
||||
// Ignore bogus GCC warnings on this line.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101436 for similar example.
|
||||
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
return (std::forward<Obj>(obj).*
|
||||
std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
|
||||
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
|
||||
// class T and t1 is not one of the types described in the previous item.
|
||||
struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> {
|
||||
template <typename... Args>
|
||||
struct AcceptImpl : std::false_type {};
|
||||
|
||||
template <typename MemFunType, typename C, typename Ptr, typename... Args>
|
||||
struct AcceptImpl<MemFunType C::*, Ptr, Args...>
|
||||
: std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
|
||||
absl::is_function<MemFunType>::value> {
|
||||
};
|
||||
|
||||
template <typename MemFun, typename Ptr, typename... Args>
|
||||
static decltype(((*std::declval<Ptr>()).*
|
||||
std::declval<MemFun>())(std::declval<Args>()...))
|
||||
Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) {
|
||||
return ((*std::forward<Ptr>(ptr)).*
|
||||
std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
|
||||
// an object of type T or a reference to an object of type T or a reference
|
||||
// to an object of a type derived from T.
|
||||
struct DataMemAndRef : StrippedAccept<DataMemAndRef> {
|
||||
template <typename... Args>
|
||||
struct AcceptImpl : std::false_type {};
|
||||
|
||||
template <typename R, typename C, typename Obj>
|
||||
struct AcceptImpl<R C::*, Obj>
|
||||
: std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
|
||||
!absl::is_function<R>::value> {};
|
||||
|
||||
template <typename DataMem, typename Ref>
|
||||
static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
|
||||
DataMem&& data_mem, Ref&& ref) {
|
||||
return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem);
|
||||
}
|
||||
};
|
||||
|
||||
// (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
|
||||
// is not one of the types described in the previous item.
|
||||
struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> {
|
||||
template <typename... Args>
|
||||
struct AcceptImpl : std::false_type {};
|
||||
|
||||
template <typename R, typename C, typename Ptr>
|
||||
struct AcceptImpl<R C::*, Ptr>
|
||||
: std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
|
||||
!absl::is_function<R>::value> {};
|
||||
|
||||
template <typename DataMem, typename Ptr>
|
||||
static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
|
||||
DataMem&& data_mem, Ptr&& ptr) {
|
||||
return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem);
|
||||
}
|
||||
};
|
||||
|
||||
// f(t1, t2, ..., tN) in all other cases.
|
||||
struct Callable {
|
||||
// Callable doesn't have Accept because it's the last clause that gets picked
|
||||
// when none of the previous clauses are applicable.
|
||||
template <typename F, typename... Args>
|
||||
static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke(
|
||||
F&& f, Args&&... args) {
|
||||
return std::forward<F>(f)(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// Resolves to the first matching clause.
|
||||
template <typename... Args>
|
||||
struct Invoker {
|
||||
typedef typename std::conditional<
|
||||
MemFunAndRef::Accept<Args...>::value, MemFunAndRef,
|
||||
typename std::conditional<
|
||||
MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr,
|
||||
typename std::conditional<
|
||||
DataMemAndRef::Accept<Args...>::value, DataMemAndRef,
|
||||
typename std::conditional<DataMemAndPtr::Accept<Args...>::value,
|
||||
DataMemAndPtr, Callable>::type>::type>::
|
||||
type>::type type;
|
||||
};
|
||||
|
||||
// The result type of Invoke<F, Args...>.
|
||||
template <typename F, typename... Args>
|
||||
using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
|
||||
std::declval<F>(), std::declval<Args>()...));
|
||||
|
||||
// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
|
||||
// [func.require] of the C++ standard.
|
||||
template <typename F, typename... Args>
|
||||
invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
|
||||
return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename AlwaysVoid, typename, typename, typename...>
|
||||
struct IsInvocableRImpl : std::false_type {};
|
||||
|
||||
template <typename R, typename F, typename... Args>
|
||||
struct IsInvocableRImpl<
|
||||
absl::void_t<absl::base_internal::invoke_result_t<F, Args...> >, R, F,
|
||||
Args...>
|
||||
: std::integral_constant<
|
||||
bool,
|
||||
std::is_convertible<absl::base_internal::invoke_result_t<F, Args...>,
|
||||
R>::value ||
|
||||
std::is_void<R>::value> {};
|
||||
|
||||
// Type trait whose member `value` is true if invoking `F` with `Args` is valid,
|
||||
// and either the return type is convertible to `R`, or `R` is void.
|
||||
// C++11-compatible version of `std::is_invocable_r`.
|
||||
template <typename R, typename F, typename... Args>
|
||||
using is_invocable_r = IsInvocableRImpl<void, R, F, Args...>;
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_INVOKE_H_
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2025 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: internal/iterator_traits.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Helpers for querying traits of iterators, for implementing containers, etc.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
|
||||
#define ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
template <typename Iterator, typename = void>
|
||||
struct IteratorCategory {};
|
||||
|
||||
template <typename Iterator>
|
||||
struct IteratorCategory<
|
||||
Iterator,
|
||||
absl::void_t<typename std::iterator_traits<Iterator>::iterator_category>> {
|
||||
using type = typename std::iterator_traits<Iterator>::iterator_category;
|
||||
};
|
||||
|
||||
template <typename Iterator, typename = void>
|
||||
struct IteratorConceptImpl : IteratorCategory<Iterator> {};
|
||||
|
||||
template <typename Iterator>
|
||||
struct IteratorConceptImpl<
|
||||
Iterator,
|
||||
absl::void_t<typename std::iterator_traits<Iterator>::iterator_concept>> {
|
||||
using type = typename std::iterator_traits<Iterator>::iterator_concept;
|
||||
};
|
||||
|
||||
// The newer `std::iterator_traits<Iterator>::iterator_concept` if available,
|
||||
// else `std::iterator_traits<Iterator>::iterator_category`.
|
||||
template <typename Iterator>
|
||||
using IteratorConcept = typename IteratorConceptImpl<Iterator>::type;
|
||||
|
||||
template <typename IteratorTag, typename Iterator>
|
||||
using IsAtLeastIterator =
|
||||
std::is_convertible<IteratorConcept<Iterator>, IteratorTag>;
|
||||
|
||||
template <typename Iterator>
|
||||
using IsAtLeastForwardIterator =
|
||||
IsAtLeastIterator<std::forward_iterator_tag, Iterator>;
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2025 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/iterator_traits.h"
|
||||
|
||||
#include <forward_list>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/iterator_traits_test_helper.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
namespace {
|
||||
|
||||
TEST(IsAtLeastIteratorTest, IsAtLeastIterator) {
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag, int*>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag, int*>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag, int*>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::random_access_iterator_tag, int*>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
|
||||
std::vector<int>::iterator>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
|
||||
std::vector<int>::iterator>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag,
|
||||
std::vector<int>::iterator>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::random_access_iterator_tag,
|
||||
std::vector<int>::iterator>()));
|
||||
|
||||
EXPECT_TRUE(
|
||||
(IsAtLeastIterator<std::input_iterator_tag, std::list<int>::iterator>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
|
||||
std::list<int>::iterator>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag,
|
||||
std::list<int>::iterator>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
|
||||
std::list<int>::iterator>()));
|
||||
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
|
||||
std::forward_list<int>::iterator>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
|
||||
std::forward_list<int>::iterator>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,
|
||||
std::forward_list<int>::iterator>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
|
||||
std::forward_list<int>::iterator>()));
|
||||
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
|
||||
std::istream_iterator<int>>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::forward_iterator_tag,
|
||||
std::istream_iterator<int>>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,
|
||||
std::istream_iterator<int>>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
|
||||
std::istream_iterator<int>>()));
|
||||
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
|
||||
Cpp20ForwardZipIterator<int*>>()));
|
||||
EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
|
||||
Cpp20ForwardZipIterator<int*>>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,
|
||||
Cpp20ForwardZipIterator<int*>>()));
|
||||
EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
|
||||
Cpp20ForwardZipIterator<int*>>()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
97
src/third_party/abseil-cpp/dist/absl/base/internal/iterator_traits_test_helper.h
vendored
Normal file
97
src/third_party/abseil-cpp/dist/absl/base/internal/iterator_traits_test_helper.h
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2025 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_
|
||||
#define ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// This would be a forward_iterator in C++20, but it's only an input iterator
|
||||
// before that, since it has a non-reference `reference`.
|
||||
template <typename Iterator>
|
||||
class Cpp20ForwardZipIterator {
|
||||
using IteratorReference = typename std::iterator_traits<Iterator>::reference;
|
||||
|
||||
public:
|
||||
Cpp20ForwardZipIterator() = default;
|
||||
explicit Cpp20ForwardZipIterator(Iterator left, Iterator right)
|
||||
: left_(left), right_(right) {}
|
||||
|
||||
Cpp20ForwardZipIterator& operator++() {
|
||||
++left_;
|
||||
++right_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Cpp20ForwardZipIterator operator++(int) {
|
||||
Cpp20ForwardZipIterator tmp(*this);
|
||||
++*this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<IteratorReference, IteratorReference> operator*() const {
|
||||
return {*left_, *right_};
|
||||
}
|
||||
|
||||
// C++17 input iterators require `operator->`, but this isn't possible to
|
||||
// implement. C++20 dropped the requirement.
|
||||
|
||||
friend bool operator==(const Cpp20ForwardZipIterator& lhs,
|
||||
const Cpp20ForwardZipIterator& rhs) {
|
||||
return lhs.left_ == rhs.left_ && lhs.right_ == rhs.right_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const Cpp20ForwardZipIterator& lhs,
|
||||
const Cpp20ForwardZipIterator& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator left_{};
|
||||
Iterator right_{};
|
||||
};
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
template <typename Iterator>
|
||||
struct std::iterator_traits<
|
||||
absl::base_internal::Cpp20ForwardZipIterator<Iterator>> {
|
||||
private:
|
||||
using IteratorReference = typename std::iterator_traits<Iterator>::reference;
|
||||
|
||||
public:
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using iterator_concept = std::forward_iterator_tag;
|
||||
using value_type = std::pair<IteratorReference, IteratorReference>;
|
||||
using difference_type =
|
||||
typename std::iterator_traits<Iterator>::difference_type;
|
||||
using reference = value_type;
|
||||
using pointer = void;
|
||||
};
|
||||
|
||||
#if defined(__cpp_lib_concepts)
|
||||
static_assert(
|
||||
std::forward_iterator<absl::base_internal::Cpp20ForwardZipIterator<int*>>);
|
||||
#endif // defined(__cpp_lib_concepts)
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_
|
||||
|
|
@ -329,8 +329,8 @@ size_t GetPageSize() {
|
|||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity);
|
||||
#elif defined(__wasm__) || defined(__asmjs__)
|
||||
return getpagesize();
|
||||
#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__)
|
||||
return static_cast<size_t>(getpagesize());
|
||||
#else
|
||||
return static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||
#endif
|
||||
|
|
@ -448,8 +448,8 @@ static inline uintptr_t RoundUp(uintptr_t addr, uintptr_t align) {
|
|||
// that the freelist is in the correct order, that it
|
||||
// consists of regions marked "unallocated", and that no two regions
|
||||
// are adjacent in memory (they should have been coalesced).
|
||||
// L >= arena->mu
|
||||
static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) {
|
||||
static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(arena->mu) {
|
||||
ABSL_RAW_CHECK(i < prev->levels, "too few levels in Next()");
|
||||
AllocList *next = prev->next[i];
|
||||
if (next != nullptr) {
|
||||
|
|
@ -473,6 +473,7 @@ static void Coalesce(AllocList *a) {
|
|||
if (n != nullptr && reinterpret_cast<char *>(a) + a->header.size ==
|
||||
reinterpret_cast<char *>(n)) {
|
||||
LowLevelAlloc::Arena *arena = a->header.arena;
|
||||
arena->mu.AssertHeld();
|
||||
a->header.size += n->header.size;
|
||||
n->header.magic = 0;
|
||||
n->header.arena = nullptr;
|
||||
|
|
@ -486,8 +487,8 @@ static void Coalesce(AllocList *a) {
|
|||
}
|
||||
|
||||
// Adds block at location "v" to the free list
|
||||
// L >= arena->mu
|
||||
static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) {
|
||||
static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(arena->mu) {
|
||||
AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -
|
||||
sizeof(f->header));
|
||||
ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
|
||||
|
|
|
|||
106
src/third_party/abseil-cpp/dist/absl/base/internal/nullability_deprecated.h
vendored
Normal file
106
src/third_party/abseil-cpp/dist/absl/base/internal/nullability_deprecated.h
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright 2023 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
|
||||
#define ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace nullability_internal {
|
||||
|
||||
template <typename T>
|
||||
using NullableImpl
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
[[clang::annotate("Nullable")]]
|
||||
#endif
|
||||
// Don't add the _Nullable attribute in Objective-C compiles. Many Objective-C
|
||||
// projects enable the `-Wnullable-to-nonnull-conversion warning`, which is
|
||||
// liable to produce false positives.
|
||||
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
|
||||
= T _Nullable;
|
||||
#else
|
||||
= T;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
using NonnullImpl
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
[[clang::annotate("Nonnull")]]
|
||||
#endif
|
||||
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
|
||||
= T _Nonnull;
|
||||
#else
|
||||
= T;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
using NullabilityUnknownImpl
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
[[clang::annotate("Nullability_Unspecified")]]
|
||||
#endif
|
||||
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
|
||||
= T _Null_unspecified;
|
||||
#else
|
||||
= T;
|
||||
#endif
|
||||
|
||||
} // namespace nullability_internal
|
||||
|
||||
// The following template aliases are deprecated forms of nullability
|
||||
// annotations. They have some limitations, for example, an incompatibility with
|
||||
// `auto*` pointers, as `auto` cannot be used in a template argument.
|
||||
//
|
||||
// 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<T*>`, for example, is simply a
|
||||
// pointer of type `T*`.
|
||||
//
|
||||
// Prefer the macro style annotations in `absl/base/nullability.h` instead.
|
||||
|
||||
// absl::Nonnull, analogous to absl_nonnull
|
||||
//
|
||||
// Example:
|
||||
// absl::Nonnull<int*> foo;
|
||||
// Is equivalent to:
|
||||
// int* absl_nonnull foo;
|
||||
template <typename T>
|
||||
using Nonnull [[deprecated("Use `absl_nonnull`.")]] =
|
||||
nullability_internal::NonnullImpl<T>;
|
||||
|
||||
// absl::Nullable, analogous to absl_nullable
|
||||
//
|
||||
// Example:
|
||||
// absl::Nullable<int*> foo;
|
||||
// Is equivalent to:
|
||||
// int* absl_nullable foo;
|
||||
template <typename T>
|
||||
using Nullable [[deprecated("Use `absl_nullable`.")]] =
|
||||
nullability_internal::NullableImpl<T>;
|
||||
|
||||
// absl::NullabilityUnknown, analogous to absl_nullability_unknown
|
||||
//
|
||||
// Example:
|
||||
// absl::NullabilityUnknown<int*> foo;
|
||||
// Is equivalent to:
|
||||
// int* absl_nullability_unknown foo;
|
||||
template <typename T>
|
||||
using NullabilityUnknown [[deprecated("Use `absl_nullability_unknown`.")]] =
|
||||
nullability_internal::NullabilityUnknownImpl<T>;
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
// Copyright 2023 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
|
||||
#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
|
||||
namespace absl {
|
||||
|
||||
namespace nullability_internal {
|
||||
|
||||
// `IsNullabilityCompatible` checks whether its first argument is a class
|
||||
// explicitly tagged as supporting nullability annotations. The tag is the type
|
||||
// declaration `absl_nullability_compatible`.
|
||||
template <typename, typename = void>
|
||||
struct IsNullabilityCompatible : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct IsNullabilityCompatible<
|
||||
T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value;
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsSupportedType<T*> = true;
|
||||
|
||||
template <typename T, typename U>
|
||||
constexpr bool IsSupportedType<T U::*> = true;
|
||||
|
||||
template <typename T, typename... Deleter>
|
||||
constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true;
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsSupportedType<std::shared_ptr<T>> = true;
|
||||
|
||||
template <typename T>
|
||||
struct EnableNullable {
|
||||
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
|
||||
"Template argument must be a raw or supported smart pointer "
|
||||
"type. See absl/base/nullability.h.");
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct EnableNonnull {
|
||||
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
|
||||
"Template argument must be a raw or supported smart pointer "
|
||||
"type. See absl/base/nullability.h.");
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct EnableNullabilityUnknown {
|
||||
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
|
||||
"Template argument must be a raw or supported smart pointer "
|
||||
"type. See absl/base/nullability.h.");
|
||||
using type = T;
|
||||
};
|
||||
|
||||
// Note: we do not apply Clang nullability attributes (e.g. _Nullable). These
|
||||
// only support raw pointers, and conditionally enabling them only for raw
|
||||
// pointers inhibits template arg deduction. Ideally, they would support all
|
||||
// pointer-like types.
|
||||
template <typename T, typename = typename EnableNullable<T>::type>
|
||||
using NullableImpl
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
[[clang::annotate("Nullable")]]
|
||||
#endif
|
||||
= T;
|
||||
|
||||
template <typename T, typename = typename EnableNonnull<T>::type>
|
||||
using NonnullImpl
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
[[clang::annotate("Nonnull")]]
|
||||
#endif
|
||||
= T;
|
||||
|
||||
template <typename T, typename = typename EnableNullabilityUnknown<T>::type>
|
||||
using NullabilityUnknownImpl
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
[[clang::annotate("Nullability_Unspecified")]]
|
||||
#endif
|
||||
= T;
|
||||
|
||||
} // namespace nullability_internal
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/poison.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/direct_mmap.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(ABSL_HAVE_ADDRESS_SANITIZER)
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#elif defined(ABSL_HAVE_MEMORY_SANITIZER)
|
||||
#include <sanitizer/msan_interface.h>
|
||||
#elif defined(ABSL_HAVE_MMAP)
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
namespace {
|
||||
|
||||
size_t GetPageSize() {
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
return system_info.dwPageSize;
|
||||
#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__)
|
||||
return getpagesize();
|
||||
#else
|
||||
return static_cast<size_t>(sysconf(_SC_PAGESIZE));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void* InitializePoisonedPointerInternal() {
|
||||
const size_t block_size = GetPageSize();
|
||||
#if defined(ABSL_HAVE_ADDRESS_SANITIZER)
|
||||
void* data = malloc(block_size);
|
||||
ASAN_POISON_MEMORY_REGION(data, block_size);
|
||||
#elif defined(ABSL_HAVE_MEMORY_SANITIZER)
|
||||
void* data = malloc(block_size);
|
||||
__msan_poison(data, block_size);
|
||||
#elif defined(ABSL_HAVE_MMAP)
|
||||
void* data = DirectMmap(nullptr, block_size, PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (data == MAP_FAILED) return GetBadPointerInternal();
|
||||
#elif defined(_WIN32)
|
||||
void* data = VirtualAlloc(nullptr, block_size, MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_NOACCESS);
|
||||
if (data == nullptr) return GetBadPointerInternal();
|
||||
#else
|
||||
return GetBadPointerInternal();
|
||||
#endif
|
||||
// Return the middle of the block so that dereferences before and after the
|
||||
// pointer will both crash.
|
||||
return static_cast<char*>(data) + block_size / 2;
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_POISON_H_
|
||||
#define ABSL_BASE_INTERNAL_POISON_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
inline void* GetBadPointerInternal() {
|
||||
// A likely bad pointer. Pointers are required to have high bits that are all
|
||||
// zero or all one for certain 64-bit CPUs. This pointer value will hopefully
|
||||
// cause a crash on dereference and also be clearly recognizable as invalid.
|
||||
constexpr uint64_t kBadPtr = 0xBAD0BAD0BAD0BAD0;
|
||||
auto ret = reinterpret_cast<void*>(static_cast<uintptr_t>(kBadPtr));
|
||||
#ifndef _MSC_VER // MSVC doesn't support inline asm with `volatile`.
|
||||
// Try to prevent the compiler from optimizing out the undefined behavior.
|
||||
asm volatile("" : : "r"(ret) :); // NOLINT
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* InitializePoisonedPointerInternal();
|
||||
|
||||
inline void* get_poisoned_pointer() {
|
||||
#if defined(NDEBUG) && !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
|
||||
!defined(ABSL_HAVE_MEMORY_SANITIZER)
|
||||
// In optimized non-sanitized builds, avoid the function-local static because
|
||||
// of the codegen and runtime cost.
|
||||
return GetBadPointerInternal();
|
||||
#else
|
||||
// Non-optimized builds may use more robust implementation. Note that we can't
|
||||
// use a static global because Chromium doesn't allow non-constinit globals.
|
||||
static void* ptr = InitializePoisonedPointerInternal();
|
||||
return ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_POISON_H_
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/poison.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
namespace {
|
||||
|
||||
TEST(PoisonTest, CrashesOnDereference) {
|
||||
#ifdef __ANDROID__
|
||||
GTEST_SKIP() << "On Android, poisoned pointer dereference times out instead "
|
||||
"of crashing.";
|
||||
#endif
|
||||
int* poisoned_ptr = static_cast<int*>(get_poisoned_pointer());
|
||||
EXPECT_DEATH_IF_SUPPORTED(std::cout << *poisoned_ptr, "");
|
||||
EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr - 10), "");
|
||||
EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr + 10), "");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
// Copyright 2022 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// TODO(b/265984188): remove all uses and delete this header.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_PREFETCH_H_
|
||||
#define ABSL_BASE_INTERNAL_PREFETCH_H_
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/prefetch.h"
|
||||
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(ABSL_INTERNAL_HAVE_SSE)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_mm_prefetch)
|
||||
#endif
|
||||
|
||||
// Compatibility wrappers around __builtin_prefetch, to prefetch data
|
||||
// for read if supported by the toolchain.
|
||||
|
||||
// Move data into the cache before it is read, or "prefetch" it.
|
||||
//
|
||||
// The value of `addr` is the address of the memory to prefetch. If
|
||||
// the target and compiler support it, data prefetch instructions are
|
||||
// generated. If the prefetch is done some time before the memory is
|
||||
// read, it may be in the cache by the time the read occurs.
|
||||
//
|
||||
// The function names specify the temporal locality heuristic applied,
|
||||
// using the names of Intel prefetch instructions:
|
||||
//
|
||||
// T0 - high degree of temporal locality; data should be left in as
|
||||
// many levels of the cache possible
|
||||
// T1 - moderate degree of temporal locality
|
||||
// T2 - low degree of temporal locality
|
||||
// Nta - no temporal locality, data need not be left in the cache
|
||||
// after the read
|
||||
//
|
||||
// Incorrect or gratuitous use of these functions can degrade
|
||||
// performance, so use them only when representative benchmarks show
|
||||
// an improvement.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// absl::base_internal::PrefetchT0(addr);
|
||||
//
|
||||
// Currently, the different prefetch calls behave on some Intel
|
||||
// architectures as follows:
|
||||
//
|
||||
// SNB..SKL SKX
|
||||
// PrefetchT0() L1/L2/L3 L1/L2
|
||||
// PrefetchT1() L2/L3 L2
|
||||
// PrefetchT2() L2/L3 L2
|
||||
// PrefetchNta() L1/--/L3 L1*
|
||||
//
|
||||
// * On SKX PrefetchNta() will bring the line into L1 but will evict
|
||||
// from L3 cache. This might result in surprising behavior.
|
||||
//
|
||||
// SNB = Sandy Bridge, SKL = Skylake, SKX = Skylake Xeon.
|
||||
//
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
|
||||
inline void PrefetchT0(const void* address) {
|
||||
absl::PrefetchToLocalCache(address);
|
||||
}
|
||||
|
||||
ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
|
||||
inline void PrefetchNta(const void* address) {
|
||||
absl::PrefetchToLocalCacheNta(address);
|
||||
}
|
||||
|
||||
ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
|
||||
void PrefetchT1(const void* addr);
|
||||
|
||||
ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
|
||||
void PrefetchT2(const void* addr);
|
||||
|
||||
// Implementation details follow.
|
||||
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
|
||||
|
||||
#define ABSL_INTERNAL_HAVE_PREFETCH 1
|
||||
|
||||
// See __builtin_prefetch:
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
|
||||
//
|
||||
// These functions speculatively load for read only. This is
|
||||
// safe for all currently supported platforms. However, prefetch for
|
||||
// store may have problems depending on the target platform.
|
||||
//
|
||||
inline void PrefetchT1(const void* addr) {
|
||||
// Note: this uses prefetcht1 on Intel.
|
||||
__builtin_prefetch(addr, 0, 2);
|
||||
}
|
||||
inline void PrefetchT2(const void* addr) {
|
||||
// Note: this uses prefetcht2 on Intel.
|
||||
__builtin_prefetch(addr, 0, 1);
|
||||
}
|
||||
|
||||
#elif defined(ABSL_INTERNAL_HAVE_SSE)
|
||||
|
||||
#define ABSL_INTERNAL_HAVE_PREFETCH 1
|
||||
|
||||
inline void PrefetchT1(const void* addr) {
|
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1);
|
||||
}
|
||||
inline void PrefetchT2(const void* addr) {
|
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2);
|
||||
}
|
||||
|
||||
#else
|
||||
inline void PrefetchT1(const void*) {}
|
||||
inline void PrefetchT2(const void*) {}
|
||||
#endif
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_PREFETCH_H_
|
||||
|
|
@ -42,8 +42,9 @@
|
|||
// This preprocessor token is also defined in raw_io.cc. If you need to copy
|
||||
// this, consider moving both to config.h instead.
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(__Fuchsia__) || defined(__native_client__) || \
|
||||
defined(__OpenBSD__) || defined(__EMSCRIPTEN__) || defined(__ASYLO__)
|
||||
defined(__hexagon__) || defined(__Fuchsia__) || \
|
||||
defined(__native_client__) || defined(__OpenBSD__) || \
|
||||
defined(__EMSCRIPTEN__) || defined(__ASYLO__)
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
@ -56,8 +57,7 @@
|
|||
// ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall
|
||||
// syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len);
|
||||
// for low level operations that want to avoid libc.
|
||||
#if (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && \
|
||||
!defined(__ANDROID__)
|
||||
#if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__)
|
||||
#include <sys/syscall.h>
|
||||
#define ABSL_HAVE_SYSCALL_WRITE 1
|
||||
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
|
||||
|
|
@ -93,8 +93,7 @@ constexpr char kTruncated[] = " ... (message truncated)\n";
|
|||
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap)
|
||||
ABSL_PRINTF_ATTRIBUTE(3, 0);
|
||||
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
|
||||
if (*size < 0)
|
||||
return false;
|
||||
if (*size < 0) return false;
|
||||
int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);
|
||||
bool result = true;
|
||||
if (n < 0 || n > *size) {
|
||||
|
|
@ -122,8 +121,7 @@ constexpr int kLogBufSize = 3000;
|
|||
bool DoRawLog(char** buf, int* size, const char* format, ...)
|
||||
ABSL_PRINTF_ATTRIBUTE(3, 4);
|
||||
bool DoRawLog(char** buf, int* size, const char* format, ...) {
|
||||
if (*size < 0)
|
||||
return false;
|
||||
if (*size < 0) return false;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);
|
||||
|
|
@ -177,7 +175,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
|
|||
} else {
|
||||
DoRawLog(&buf, &size, "%s", kTruncated);
|
||||
}
|
||||
AsyncSignalSafeWriteError(buffer, strlen(buffer));
|
||||
AsyncSignalSafeWriteError(buffer, static_cast<size_t>(buf - buffer));
|
||||
}
|
||||
#else
|
||||
static_cast<void>(format);
|
||||
|
|
@ -242,8 +240,8 @@ void AsyncSignalSafeWriteError(const char* s, size_t len) {
|
|||
_write(/* stderr */ 2, s, static_cast<unsigned>(len));
|
||||
#else
|
||||
// stderr logging unsupported on this platform
|
||||
(void) s;
|
||||
(void) len;
|
||||
(void)s;
|
||||
(void)len;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -258,7 +256,7 @@ void RawLog(absl::LogSeverity severity, const char* file, int line,
|
|||
bool RawLoggingFullySupported() {
|
||||
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
|
||||
return true;
|
||||
#else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
|
||||
#else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
|
||||
return false;
|
||||
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@
|
|||
#define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning
|
||||
#define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError
|
||||
#define ABSL_RAW_LOG_INTERNAL_FATAL ::absl::LogSeverity::kFatal
|
||||
#define ABSL_RAW_LOG_INTERNAL_DFATAL ::absl::kLogDebugFatal
|
||||
#define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \
|
||||
::absl::NormalizeLogSeverity(severity)
|
||||
|
||||
|
|
@ -115,6 +116,7 @@
|
|||
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_WARNING
|
||||
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_ERROR
|
||||
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_FATAL ABSL_UNREACHABLE()
|
||||
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_DFATAL
|
||||
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_LEVEL(severity)
|
||||
|
||||
namespace absl {
|
||||
|
|
|
|||
|
|
@ -67,15 +67,6 @@ void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,
|
|||
submit_profile_data.Store(fn);
|
||||
}
|
||||
|
||||
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
// Static member variable definitions.
|
||||
constexpr uint32_t SpinLock::kSpinLockHeld;
|
||||
constexpr uint32_t SpinLock::kSpinLockCooperative;
|
||||
constexpr uint32_t SpinLock::kSpinLockDisabledScheduling;
|
||||
constexpr uint32_t SpinLock::kSpinLockSleeper;
|
||||
constexpr uint32_t SpinLock::kWaitTimeMask;
|
||||
#endif
|
||||
|
||||
// Uncommon constructors.
|
||||
SpinLock::SpinLock(base_internal::SchedulingMode mode)
|
||||
: lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@
|
|||
// - for use by Abseil internal code that Mutex itself depends on
|
||||
// - for async signal safety (see below)
|
||||
|
||||
// SpinLock is async signal safe. If a spinlock is used within a signal
|
||||
// handler, all code that acquires the lock must ensure that the signal cannot
|
||||
// arrive while they are holding the lock. Typically, this is done by blocking
|
||||
// the signal.
|
||||
// SpinLock with a base_internal::SchedulingMode::SCHEDULE_KERNEL_ONLY is async
|
||||
// signal safe. If a spinlock is used within a signal handler, all code that
|
||||
// acquires the lock must ensure that the signal cannot arrive while they are
|
||||
// holding the lock. Typically, this is done by blocking the signal.
|
||||
//
|
||||
// Threads waiting on a SpinLock may be woken in an arbitrary order.
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ namespace absl {
|
|||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
class ABSL_LOCKABLE SpinLock {
|
||||
class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock {
|
||||
public:
|
||||
SpinLock() : lockword_(kSpinLockCooperative) {
|
||||
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
|
||||
|
|
@ -89,7 +89,7 @@ class ABSL_LOCKABLE SpinLock {
|
|||
// acquisition was successful. If the lock was not acquired, false is
|
||||
// returned. If this SpinLock is free at the time of the call, TryLock
|
||||
// will return true with high probability.
|
||||
inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
||||
[[nodiscard]] inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
||||
ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
|
||||
bool res = TryLockImpl();
|
||||
ABSL_TSAN_MUTEX_POST_LOCK(
|
||||
|
|
@ -120,7 +120,7 @@ class ABSL_LOCKABLE SpinLock {
|
|||
// Determine if the lock is held. When the lock is held by the invoking
|
||||
// thread, true will always be returned. Intended to be used as
|
||||
// CHECK(lock.IsHeld()).
|
||||
inline bool IsHeld() const {
|
||||
[[nodiscard]] inline bool IsHeld() const {
|
||||
return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +202,7 @@ class ABSL_LOCKABLE SpinLock {
|
|||
|
||||
// Corresponding locker object that arranges to acquire a spinlock for
|
||||
// the duration of a C++ scope.
|
||||
class ABSL_SCOPED_LOCKABLE SpinLockHolder {
|
||||
class ABSL_SCOPED_LOCKABLE [[nodiscard]] SpinLockHolder {
|
||||
public:
|
||||
inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)
|
||||
: lock_(l) {
|
||||
|
|
|
|||
|
|
@ -18,22 +18,39 @@
|
|||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/scheduling_mode.h"
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
#include "absl/base/no_destructor.h"
|
||||
#include "absl/synchronization/internal/create_thread_identity.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
|
||||
template <absl::base_internal::SchedulingMode scheduling_mode>
|
||||
static void BM_SpinLock(benchmark::State& state) {
|
||||
// Ensure a ThreadIdentity is installed.
|
||||
static void BM_TryLock(benchmark::State& state) {
|
||||
// Ensure a ThreadIdentity is installed so that KERNEL_ONLY has an effect.
|
||||
ABSL_INTERNAL_CHECK(
|
||||
absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=
|
||||
nullptr,
|
||||
"GetOrCreateCurrentThreadIdentity() failed");
|
||||
|
||||
static auto* spinlock = new absl::base_internal::SpinLock(scheduling_mode);
|
||||
static absl::NoDestructor<absl::base_internal::SpinLock> spinlock(
|
||||
scheduling_mode);
|
||||
for (auto _ : state) {
|
||||
absl::base_internal::SpinLockHolder holder(spinlock);
|
||||
if (spinlock->TryLock()) spinlock->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
template <absl::base_internal::SchedulingMode scheduling_mode>
|
||||
static void BM_SpinLock(benchmark::State& state) {
|
||||
// Ensure a ThreadIdentity is installed so that KERNEL_ONLY has an effect.
|
||||
ABSL_INTERNAL_CHECK(
|
||||
absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=
|
||||
nullptr,
|
||||
"GetOrCreateCurrentThreadIdentity() failed");
|
||||
|
||||
static absl::NoDestructor<absl::base_internal::SpinLock> spinlock(
|
||||
scheduling_mode);
|
||||
for (auto _ : state) {
|
||||
absl::base_internal::SpinLockHolder holder(spinlock.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,4 +66,15 @@ BENCHMARK_TEMPLATE(BM_SpinLock,
|
|||
->Threads(1)
|
||||
->ThreadPerCpu();
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_TryLock, absl::base_internal::SCHEDULE_KERNEL_ONLY)
|
||||
->UseRealTime()
|
||||
->Threads(1)
|
||||
->ThreadPerCpu();
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_TryLock,
|
||||
absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL)
|
||||
->UseRealTime()
|
||||
->Threads(1)
|
||||
->ThreadPerCpu();
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@
|
|||
#include <rtems.h>
|
||||
#endif
|
||||
|
||||
#if defined(__Fuchsia__)
|
||||
#include <zircon/process.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cassert>
|
||||
|
|
@ -461,6 +465,16 @@ pid_t GetTID() {
|
|||
return reinterpret_cast<pid_t>(thread);
|
||||
}
|
||||
|
||||
#elif defined(__Fuchsia__)
|
||||
|
||||
pid_t GetTID() {
|
||||
// Use our thread handle as the TID, which should be unique within this
|
||||
// process (but may not be globally unique). The handle value was chosen over
|
||||
// a kernel object ID (KOID) because zx_handle_t (32-bits) can be cast to a
|
||||
// pid_t type without loss of precision, but a zx_koid_t (64-bits) cannot.
|
||||
return static_cast<pid_t>(zx_thread_self());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Fallback implementation of `GetTID` using `pthread_self`.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ TEST(SysinfoTest, GetTID) {
|
|||
EXPECT_EQ(GetTID(), GetTID()); // Basic compile and equality test.
|
||||
#ifdef __native_client__
|
||||
// Native Client has a race condition bug that leads to memory
|
||||
// exaustion when repeatedly creating and joining threads.
|
||||
// exhaustion when repeatedly creating and joining threads.
|
||||
// https://bugs.chromium.org/p/nativeclient/issues/detail?id=1027
|
||||
return;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,280 +0,0 @@
|
|||
// Copyright 2019 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: thread_annotations.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// WARNING: This is a backwards compatible header and it will be removed after
|
||||
// the migration to prefixed thread annotations is finished; please include
|
||||
// "absl/base/thread_annotations.h".
|
||||
//
|
||||
// This header file contains macro definitions for thread safety annotations
|
||||
// that allow developers to document the locking policies of multi-threaded
|
||||
// code. The annotations can also help program analysis tools to identify
|
||||
// potential thread safety issues.
|
||||
//
|
||||
// These annotations are implemented using compiler attributes. Using the macros
|
||||
// defined here instead of raw attributes allow for portability and future
|
||||
// compatibility.
|
||||
//
|
||||
// When referring to mutexes in the arguments of the attributes, you should
|
||||
// use variable names or more complex expressions (e.g. my_object->mutex_)
|
||||
// that evaluate to a concrete mutex object whenever possible. If the mutex
|
||||
// you want to refer to is not in scope, you may use a member pointer
|
||||
// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
|
||||
#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
|
||||
|
||||
// ABSL_LEGACY_THREAD_ANNOTATIONS is a *temporary* compatibility macro that can
|
||||
// be defined on the compile command-line to restore the legacy spellings of the
|
||||
// thread annotations macros/functions. The macros in this file are available
|
||||
// under ABSL_ prefixed spellings in absl/base/thread_annotations.h. This macro
|
||||
// and the legacy spellings will be removed in the future.
|
||||
#ifdef ABSL_LEGACY_THREAD_ANNOTATIONS
|
||||
|
||||
#if defined(__clang__)
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||
#else
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
||||
#endif
|
||||
|
||||
// GUARDED_BY()
|
||||
//
|
||||
// Documents if a shared field or global variable needs to be protected by a
|
||||
// mutex. GUARDED_BY() allows the user to specify a particular mutex that
|
||||
// should be held when accessing the annotated variable.
|
||||
//
|
||||
// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to
|
||||
// local variables, a local variable and its associated mutex can often be
|
||||
// combined into a small class or struct, thereby allowing the annotation.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// class Foo {
|
||||
// Mutex mu_;
|
||||
// int p1_ GUARDED_BY(mu_);
|
||||
// ...
|
||||
// };
|
||||
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
||||
|
||||
// PT_GUARDED_BY()
|
||||
//
|
||||
// Documents if the memory location pointed to by a pointer should be guarded
|
||||
// by a mutex when dereferencing the pointer.
|
||||
//
|
||||
// Example:
|
||||
// class Foo {
|
||||
// Mutex mu_;
|
||||
// int *p1_ PT_GUARDED_BY(mu_);
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// Note that a pointer variable to a shared memory location could itself be a
|
||||
// shared variable.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // `q_`, guarded by `mu1_`, points to a shared memory location that is
|
||||
// // guarded by `mu2_`:
|
||||
// int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
|
||||
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
|
||||
|
||||
// ACQUIRED_AFTER() / ACQUIRED_BEFORE()
|
||||
//
|
||||
// Documents the acquisition order between locks that can be held
|
||||
// simultaneously by a thread. For any two locks that need to be annotated
|
||||
// to establish an acquisition order, only one of them needs the annotation.
|
||||
// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
|
||||
// and ACQUIRED_BEFORE.)
|
||||
//
|
||||
// As with GUARDED_BY, this is only applicable to mutexes that are shared
|
||||
// fields or global variables.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// Mutex m1_;
|
||||
// Mutex m2_ ACQUIRED_AFTER(m1_);
|
||||
#define ACQUIRED_AFTER(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
|
||||
|
||||
#define ACQUIRED_BEFORE(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
|
||||
|
||||
// EXCLUSIVE_LOCKS_REQUIRED() / SHARED_LOCKS_REQUIRED()
|
||||
//
|
||||
// Documents a function that expects a mutex to be held prior to entry.
|
||||
// The mutex is expected to be held both on entry to, and exit from, the
|
||||
// function.
|
||||
//
|
||||
// An exclusive lock allows read-write access to the guarded data member(s), and
|
||||
// only one thread can acquire a lock exclusively at any one time. A shared lock
|
||||
// allows read-only access, and any number of threads can acquire a shared lock
|
||||
// concurrently.
|
||||
//
|
||||
// Generally, non-const methods should be annotated with
|
||||
// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
|
||||
// SHARED_LOCKS_REQUIRED.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// Mutex mu1, mu2;
|
||||
// int a GUARDED_BY(mu1);
|
||||
// int b GUARDED_BY(mu2);
|
||||
//
|
||||
// void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
|
||||
// void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
|
||||
#define EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
|
||||
|
||||
#define SHARED_LOCKS_REQUIRED(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
|
||||
|
||||
// LOCKS_EXCLUDED()
|
||||
//
|
||||
// Documents the locks acquired in the body of the function. These locks
|
||||
// cannot be held when calling this function (as Abseil's `Mutex` locks are
|
||||
// non-reentrant).
|
||||
#define LOCKS_EXCLUDED(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
|
||||
|
||||
// LOCK_RETURNED()
|
||||
//
|
||||
// Documents a function that returns a mutex without acquiring it. For example,
|
||||
// a public getter method that returns a pointer to a private mutex should
|
||||
// be annotated with LOCK_RETURNED.
|
||||
#define LOCK_RETURNED(x) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
|
||||
// LOCKABLE
|
||||
//
|
||||
// Documents if a class/type is a lockable type (such as the `Mutex` class).
|
||||
#define LOCKABLE \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(lockable)
|
||||
|
||||
// SCOPED_LOCKABLE
|
||||
//
|
||||
// Documents if a class does RAII locking (such as the `MutexLock` class).
|
||||
// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is
|
||||
// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
|
||||
// arguments; the analysis will assume that the destructor unlocks whatever the
|
||||
// constructor locked.
|
||||
#define SCOPED_LOCKABLE \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
|
||||
// EXCLUSIVE_LOCK_FUNCTION()
|
||||
//
|
||||
// Documents functions that acquire a lock in the body of a function, and do
|
||||
// not release it.
|
||||
#define EXCLUSIVE_LOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
|
||||
|
||||
// SHARED_LOCK_FUNCTION()
|
||||
//
|
||||
// Documents functions that acquire a shared (reader) lock in the body of a
|
||||
// function, and do not release it.
|
||||
#define SHARED_LOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
|
||||
|
||||
// UNLOCK_FUNCTION()
|
||||
//
|
||||
// Documents functions that expect a lock to be held on entry to the function,
|
||||
// and release it in the body of the function.
|
||||
#define UNLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
|
||||
|
||||
// EXCLUSIVE_TRYLOCK_FUNCTION() / SHARED_TRYLOCK_FUNCTION()
|
||||
//
|
||||
// Documents functions that try to acquire a lock, and return success or failure
|
||||
// (or a non-boolean value that can be interpreted as a boolean).
|
||||
// The first argument should be `true` for functions that return `true` on
|
||||
// success, or `false` for functions that return `false` on success. The second
|
||||
// argument specifies the mutex that is locked on success. If unspecified, this
|
||||
// mutex is assumed to be `this`.
|
||||
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
|
||||
|
||||
#define SHARED_TRYLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
|
||||
|
||||
// ASSERT_EXCLUSIVE_LOCK() / ASSERT_SHARED_LOCK()
|
||||
//
|
||||
// Documents functions that dynamically check to see if a lock is held, and fail
|
||||
// if it is not held.
|
||||
#define ASSERT_EXCLUSIVE_LOCK(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
|
||||
|
||||
#define ASSERT_SHARED_LOCK(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
|
||||
|
||||
// NO_THREAD_SAFETY_ANALYSIS
|
||||
//
|
||||
// Turns off thread safety checking within the body of a particular function.
|
||||
// This annotation is used to mark functions that are known to be correct, but
|
||||
// the locking behavior is more complicated than the analyzer can handle.
|
||||
#define NO_THREAD_SAFETY_ANALYSIS \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Tool-Supplied Annotations
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// TS_UNCHECKED should be placed around lock expressions that are not valid
|
||||
// C++ syntax, but which are present for documentation purposes. These
|
||||
// annotations will be ignored by the analysis.
|
||||
#define TS_UNCHECKED(x) ""
|
||||
|
||||
// TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
|
||||
// It is used by automated tools to mark and disable invalid expressions.
|
||||
// The annotation should either be fixed, or changed to TS_UNCHECKED.
|
||||
#define TS_FIXME(x) ""
|
||||
|
||||
// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of
|
||||
// a particular function. However, this attribute is used to mark functions
|
||||
// that are incorrect and need to be fixed. It is used by automated tools to
|
||||
// avoid breaking the build when the analysis is updated.
|
||||
// Code owners are expected to eventually fix the routine.
|
||||
#define NO_THREAD_SAFETY_ANALYSIS_FIXME NO_THREAD_SAFETY_ANALYSIS
|
||||
|
||||
// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a GUARDED_BY
|
||||
// annotation that needs to be fixed, because it is producing thread safety
|
||||
// warning. It disables the GUARDED_BY.
|
||||
#define GUARDED_BY_FIXME(x)
|
||||
|
||||
// Disables warnings for a single read operation. This can be used to avoid
|
||||
// warnings when it is known that the read is not actually involved in a race,
|
||||
// but the compiler cannot confirm that.
|
||||
#define TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x)
|
||||
|
||||
|
||||
namespace thread_safety_analysis {
|
||||
|
||||
// Takes a reference to a guarded data member, and returns an unguarded
|
||||
// reference.
|
||||
template <typename T>
|
||||
inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace thread_safety_analysis
|
||||
|
||||
#endif // defined(ABSL_LEGACY_THREAD_ANNOTATIONS)
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
|
||||
|
|
@ -16,8 +16,12 @@
|
|||
|
||||
#if !defined(_WIN32) || defined(__MINGW32__)
|
||||
#include <pthread.h>
|
||||
#ifndef __wasi__
|
||||
// WASI does not provide this header, either way we disable use
|
||||
// of signals with it below.
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
|
|
@ -80,10 +84,12 @@ void SetCurrentThreadIdentity(ThreadIdentity* identity,
|
|||
absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
|
||||
reclaimer);
|
||||
|
||||
#if defined(__EMSCRIPTEN__) || defined(__MINGW32__) || defined(__hexagon__)
|
||||
// Emscripten and MinGW pthread implementations does not support signals.
|
||||
// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
|
||||
// for more information.
|
||||
#if defined(__wasi__) || defined(__EMSCRIPTEN__) || defined(__MINGW32__) || \
|
||||
defined(__hexagon__)
|
||||
// Emscripten, WASI and MinGW pthread implementations does not support
|
||||
// signals. See
|
||||
// https://kripken.github.io/emscripten-site/docs/porting/pthreads.html for
|
||||
// more information.
|
||||
pthread_setspecific(thread_identity_pthread_key,
|
||||
reinterpret_cast<void*>(identity));
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -130,7 +130,11 @@ struct PerThreadSynch {
|
|||
};
|
||||
|
||||
// The instances of this class are allocated in NewThreadIdentity() with an
|
||||
// alignment of PerThreadSynch::kAlignment.
|
||||
// alignment of PerThreadSynch::kAlignment and never destroyed. Initialization
|
||||
// should happen in OneTimeInitThreadIdentity().
|
||||
//
|
||||
// Instances may be reused by new threads - fields should be reset in
|
||||
// ResetThreadIdentityBetweenReuse().
|
||||
//
|
||||
// NOTE: The layout of fields in this structure is critical, please do not
|
||||
// add, remove, or modify the field placements without fully auditing the
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "absl/base/internal/thread_identity.h"
|
||||
#include "absl/synchronization/internal/create_thread_identity.h"
|
||||
#include "absl/synchronization/internal/per_thread_sem.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/tracing.h"
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
extern "C" {
|
||||
|
||||
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(
|
||||
const void*, ObjectKind) {}
|
||||
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(
|
||||
const void*, ObjectKind) {}
|
||||
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(
|
||||
const void*, ObjectKind) {}
|
||||
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(
|
||||
const void*, ObjectKind) {}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_TRACING_H_
|
||||
#define ABSL_BASE_INTERNAL_TRACING_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// Well known Abseil object types that have causality.
|
||||
enum class ObjectKind { kUnknown, kBlockingCounter, kNotification };
|
||||
|
||||
// `TraceWait` and `TraceContinue` record the start and end of a potentially
|
||||
// blocking wait operation on `object`. `object` typically represents a higher
|
||||
// level synchronization object such as `absl::Notification`.
|
||||
void TraceWait(const void* object, ObjectKind kind);
|
||||
void TraceContinue(const void* object, ObjectKind kind);
|
||||
|
||||
// `TraceSignal` records a signal on `object`.
|
||||
void TraceSignal(const void* object, ObjectKind kind);
|
||||
|
||||
// `TraceObserved` records the non-blocking observation of a signaled object.
|
||||
void TraceObserved(const void* object, ObjectKind kind);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Weak implementation detail:
|
||||
//
|
||||
// We define the weak API as extern "C": in some build configurations we pass
|
||||
// `--detect-odr-violations` to the gold linker. This causes it to flag weak
|
||||
// symbol overrides as ODR violations. Because ODR only applies to C++ and not
|
||||
// C, `--detect-odr-violations` ignores symbols not mangled with C++ names.
|
||||
// By changing our extension points to be extern "C", we dodge this check.
|
||||
// ---------------------------------------------------------------------------
|
||||
extern "C" {
|
||||
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
|
||||
ObjectKind kind);
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
|
||||
ObjectKind kind);
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
|
||||
ObjectKind kind);
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
|
||||
ObjectKind kind);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
inline void TraceWait(const void* object, ObjectKind kind) {
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(object, kind);
|
||||
}
|
||||
|
||||
inline void TraceContinue(const void* object, ObjectKind kind) {
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(object, kind);
|
||||
}
|
||||
|
||||
inline void TraceSignal(const void* object, ObjectKind kind) {
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(object, kind);
|
||||
}
|
||||
|
||||
inline void TraceObserved(const void* object, ObjectKind kind) {
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(object, kind);
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_TRACING_H_
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/tracing.h"
|
||||
|
||||
#if ABSL_HAVE_ATTRIBUTE_WEAK
|
||||
|
||||
namespace {
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
|
||||
using ::absl::base_internal::ObjectKind;
|
||||
|
||||
enum Function { kWait, kContinue, kSignal, kObserved };
|
||||
|
||||
using Record = std::tuple<Function, const void*, ObjectKind>;
|
||||
|
||||
thread_local std::vector<Record>* tls_records = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// Strong extern "C" implementation.
|
||||
extern "C" {
|
||||
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
|
||||
ObjectKind kind) {
|
||||
if (tls_records != nullptr) {
|
||||
tls_records->push_back({kWait, object, kind});
|
||||
}
|
||||
}
|
||||
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
|
||||
ObjectKind kind) {
|
||||
if (tls_records != nullptr) {
|
||||
tls_records->push_back({kContinue, object, kind});
|
||||
}
|
||||
}
|
||||
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
|
||||
ObjectKind kind) {
|
||||
if (tls_records != nullptr) {
|
||||
tls_records->push_back({kSignal, object, kind});
|
||||
}
|
||||
}
|
||||
|
||||
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
|
||||
ObjectKind kind) {
|
||||
if (tls_records != nullptr) {
|
||||
tls_records->push_back({kObserved, object, kind});
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(TracingInternal, InvokesStrongFunctionWithNullptr) {
|
||||
std::vector<Record> records;
|
||||
tls_records = &records;
|
||||
auto kind = absl::base_internal::ObjectKind::kUnknown;
|
||||
absl::base_internal::TraceWait(nullptr, kind);
|
||||
absl::base_internal::TraceContinue(nullptr, kind);
|
||||
absl::base_internal::TraceSignal(nullptr, kind);
|
||||
absl::base_internal::TraceObserved(nullptr, kind);
|
||||
tls_records = nullptr;
|
||||
|
||||
EXPECT_THAT(records, ElementsAre(Record{kWait, nullptr, kind},
|
||||
Record{kContinue, nullptr, kind},
|
||||
Record{kSignal, nullptr, kind},
|
||||
Record{kObserved, nullptr, kind}));
|
||||
}
|
||||
|
||||
TEST(TracingInternal, InvokesStrongFunctionWithObjectAddress) {
|
||||
int object = 0;
|
||||
std::vector<Record> records;
|
||||
tls_records = &records;
|
||||
auto kind = absl::base_internal::ObjectKind::kUnknown;
|
||||
absl::base_internal::TraceWait(&object, kind);
|
||||
absl::base_internal::TraceContinue(&object, kind);
|
||||
absl::base_internal::TraceSignal(&object, kind);
|
||||
absl::base_internal::TraceObserved(&object, kind);
|
||||
tls_records = nullptr;
|
||||
|
||||
EXPECT_THAT(records, ElementsAre(Record{kWait, &object, kind},
|
||||
Record{kContinue, &object, kind},
|
||||
Record{kSignal, &object, kind},
|
||||
Record{kObserved, &object, kind}));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // ABSL_HAVE_ATTRIBUTE_WEAK
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2024 The Abseil Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/internal/tracing.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(TracingInternal, HasDefaultImplementation) {
|
||||
auto kind = absl::base_internal::ObjectKind::kUnknown;
|
||||
absl::base_internal::TraceWait(nullptr, kind);
|
||||
absl::base_internal::TraceContinue(nullptr, kind);
|
||||
absl::base_internal::TraceSignal(nullptr, kind);
|
||||
absl::base_internal::TraceObserved(nullptr, kind);
|
||||
|
||||
int object = 0;
|
||||
absl::base_internal::TraceWait(&object, kind);
|
||||
absl::base_internal::TraceContinue(&object, kind);
|
||||
absl::base_internal::TraceSignal(&object, kind);
|
||||
absl::base_internal::TraceObserved(&object, kind);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/nullability.h"
|
||||
|
||||
// unaligned APIs
|
||||
|
||||
|
|
@ -35,29 +36,35 @@ namespace absl {
|
|||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
inline uint16_t UnalignedLoad16(const void *p) {
|
||||
inline uint16_t UnalignedLoad16(const void* absl_nonnull p) {
|
||||
uint16_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint32_t UnalignedLoad32(const void *p) {
|
||||
inline uint32_t UnalignedLoad32(const void* absl_nonnull p) {
|
||||
uint32_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64_t UnalignedLoad64(const void *p) {
|
||||
inline uint64_t UnalignedLoad64(const void* absl_nonnull p) {
|
||||
uint64_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); }
|
||||
inline void UnalignedStore16(void* absl_nonnull p, uint16_t v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
|
||||
inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
|
||||
inline void UnalignedStore32(void* absl_nonnull p, uint32_t v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
|
||||
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
|
||||
inline void UnalignedStore64(void* absl_nonnull p, uint64_t v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -105,34 +105,12 @@ double UnscaledCycleClock::Frequency() {
|
|||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
// System timer of ARMv8 runs at a different frequency than the CPU's.
|
||||
// The frequency is fixed, typically in the range 1-50MHz. It can be
|
||||
// read at CNTFRQ special register. We assume the OS has set up
|
||||
// the virtual timer properly.
|
||||
int64_t UnscaledCycleClock::Now() {
|
||||
int64_t virtual_timer_value;
|
||||
asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
|
||||
return virtual_timer_value;
|
||||
}
|
||||
|
||||
double UnscaledCycleClock::Frequency() {
|
||||
uint64_t aarch64_timer_frequency;
|
||||
asm volatile("mrs %0, cntfrq_el0" : "=r"(aarch64_timer_frequency));
|
||||
return aarch64_timer_frequency;
|
||||
}
|
||||
|
||||
#elif defined(__riscv)
|
||||
|
||||
int64_t UnscaledCycleClock::Now() {
|
||||
int64_t virtual_timer_value;
|
||||
asm volatile("rdcycle %0" : "=r"(virtual_timer_value));
|
||||
return virtual_timer_value;
|
||||
}
|
||||
|
||||
double UnscaledCycleClock::Frequency() {
|
||||
return base_internal::NominalCPUFrequency();
|
||||
}
|
||||
|
||||
#elif defined(_M_IX86) || defined(_M_X64)
|
||||
|
||||
#pragma intrinsic(__rdtsc)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,23 @@ inline int64_t UnscaledCycleClock::Now() {
|
|||
return static_cast<int64_t>((high << 32) | low);
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
// System timer of ARMv8 runs at a different frequency than the CPU's.
|
||||
//
|
||||
// Frequency is fixed. From Armv8.6-A and Armv9.1-A on, the frequency is 1GHz.
|
||||
// Pre-Armv8.6-A, the frequency was a system design choice, typically in the
|
||||
// range of 1MHz to 50MHz. See also:
|
||||
// https://developer.arm.com/documentation/102379/0101/What-is-the-Generic-Timer-
|
||||
//
|
||||
// It can be read at CNTFRQ special register. We assume the OS has set up the
|
||||
// virtual timer properly.
|
||||
inline int64_t UnscaledCycleClock::Now() {
|
||||
int64_t virtual_timer_value;
|
||||
asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
|
||||
return virtual_timer_value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace base_internal
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
// The following platforms have an implementation of a hardware counter.
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
|
||||
defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
|
||||
defined(__powerpc__) || defined(__ppc__) || defined(_M_IX86) || \
|
||||
(defined(_M_X64) && !defined(_M_ARM64EC))
|
||||
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
|
||||
#else
|
||||
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
|
||||
|
|
@ -53,8 +53,8 @@
|
|||
#if ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
// This macro can be used to test if UnscaledCycleClock::Frequency()
|
||||
// is NominalCPUFrequency() on a particular platform.
|
||||
#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
|
||||
defined(_M_IX86) || defined(_M_X64))
|
||||
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
|
||||
defined(_M_X64))
|
||||
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,331 +0,0 @@
|
|||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/invoke.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
namespace {
|
||||
|
||||
int Function(int a, int b) { return a - b; }
|
||||
|
||||
void VoidFunction(int& a, int& b) {
|
||||
a += b;
|
||||
b = a - b;
|
||||
a -= b;
|
||||
}
|
||||
|
||||
int ZeroArgFunction() { return -1937; }
|
||||
|
||||
int Sink(std::unique_ptr<int> p) {
|
||||
return *p;
|
||||
}
|
||||
|
||||
std::unique_ptr<int> Factory(int n) {
|
||||
return make_unique<int>(n);
|
||||
}
|
||||
|
||||
void NoOp() {}
|
||||
|
||||
struct ConstFunctor {
|
||||
int operator()(int a, int b) const { return a - b; }
|
||||
};
|
||||
|
||||
struct MutableFunctor {
|
||||
int operator()(int a, int b) { return a - b; }
|
||||
};
|
||||
|
||||
struct EphemeralFunctor {
|
||||
int operator()(int a, int b) && { return a - b; }
|
||||
};
|
||||
|
||||
struct OverloadedFunctor {
|
||||
template <typename... Args>
|
||||
std::string operator()(const Args&... args) & {
|
||||
return StrCat("&", args...);
|
||||
}
|
||||
template <typename... Args>
|
||||
std::string operator()(const Args&... args) const& {
|
||||
return StrCat("const&", args...);
|
||||
}
|
||||
template <typename... Args>
|
||||
std::string operator()(const Args&... args) && {
|
||||
return StrCat("&&", args...);
|
||||
}
|
||||
};
|
||||
|
||||
struct Class {
|
||||
int Method(int a, int b) { return a - b; }
|
||||
int ConstMethod(int a, int b) const { return a - b; }
|
||||
int RefMethod(int a, int b) & { return a - b; }
|
||||
int RefRefMethod(int a, int b) && { return a - b; }
|
||||
int NoExceptMethod(int a, int b) noexcept { return a - b; }
|
||||
int VolatileMethod(int a, int b) volatile { return a - b; }
|
||||
|
||||
int member;
|
||||
};
|
||||
|
||||
struct FlipFlop {
|
||||
int ConstMethod() const { return member; }
|
||||
FlipFlop operator*() const { return {-member}; }
|
||||
|
||||
int member;
|
||||
};
|
||||
|
||||
// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
|
||||
// on which one is valid.
|
||||
template <typename F>
|
||||
decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
|
||||
const F& f) {
|
||||
return base_internal::invoke(f);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
|
||||
const F& f) {
|
||||
return base_internal::invoke(f, 42);
|
||||
}
|
||||
|
||||
TEST(InvokeTest, Function) {
|
||||
EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, NonCopyableArgument) {
|
||||
EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, NonCopyableResult) {
|
||||
EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
|
||||
|
||||
TEST(InvokeTest, ConstFunctor) {
|
||||
EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, MutableFunctor) {
|
||||
MutableFunctor f;
|
||||
EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, EphemeralFunctor) {
|
||||
EphemeralFunctor f;
|
||||
EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, OverloadedFunctor) {
|
||||
OverloadedFunctor f;
|
||||
const OverloadedFunctor& cf = f;
|
||||
|
||||
EXPECT_EQ("&", base_internal::invoke(f));
|
||||
EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
|
||||
|
||||
EXPECT_EQ("const&", base_internal::invoke(cf));
|
||||
EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
|
||||
|
||||
EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
|
||||
|
||||
OverloadedFunctor f2;
|
||||
EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, ReferenceWrapper) {
|
||||
ConstFunctor cf;
|
||||
MutableFunctor mf;
|
||||
EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, MemberFunction) {
|
||||
std::unique_ptr<Class> p(new Class);
|
||||
std::unique_ptr<const Class> cp(new Class);
|
||||
std::unique_ptr<volatile Class> vp(new Class);
|
||||
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
|
||||
2)); // NOLINT
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
|
||||
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
|
||||
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
|
||||
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
|
||||
|
||||
EXPECT_EQ(1,
|
||||
base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
|
||||
3, 2));
|
||||
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
|
||||
make_unique<const Class>(), 3, 2));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, DataMember) {
|
||||
std::unique_ptr<Class> p(new Class{42});
|
||||
std::unique_ptr<const Class> cp(new Class{42});
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
|
||||
|
||||
base_internal::invoke(&Class::member, p) = 42;
|
||||
base_internal::invoke(&Class::member, p.get()) = 42;
|
||||
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
|
||||
EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, FlipFlop) {
|
||||
FlipFlop obj = {42};
|
||||
// This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
|
||||
// ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
|
||||
EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
|
||||
EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
|
||||
}
|
||||
|
||||
TEST(InvokeTest, SfinaeFriendly) {
|
||||
CallMaybeWithArg(NoOp);
|
||||
EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableExactMatch) {
|
||||
static_assert(
|
||||
base_internal::is_invocable_r<int, decltype(Function), int, int>::value,
|
||||
"Should be true for exact match of types on a free function");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableArgumentConversionMatch) {
|
||||
static_assert(
|
||||
base_internal::is_invocable_r<int, decltype(Function), char, int>::value,
|
||||
"Should be true for convertible argument type");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableReturnConversionMatch) {
|
||||
static_assert(base_internal::is_invocable_r<double, decltype(Function), int,
|
||||
int>::value,
|
||||
"Should be true for convertible return type");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableReturnVoid) {
|
||||
static_assert(base_internal::is_invocable_r<void, decltype(VoidFunction),
|
||||
int&, int&>::value,
|
||||
"Should be true for void expected and actual return types");
|
||||
static_assert(
|
||||
base_internal::is_invocable_r<void, decltype(Function), int, int>::value,
|
||||
"Should be true for void expected and non-void actual return types");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableRefQualifierMismatch) {
|
||||
static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
|
||||
int&, const int&>::value,
|
||||
"Should be false for reference constness mismatch");
|
||||
static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
|
||||
int&&, int&>::value,
|
||||
"Should be false for reference value category mismatch");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableArgumentTypeMismatch) {
|
||||
static_assert(!base_internal::is_invocable_r<int, decltype(Function),
|
||||
std::string, int>::value,
|
||||
"Should be false for argument type mismatch");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableReturnTypeMismatch) {
|
||||
static_assert(!base_internal::is_invocable_r<std::string, decltype(Function),
|
||||
int, int>::value,
|
||||
"Should be false for return type mismatch");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableTooFewArgs) {
|
||||
static_assert(
|
||||
!base_internal::is_invocable_r<int, decltype(Function), int>::value,
|
||||
"Should be false for too few arguments");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableTooManyArgs) {
|
||||
static_assert(!base_internal::is_invocable_r<int, decltype(Function), int,
|
||||
int, int>::value,
|
||||
"Should be false for too many arguments");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, MemberFunctionAndReference) {
|
||||
static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
|
||||
Class&, int, int>::value,
|
||||
"Should be true for exact match of types on a member function "
|
||||
"and class reference");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, MemberFunctionAndPointer) {
|
||||
static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
|
||||
Class*, int, int>::value,
|
||||
"Should be true for exact match of types on a member function "
|
||||
"and class pointer");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, DataMemberAndReference) {
|
||||
static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
|
||||
Class&>::value,
|
||||
"Should be true for exact match of types on a data member and "
|
||||
"class reference");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, DataMemberAndPointer) {
|
||||
static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
|
||||
Class*>::value,
|
||||
"Should be true for exact match of types on a data member and "
|
||||
"class pointer");
|
||||
}
|
||||
|
||||
TEST(IsInvocableRTest, CallableZeroArgs) {
|
||||
static_assert(
|
||||
base_internal::is_invocable_r<int, decltype(ZeroArgFunction)>::value,
|
||||
"Should be true for exact match for a zero-arg free function");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include <ostream>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ ABSL_NAMESPACE_BEGIN
|
|||
// --my_log_level=info
|
||||
// --my_log_level=0
|
||||
//
|
||||
// `DFATAL` and `kLogDebugFatal` are similarly accepted.
|
||||
//
|
||||
// Unparsing a flag produces the same result as `absl::LogSeverityName()` for
|
||||
// the standard levels and a base-ten integer otherwise.
|
||||
enum class LogSeverity : int {
|
||||
|
|
@ -82,18 +84,28 @@ constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
|
|||
absl::LogSeverity::kError, absl::LogSeverity::kFatal}};
|
||||
}
|
||||
|
||||
// `absl::kLogDebugFatal` equals `absl::LogSeverity::kFatal` in debug builds
|
||||
// (i.e. when `NDEBUG` is not defined) and `absl::LogSeverity::kError`
|
||||
// otherwise. Avoid ODR-using this variable as it has internal linkage and thus
|
||||
// distinct storage in different TUs.
|
||||
#ifdef NDEBUG
|
||||
static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kError;
|
||||
#else
|
||||
static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kFatal;
|
||||
#endif
|
||||
|
||||
// LogSeverityName()
|
||||
//
|
||||
// Returns the all-caps string representation (e.g. "INFO") of the specified
|
||||
// severity level if it is one of the standard levels and "UNKNOWN" otherwise.
|
||||
constexpr const char* LogSeverityName(absl::LogSeverity s) {
|
||||
return s == absl::LogSeverity::kInfo
|
||||
? "INFO"
|
||||
: s == absl::LogSeverity::kWarning
|
||||
? "WARNING"
|
||||
: s == absl::LogSeverity::kError
|
||||
? "ERROR"
|
||||
: s == absl::LogSeverity::kFatal ? "FATAL" : "UNKNOWN";
|
||||
switch (s) {
|
||||
case absl::LogSeverity::kInfo: return "INFO";
|
||||
case absl::LogSeverity::kWarning: return "WARNING";
|
||||
case absl::LogSeverity::kError: return "ERROR";
|
||||
case absl::LogSeverity::kFatal: return "FATAL";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
// NormalizeLogSeverity()
|
||||
|
|
@ -101,9 +113,10 @@ constexpr const char* LogSeverityName(absl::LogSeverity s) {
|
|||
// Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal`
|
||||
// normalize to `kError` (**NOT** `kFatal`).
|
||||
constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) {
|
||||
return s < absl::LogSeverity::kInfo
|
||||
? absl::LogSeverity::kInfo
|
||||
: s > absl::LogSeverity::kFatal ? absl::LogSeverity::kError : s;
|
||||
absl::LogSeverity n = s;
|
||||
if (n < absl::LogSeverity::kInfo) n = absl::LogSeverity::kInfo;
|
||||
if (n > absl::LogSeverity::kFatal) n = absl::LogSeverity::kError;
|
||||
return n;
|
||||
}
|
||||
constexpr absl::LogSeverity NormalizeLogSeverity(int s) {
|
||||
return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));
|
||||
|
|
|
|||
|
|
@ -146,7 +146,12 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
std::make_tuple("fatal", absl::LogSeverity::kFatal),
|
||||
std::make_tuple("kFatal", absl::LogSeverity::kFatal),
|
||||
std::make_tuple("FaTaL", absl::LogSeverity::kFatal),
|
||||
std::make_tuple("KfAtAl", absl::LogSeverity::kFatal)));
|
||||
std::make_tuple("KfAtAl", absl::LogSeverity::kFatal),
|
||||
std::make_tuple("DFATAL", absl::kLogDebugFatal),
|
||||
std::make_tuple("dfatal", absl::kLogDebugFatal),
|
||||
std::make_tuple("kLogDebugFatal", absl::kLogDebugFatal),
|
||||
std::make_tuple("dFaTaL", absl::kLogDebugFatal),
|
||||
std::make_tuple("kLoGdEbUgFaTaL", absl::kLogDebugFatal)));
|
||||
TEST_P(ParseFlagFromEnumeratorTest, YieldsExpectedValue) {
|
||||
const absl::string_view to_parse = std::get<0>(GetParam());
|
||||
const absl::LogSeverity expected = std::get<1>(GetParam());
|
||||
|
|
@ -158,7 +163,8 @@ TEST_P(ParseFlagFromEnumeratorTest, YieldsExpectedValue) {
|
|||
|
||||
using ParseFlagFromGarbageTest = TestWithParam<absl::string_view>;
|
||||
INSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromGarbageTest,
|
||||
Values("", "\0", " ", "garbage", "kkinfo", "I"));
|
||||
Values("", "\0", " ", "garbage", "kkinfo", "I",
|
||||
"kDFATAL", "LogDebugFatal", "lOgDeBuGfAtAl"));
|
||||
TEST_P(ParseFlagFromGarbageTest, ReturnsError) {
|
||||
const absl::string_view to_parse = GetParam();
|
||||
absl::LogSeverity value;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/optimization.h"
|
||||
#include "absl/base/options.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
// ABSL_ARRAYSIZE()
|
||||
|
|
@ -81,8 +82,9 @@ ABSL_NAMESPACE_END
|
|||
// ABSL_ASSERT()
|
||||
//
|
||||
// In C++11, `assert` can't be used portably within constexpr functions.
|
||||
// `assert` also generates spurious unused-symbol warnings.
|
||||
// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr
|
||||
// functions. Example:
|
||||
// functions, and maintains references to symbols. Example:
|
||||
//
|
||||
// constexpr double Divide(double a, double b) {
|
||||
// return ABSL_ASSERT(b != 0), a / b;
|
||||
|
|
@ -91,8 +93,18 @@ ABSL_NAMESPACE_END
|
|||
// This macro is inspired by
|
||||
// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
|
||||
#if defined(NDEBUG)
|
||||
#define ABSL_ASSERT(expr) \
|
||||
(false ? static_cast<void>(expr) : static_cast<void>(0))
|
||||
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
// We use `decltype` here to avoid generating unnecessary code that the
|
||||
// optimizer then has to optimize away.
|
||||
// This not only improves compilation performance by reducing codegen bloat
|
||||
// and optimization work, but also guarantees fast run-time performance without
|
||||
// having to rely on the optimizer.
|
||||
#define ABSL_ASSERT(expr) (decltype((expr) ? void() : void())())
|
||||
#else
|
||||
// Pre-C++20, lambdas can't be inside unevaluated operands, so we're forced to
|
||||
// rely on the optimizer.
|
||||
#define ABSL_ASSERT(expr) (false ? ((expr) ? void() : void()) : void())
|
||||
#endif
|
||||
#else
|
||||
#define ABSL_ASSERT(expr) \
|
||||
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
|
||||
|
|
@ -120,7 +132,7 @@ ABSL_NAMESPACE_END
|
|||
//
|
||||
// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
|
||||
// hardened mode.
|
||||
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
|
||||
#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
|
||||
#define ABSL_HARDENING_ASSERT(expr) \
|
||||
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
|
||||
: [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
|
||||
|
|
@ -128,6 +140,25 @@ ABSL_NAMESPACE_END
|
|||
#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
// ABSL_HARDENING_ASSERT_SLOW()
|
||||
//
|
||||
// `ABSL_HARDENING_ASSERT()` is like `ABSL_HARDENING_ASSERT()`,
|
||||
// but specifically for assertions whose predicates are too slow
|
||||
// to be enabled in many applications.
|
||||
//
|
||||
// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT_SLOW()` is identical to
|
||||
// `ABSL_ASSERT()`.
|
||||
//
|
||||
// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
|
||||
// hardened mode.
|
||||
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
|
||||
#define ABSL_HARDENING_ASSERT_SLOW(expr) \
|
||||
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
|
||||
: [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
|
||||
#else
|
||||
#define ABSL_HARDENING_ASSERT_SLOW(expr) ABSL_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
#define ABSL_INTERNAL_TRY try
|
||||
#define ABSL_INTERNAL_CATCH_ANY catch (...)
|
||||
|
|
@ -138,4 +169,52 @@ ABSL_NAMESPACE_END
|
|||
#define ABSL_INTERNAL_RETHROW do {} while (false)
|
||||
#endif // ABSL_HAVE_EXCEPTIONS
|
||||
|
||||
// ABSL_DEPRECATE_AND_INLINE()
|
||||
//
|
||||
// Marks a function or type alias as deprecated and tags it to be picked up for
|
||||
// automated refactoring by go/cpp-inliner. It can added to inline function
|
||||
// definitions or type aliases. It should only be used within a header file. It
|
||||
// differs from `ABSL_DEPRECATED` in the following ways:
|
||||
//
|
||||
// 1. New uses of the function or type will be discouraged via Tricorder
|
||||
// warnings.
|
||||
// 2. If enabled via `METADATA`, automated changes will be sent out inlining the
|
||||
// functions's body or replacing the type where it is used.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// ABSL_DEPRECATE_AND_INLINE() inline int OldFunc(int x) {
|
||||
// return NewFunc(x, 0);
|
||||
// }
|
||||
//
|
||||
// will mark `OldFunc` as deprecated, and the go/cpp-inliner service will
|
||||
// replace calls to `OldFunc(x)` with calls to `NewFunc(x, 0)`. Once all calls
|
||||
// to `OldFunc` have been replaced, `OldFunc` can be deleted.
|
||||
//
|
||||
// See go/cpp-inliner for more information.
|
||||
//
|
||||
// Note: go/cpp-inliner is Google-internal service for automated refactoring.
|
||||
// While open-source users do not have access to this service, the macro is
|
||||
// provided for compatibility, and so that users receive deprecation warnings.
|
||||
#if ABSL_HAVE_CPP_ATTRIBUTE(deprecated) && \
|
||||
ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
#define ABSL_DEPRECATE_AND_INLINE() [[deprecated, clang::annotate("inline-me")]]
|
||||
#elif ABSL_HAVE_CPP_ATTRIBUTE(deprecated)
|
||||
#define ABSL_DEPRECATE_AND_INLINE() [[deprecated]]
|
||||
#else
|
||||
#define ABSL_DEPRECATE_AND_INLINE()
|
||||
#endif
|
||||
|
||||
// Requires the compiler to prove that the size of the given object is at least
|
||||
// the expected amount.
|
||||
#if ABSL_HAVE_ATTRIBUTE(diagnose_if) && ABSL_HAVE_BUILTIN(__builtin_object_size)
|
||||
#define ABSL_INTERNAL_NEED_MIN_SIZE(Obj, N) \
|
||||
__attribute__((diagnose_if(__builtin_object_size(Obj, 0) < N, \
|
||||
"object size provably too small " \
|
||||
"(this would corrupt memory)", \
|
||||
"error")))
|
||||
#else
|
||||
#define ABSL_INTERNAL_NEED_MIN_SIZE(Obj, N)
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_MACROS_H_
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
// Copyright 2023 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: no_destructor.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file defines the absl::NoDestructor<T> wrapper for defining a
|
||||
// static type that does not need to be destructed upon program exit. Instead,
|
||||
// such an object survives during program exit (and can be safely accessed at
|
||||
// any time).
|
||||
//
|
||||
// absl::NoDestructor<T> is useful when when a variable has static storage
|
||||
// duration but its type has a non-trivial destructor. Global constructors are
|
||||
// not recommended because of the C++'s static initialization order fiasco (See
|
||||
// https://en.cppreference.com/w/cpp/language/siof). Global destructors are not
|
||||
// allowed due to similar concerns about destruction ordering. Using
|
||||
// absl::NoDestructor<T> as a function-local static prevents both of these
|
||||
// issues.
|
||||
//
|
||||
// See below for complete details.
|
||||
|
||||
|
||||
#ifndef ABSL_BASE_NO_DESTRUCTOR_H_
|
||||
#define ABSL_BASE_NO_DESTRUCTOR_H_
|
||||
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/nullability.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
// absl::NoDestructor<T>
|
||||
//
|
||||
// NoDestructor<T> is a wrapper around an object of type T that behaves as an
|
||||
// object of type T but never calls T's destructor. NoDestructor<T> makes it
|
||||
// safer and/or more efficient to use such objects in static storage contexts,
|
||||
// ideally as function scope static variables.
|
||||
//
|
||||
// An instance of absl::NoDestructor<T> has similar type semantics to an
|
||||
// instance of T:
|
||||
//
|
||||
// * Constructs in the same manner as an object of type T through perfect
|
||||
// forwarding.
|
||||
// * Provides pointer/reference semantic access to the object of type T via
|
||||
// `->`, `*`, and `get()`.
|
||||
// (Note that `const NoDestructor<T>` works like a pointer to const `T`.)
|
||||
//
|
||||
// Additionally, NoDestructor<T> provides the following benefits:
|
||||
//
|
||||
// * Never calls T's destructor for the object
|
||||
// * If the object is a function-local static variable, the type can be
|
||||
// lazily constructed.
|
||||
//
|
||||
// An object of type NoDestructor<T> is "trivially destructible" in the notion
|
||||
// that its destructor is never run.
|
||||
//
|
||||
// Usage as Function Scope Static Variables
|
||||
//
|
||||
// Function static objects will be lazily initialized within static storage:
|
||||
//
|
||||
// // Function scope.
|
||||
// const std::string& MyString() {
|
||||
// static const absl::NoDestructor<std::string> x("foo");
|
||||
// return *x;
|
||||
// }
|
||||
//
|
||||
// For function static variables, NoDestructor avoids heap allocation and can be
|
||||
// inlined in static storage, resulting in exactly-once, thread-safe
|
||||
// construction of an object, and very fast access thereafter (the cost is a few
|
||||
// extra cycles).
|
||||
//
|
||||
// Using NoDestructor<T> in this manner is generally better than other patterns
|
||||
// which require pointer chasing:
|
||||
//
|
||||
// // Prefer using absl::NoDestructor<T> instead for the static variable.
|
||||
// const std::string& MyString() {
|
||||
// static const std::string* x = new std::string("foo");
|
||||
// return *x;
|
||||
// }
|
||||
//
|
||||
// Usage as Global Static Variables
|
||||
//
|
||||
// NoDestructor<T> allows declaration of a global object of type T that has a
|
||||
// non-trivial destructor since its destructor is never run. However, such
|
||||
// objects still need to worry about initialization order, so such use is not
|
||||
// recommended, strongly discouraged by the Google C++ Style Guide, and outright
|
||||
// banned in Chromium.
|
||||
// See https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
|
||||
//
|
||||
// // Global or namespace scope.
|
||||
// absl::NoDestructor<MyRegistry> reg{"foo", "bar", 8008};
|
||||
//
|
||||
// Note that if your object already has a trivial destructor, you don't need to
|
||||
// use NoDestructor<T>.
|
||||
//
|
||||
template <typename T>
|
||||
class NoDestructor {
|
||||
public:
|
||||
// Forwards arguments to the T's constructor: calls T(args...).
|
||||
template <typename... Ts,
|
||||
// Disable this overload when it might collide with copy/move.
|
||||
typename std::enable_if<!std::is_same<void(std::decay_t<Ts>&...),
|
||||
void(NoDestructor&)>::value,
|
||||
int>::type = 0>
|
||||
explicit constexpr NoDestructor(Ts&&... args)
|
||||
: impl_(std::forward<Ts>(args)...) {}
|
||||
|
||||
// Forwards copy and move construction for T. Enables usage like this:
|
||||
// static NoDestructor<std::array<string, 3>> x{{{"1", "2", "3"}}};
|
||||
// static NoDestructor<std::vector<int>> x{{1, 2, 3}};
|
||||
explicit constexpr NoDestructor(const T& x) : impl_(x) {}
|
||||
explicit constexpr NoDestructor(T&& x)
|
||||
: impl_(std::move(x)) {}
|
||||
|
||||
// No copying.
|
||||
NoDestructor(const NoDestructor&) = delete;
|
||||
NoDestructor& operator=(const NoDestructor&) = delete;
|
||||
|
||||
// Pretend to be a smart pointer to T with deep constness.
|
||||
// Never returns a null pointer.
|
||||
T& operator*() { return *get(); }
|
||||
T* absl_nonnull operator->() { return get(); }
|
||||
T* absl_nonnull get() { return impl_.get(); }
|
||||
const T& operator*() const { return *get(); }
|
||||
const T* absl_nonnull operator->() const { return get(); }
|
||||
const T* absl_nonnull get() const { return impl_.get(); }
|
||||
|
||||
private:
|
||||
class DirectImpl {
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit constexpr DirectImpl(Args&&... args)
|
||||
: value_(std::forward<Args>(args)...) {}
|
||||
const T* absl_nonnull get() const { return &value_; }
|
||||
T* absl_nonnull get() { return &value_; }
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
class PlacementImpl {
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit PlacementImpl(Args&&... args) {
|
||||
new (&space_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
const T* absl_nonnull get() const {
|
||||
return std::launder(reinterpret_cast<const T*>(&space_));
|
||||
}
|
||||
T* absl_nonnull get() {
|
||||
return std::launder(reinterpret_cast<T*>(&space_));
|
||||
}
|
||||
|
||||
private:
|
||||
alignas(T) unsigned char space_[sizeof(T)];
|
||||
};
|
||||
|
||||
// If the object is trivially destructible we use a member directly to avoid
|
||||
// potential once-init runtime initialization. It somewhat defeats the
|
||||
// purpose of NoDestructor in this case, but this makes the class more
|
||||
// friendly to generic code.
|
||||
std::conditional_t<std::is_trivially_destructible<T>::value, DirectImpl,
|
||||
PlacementImpl>
|
||||
impl_;
|
||||
};
|
||||
|
||||
// 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 <typename T>
|
||||
NoDestructor(T) -> NoDestructor<T>;
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_NO_DESTRUCTOR_H_
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright 2023 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/no_destructor.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Number of static-NoDestructor-in-a-function to exercise.
|
||||
// This must be low enough not to hit template instantiation limits
|
||||
// (happens around 1000).
|
||||
constexpr int kNumObjects = 1; // set to 512 when doing benchmarks
|
||||
// 1 is faster to compile: just one templated
|
||||
// function instantiation
|
||||
|
||||
// Size of individual objects to benchmark static-NoDestructor-in-a-function
|
||||
// usage with.
|
||||
constexpr int kObjSize = sizeof(void*)*1;
|
||||
|
||||
// Simple object of kObjSize bytes (rounded to int).
|
||||
// We benchmark complete reading of its state via Verify().
|
||||
class BM_Blob {
|
||||
public:
|
||||
BM_Blob(int val) { for (auto& d : data_) d = val; }
|
||||
BM_Blob() : BM_Blob(-1) {}
|
||||
void Verify(int val) const { // val must be the c-tor argument
|
||||
for (auto& d : data_) ABSL_INTERNAL_CHECK(d == val, "");
|
||||
}
|
||||
private:
|
||||
int data_[kObjSize / sizeof(int) > 0 ? kObjSize / sizeof(int) : 1];
|
||||
};
|
||||
|
||||
// static-NoDestructor-in-a-function pattern instances.
|
||||
// We'll instantiate kNumObjects of them.
|
||||
template<int i>
|
||||
const BM_Blob& NoDestrBlobFunc() {
|
||||
static absl::NoDestructor<BM_Blob> x(i);
|
||||
return *x;
|
||||
}
|
||||
|
||||
// static-heap-ptr-in-a-function pattern instances
|
||||
// We'll instantiate kNumObjects of them.
|
||||
template<int i>
|
||||
const BM_Blob& OnHeapBlobFunc() {
|
||||
static BM_Blob* x = new BM_Blob(i);
|
||||
return *x;
|
||||
}
|
||||
|
||||
// Type for NoDestrBlobFunc or OnHeapBlobFunc.
|
||||
typedef const BM_Blob& (*FuncType)();
|
||||
|
||||
// ========================================================================= //
|
||||
// Simple benchmarks that read a single BM_Blob over and over, hence
|
||||
// all they touch fits into L1 CPU cache:
|
||||
|
||||
// Direct non-POD global variable (style guide violation) as a baseline.
|
||||
static BM_Blob direct_blob(0);
|
||||
|
||||
void BM_Direct(benchmark::State& state) {
|
||||
for (auto s : state) {
|
||||
direct_blob.Verify(0);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_Direct);
|
||||
|
||||
void BM_NoDestr(benchmark::State& state) {
|
||||
for (auto s : state) {
|
||||
NoDestrBlobFunc<0>().Verify(0);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_NoDestr);
|
||||
|
||||
void BM_OnHeap(benchmark::State& state) {
|
||||
for (auto s : state) {
|
||||
OnHeapBlobFunc<0>().Verify(0);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_OnHeap);
|
||||
|
||||
// ========================================================================= //
|
||||
// Benchmarks that read kNumObjects of BM_Blob over and over, hence with
|
||||
// appropriate values of sizeof(BM_Blob) and kNumObjects their working set
|
||||
// can exceed a given layer of CPU cache.
|
||||
|
||||
// Type of benchmark to select between NoDestrBlobFunc and OnHeapBlobFunc.
|
||||
enum BM_Type { kNoDestr, kOnHeap, kDirect };
|
||||
|
||||
// BlobFunc<n>(t, i) returns the i-th function of type t.
|
||||
// n must be larger than i (we'll use kNumObjects for n).
|
||||
template<int n>
|
||||
FuncType BlobFunc(BM_Type t, int i) {
|
||||
if (i == n) {
|
||||
switch (t) {
|
||||
case kNoDestr: return &NoDestrBlobFunc<n>;
|
||||
case kOnHeap: return &OnHeapBlobFunc<n>;
|
||||
case kDirect: return nullptr;
|
||||
}
|
||||
}
|
||||
return BlobFunc<n-1>(t, i);
|
||||
}
|
||||
|
||||
template<>
|
||||
FuncType BlobFunc<0>(BM_Type t, int i) {
|
||||
ABSL_INTERNAL_CHECK(i == 0, "");
|
||||
switch (t) {
|
||||
case kNoDestr: return &NoDestrBlobFunc<0>;
|
||||
case kOnHeap: return &OnHeapBlobFunc<0>;
|
||||
case kDirect: return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Direct non-POD global variables (style guide violation) as a baseline.
|
||||
static BM_Blob direct_blobs[kNumObjects];
|
||||
|
||||
// Helper that cheaply maps benchmark iteration to randomish index in
|
||||
// [0, kNumObjects).
|
||||
int RandIdx(int i) {
|
||||
// int64 is to avoid overflow and generating negative return values:
|
||||
return (static_cast<int64_t>(i) * 13) % kNumObjects;
|
||||
}
|
||||
|
||||
// Generic benchmark working with kNumObjects for any of the possible BM_Type.
|
||||
template <BM_Type t>
|
||||
void BM_Many(benchmark::State& state) {
|
||||
FuncType funcs[kNumObjects];
|
||||
for (int i = 0; i < kNumObjects; ++i) {
|
||||
funcs[i] = BlobFunc<kNumObjects-1>(t, i);
|
||||
}
|
||||
if (t == kDirect) {
|
||||
for (auto s : state) {
|
||||
int idx = RandIdx(state.iterations());
|
||||
direct_blobs[idx].Verify(-1);
|
||||
}
|
||||
} else {
|
||||
for (auto s : state) {
|
||||
int idx = RandIdx(state.iterations());
|
||||
funcs[idx]().Verify(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BM_DirectMany(benchmark::State& state) { BM_Many<kDirect>(state); }
|
||||
void BM_NoDestrMany(benchmark::State& state) { BM_Many<kNoDestr>(state); }
|
||||
void BM_OnHeapMany(benchmark::State& state) { BM_Many<kOnHeap>(state); }
|
||||
|
||||
BENCHMARK(BM_DirectMany);
|
||||
BENCHMARK(BM_NoDestrMany);
|
||||
BENCHMARK(BM_OnHeapMany);
|
||||
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
// Copyright 2023 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/no_destructor.h"
|
||||
|
||||
#include <array>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct Blob {
|
||||
Blob() : val(42) {}
|
||||
Blob(int x, int y) : val(x + y) {}
|
||||
Blob(std::initializer_list<int> xs) {
|
||||
val = 0;
|
||||
for (auto& x : xs) val += x;
|
||||
}
|
||||
|
||||
Blob(const Blob& /*b*/) = delete;
|
||||
Blob(Blob&& b) noexcept : val(b.val) {
|
||||
b.moved_out = true;
|
||||
} // moving is fine
|
||||
|
||||
// no crash: NoDestructor indeed does not destruct (the moved-out Blob
|
||||
// temporaries do get destroyed though)
|
||||
~Blob() { ABSL_INTERNAL_CHECK(moved_out, "~Blob"); }
|
||||
|
||||
int val;
|
||||
bool moved_out = false;
|
||||
};
|
||||
|
||||
struct TypeWithDeletedDestructor {
|
||||
~TypeWithDeletedDestructor() = delete;
|
||||
};
|
||||
|
||||
TEST(NoDestructorTest, DestructorNeverCalled) {
|
||||
absl::NoDestructor<TypeWithDeletedDestructor> a;
|
||||
(void)a;
|
||||
}
|
||||
|
||||
TEST(NoDestructorTest, Noncopyable) {
|
||||
using T = absl::NoDestructor<int>;
|
||||
|
||||
EXPECT_FALSE((std::is_constructible<T, T>::value));
|
||||
EXPECT_FALSE((std::is_constructible<T, const T>::value));
|
||||
EXPECT_FALSE((std::is_constructible<T, T&>::value));
|
||||
EXPECT_FALSE((std::is_constructible<T, const T&>::value));
|
||||
|
||||
EXPECT_FALSE((std::is_assignable<T&, T>::value));
|
||||
EXPECT_FALSE((std::is_assignable<T&, const T>::value));
|
||||
EXPECT_FALSE((std::is_assignable<T&, T&>::value));
|
||||
EXPECT_FALSE((std::is_assignable<T&, const T&>::value));
|
||||
}
|
||||
|
||||
TEST(NoDestructorTest, Interface) {
|
||||
EXPECT_TRUE(std::is_trivially_destructible<absl::NoDestructor<Blob>>::value);
|
||||
EXPECT_TRUE(
|
||||
std::is_trivially_destructible<absl::NoDestructor<const Blob>>::value);
|
||||
{
|
||||
absl::NoDestructor<Blob> b; // default c-tor
|
||||
// access: *, ->, get()
|
||||
EXPECT_EQ(42, (*b).val);
|
||||
(*b).val = 55;
|
||||
EXPECT_EQ(55, b->val);
|
||||
b->val = 66;
|
||||
EXPECT_EQ(66, b.get()->val);
|
||||
b.get()->val = 42; // NOLINT
|
||||
EXPECT_EQ(42, (*b).val);
|
||||
}
|
||||
{
|
||||
absl::NoDestructor<const Blob> b(70, 7); // regular c-tor, const
|
||||
EXPECT_EQ(77, (*b).val);
|
||||
EXPECT_EQ(77, b->val);
|
||||
EXPECT_EQ(77, b.get()->val);
|
||||
}
|
||||
{
|
||||
const absl::NoDestructor<Blob> b{
|
||||
{20, 28, 40}}; // init-list c-tor, deep const
|
||||
// This only works in clang, not in gcc:
|
||||
// const absl::NoDestructor<Blob> b({20, 28, 40});
|
||||
EXPECT_EQ(88, (*b).val);
|
||||
EXPECT_EQ(88, b->val);
|
||||
EXPECT_EQ(88, b.get()->val);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NoDestructorTest, SfinaeRegressionAbstractArg) {
|
||||
struct Abstract {
|
||||
virtual ~Abstract() = default;
|
||||
virtual int foo() const = 0;
|
||||
};
|
||||
|
||||
struct Concrete : Abstract {
|
||||
int foo() const override { return 17; }
|
||||
};
|
||||
|
||||
struct UsesAbstractInConstructor {
|
||||
explicit UsesAbstractInConstructor(const Abstract& abstract)
|
||||
: i(abstract.foo()) {}
|
||||
int i;
|
||||
};
|
||||
|
||||
Concrete input;
|
||||
absl::NoDestructor<UsesAbstractInConstructor> foo1(input);
|
||||
EXPECT_EQ(foo1->i, 17);
|
||||
absl::NoDestructor<UsesAbstractInConstructor> foo2(
|
||||
static_cast<const Abstract&>(input));
|
||||
EXPECT_EQ(foo2->i, 17);
|
||||
}
|
||||
|
||||
// ========================================================================= //
|
||||
|
||||
std::string* Str0() {
|
||||
static absl::NoDestructor<std::string> x;
|
||||
return x.get();
|
||||
}
|
||||
|
||||
extern const std::string& Str2();
|
||||
|
||||
const char* Str1() {
|
||||
static absl::NoDestructor<std::string> x(Str2() + "_Str1");
|
||||
return x->c_str();
|
||||
}
|
||||
|
||||
const std::string& Str2() {
|
||||
static absl::NoDestructor<std::string> x("Str2");
|
||||
return *x;
|
||||
}
|
||||
|
||||
const std::string& Str2Copy() {
|
||||
// Exercise copy construction
|
||||
static absl::NoDestructor<std::string> x(Str2());
|
||||
return *x;
|
||||
}
|
||||
|
||||
typedef std::array<std::string, 3> MyArray;
|
||||
const MyArray& Array() {
|
||||
static absl::NoDestructor<MyArray> x{{{"foo", "bar", "baz"}}};
|
||||
// This only works in clang, not in gcc:
|
||||
// static absl::NoDestructor<MyArray> x({{"foo", "bar", "baz"}});
|
||||
return *x;
|
||||
}
|
||||
|
||||
typedef std::vector<int> MyVector;
|
||||
const MyVector& Vector() {
|
||||
static absl::NoDestructor<MyVector> x{{1, 2, 3}};
|
||||
return *x;
|
||||
}
|
||||
|
||||
const int& Int() {
|
||||
static absl::NoDestructor<int> x;
|
||||
return *x;
|
||||
}
|
||||
|
||||
TEST(NoDestructorTest, StaticPattern) {
|
||||
EXPECT_TRUE(
|
||||
std::is_trivially_destructible<absl::NoDestructor<std::string>>::value);
|
||||
EXPECT_TRUE(
|
||||
std::is_trivially_destructible<absl::NoDestructor<MyArray>>::value);
|
||||
EXPECT_TRUE(
|
||||
std::is_trivially_destructible<absl::NoDestructor<MyVector>>::value);
|
||||
EXPECT_TRUE(std::is_trivially_destructible<absl::NoDestructor<int>>::value);
|
||||
|
||||
EXPECT_EQ(*Str0(), "");
|
||||
Str0()->append("foo");
|
||||
EXPECT_EQ(*Str0(), "foo");
|
||||
|
||||
EXPECT_EQ(std::string(Str1()), "Str2_Str1");
|
||||
|
||||
EXPECT_EQ(Str2(), "Str2");
|
||||
EXPECT_EQ(Str2Copy(), "Str2");
|
||||
|
||||
EXPECT_THAT(Array(), testing::ElementsAre("foo", "bar", "baz"));
|
||||
|
||||
EXPECT_THAT(Vector(), testing::ElementsAre(1, 2, 3));
|
||||
|
||||
EXPECT_EQ(0, Int()); // should get zero-initialized
|
||||
}
|
||||
|
||||
TEST(NoDestructorTest, ClassTemplateArgumentDeduction) {
|
||||
absl::NoDestructor i(1);
|
||||
static_assert(std::is_same<decltype(i), absl::NoDestructor<int>>::value,
|
||||
"Expected deduced type to be int.");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -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<T>`), 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<T>`), 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<T>`), 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<T>`; 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> 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<T*>`, 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<Employee *> 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<Account *> 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<Employee *> 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");
|
||||
|
|
@ -128,49 +161,86 @@
|
|||
//
|
||||
// By default, nullability annotations are applicable to raw and smart
|
||||
// pointers. User-defined types can indicate compatibility with nullability
|
||||
// annotations by providing an `absl_nullability_compatible` nested type. The
|
||||
// actual definition of this inner type is not relevant as it is used merely as
|
||||
// a marker. It is common to use a using declaration of
|
||||
// `absl_nullability_compatible` set to void.
|
||||
// annotations by adding the ABSL_NULLABILITY_COMPATIBLE attribute.
|
||||
//
|
||||
// // Example:
|
||||
// struct MyPtr {
|
||||
// using absl_nullability_compatible = void;
|
||||
// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// Note: Compilers that don't support the `nullability_on_classes` feature will
|
||||
// allow nullability annotations to be applied to any type, not just ones
|
||||
// marked with `ABSL_NULLABILITY_COMPATIBLE`.
|
||||
//
|
||||
// DISCLAIMER:
|
||||
// ===========================================================================
|
||||
// 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<T*>` is *not guaranteed* to be non-null, and the compiler won't
|
||||
// alert or prevent assignment of a `Nullable<T*>` to a `Nonnull<T*>`.
|
||||
// `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/internal/nullability_impl.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/nullability_deprecated.h"
|
||||
|
||||
namespace absl {
|
||||
// ABSL_POINTERS_DEFAULT_NONNULL
|
||||
//
|
||||
// This macro specifies that all unannotated pointer types within the given
|
||||
// file are designated as nonnull (instead of the default "unknown"). This macro
|
||||
// exists as a standalone statement and applies default nonnull behavior to all
|
||||
// subsequent pointers; as a result, place this macro as the first non-comment,
|
||||
// non-`#include` line in a file.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// #include "absl/base/nullability.h"
|
||||
//
|
||||
// ABSL_POINTERS_DEFAULT_NONNULL
|
||||
//
|
||||
// void FillMessage(Message *m); // implicitly non-null
|
||||
// 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
|
||||
// that include it.
|
||||
//
|
||||
// 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
|
||||
// unknown, and otherwise require explicit annotations to change this behavior:
|
||||
//
|
||||
// #include "absl/base/nullability.h"
|
||||
//
|
||||
// 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
|
||||
|
||||
// absl::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 be
|
||||
// of this pointer across an API boundary to ensure that the pointer is never
|
||||
// set to null. Consumers of this pointer across an API boundary may safely
|
||||
// dereference the pointer.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // `employee` is designated as not null.
|
||||
// void PaySalary(absl::Nonnull<Employee *> employee) {
|
||||
// void PaySalary(Employee* absl_nonnull employee) {
|
||||
// pay(*employee); // OK to dereference
|
||||
// }
|
||||
template <typename T>
|
||||
using Nonnull = nullability_internal::NonnullImpl<T>;
|
||||
#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
|
||||
|
|
@ -179,15 +249,14 @@ using Nonnull = nullability_internal::NonnullImpl<T>;
|
|||
// Example:
|
||||
//
|
||||
// // `employee` may be null.
|
||||
// void PaySalary(absl::Nullable<Employee *> employee) {
|
||||
// void PaySalary(Employee* absl_nullable employee) {
|
||||
// if (employee != nullptr) {
|
||||
// Pay(*employee); // OK to dereference
|
||||
// }
|
||||
// }
|
||||
template <typename T>
|
||||
using Nullable = nullability_internal::NullableImpl<T>;
|
||||
#define absl_nullable _Nullable
|
||||
|
||||
// absl::NullabilityUnknown (default)
|
||||
// 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
|
||||
|
|
@ -195,17 +264,18 @@ using Nullable = nullability_internal::NullableImpl<T>;
|
|||
// 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<T>` or
|
||||
// `Nullable<T>`.
|
||||
// migrated into one of the above two nullability states: `absl_nonnull` or
|
||||
// `absl_nullable`.
|
||||
//
|
||||
// NOTE: Because this annotation is the global default state, pointers without
|
||||
// any annotation are assumed to have "unknown" semantics. This assumption is
|
||||
// designed to minimize churn and reduce clutter within the codebase.
|
||||
// NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`,
|
||||
// because this annotation is the global default state, unannotated pointers are
|
||||
// are assumed to have "unknown" semantics. This assumption is designed to
|
||||
// minimize churn and reduce clutter within the codebase.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // `employee`s nullability state is unknown.
|
||||
// void PaySalary(absl::NullabilityUnknown<Employee *> employee) {
|
||||
// void PaySalary(Employee* absl_nullability_unknown employee) {
|
||||
// Pay(*employee); // Potentially dangerous. API provider should investigate.
|
||||
// }
|
||||
//
|
||||
|
|
@ -216,9 +286,33 @@ using Nullable = nullability_internal::NullableImpl<T>;
|
|||
// void PaySalary(Employee* employee) {
|
||||
// Pay(*employee); // Potentially dangerous. API provider should investigate.
|
||||
// }
|
||||
template <typename T>
|
||||
using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>;
|
||||
#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
|
||||
|
||||
} // namespace absl
|
||||
// ABSL_NULLABILITY_COMPATIBLE
|
||||
//
|
||||
// Indicates that a class is compatible with nullability annotations.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// Note: Compilers that don't support the `nullability_on_classes` feature will
|
||||
// allow nullability annotations to be applied to any type, not just ones marked
|
||||
// with `ABSL_NULLABILITY_COMPATIBLE`.
|
||||
#if ABSL_HAVE_FEATURE(nullability_on_classes)
|
||||
#define ABSL_NULLABILITY_COMPATIBLE _Nullable
|
||||
#else
|
||||
#define ABSL_NULLABILITY_COMPATIBLE
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_NULLABILITY_H_
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2022 The Abseil Authors.
|
||||
// Copyright 2024 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -12,32 +12,33 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "absl/base/internal/prefetch.h"
|
||||
#include <cassert>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/nullability.h"
|
||||
|
||||
ABSL_POINTERS_DEFAULT_NONNULL
|
||||
|
||||
namespace {
|
||||
|
||||
int number = 42;
|
||||
void FuncWithDefaultNonnullArg(int* /*arg*/) {}
|
||||
template <typename T>
|
||||
void FuncWithDeducedDefaultNonnullArg(T* /*arg*/) {}
|
||||
|
||||
TEST(Prefetch, TemporalLocalityNone) {
|
||||
absl::base_internal::PrefetchNta(&number);
|
||||
EXPECT_EQ(number, 42);
|
||||
TEST(DefaultNonnullTest, NonnullArgument) {
|
||||
int var = 0;
|
||||
FuncWithDefaultNonnullArg(&var);
|
||||
FuncWithDeducedDefaultNonnullArg<int>(&var);
|
||||
}
|
||||
|
||||
TEST(Prefetch, TemporalLocalityLow) {
|
||||
absl::base_internal::PrefetchT2(&number);
|
||||
EXPECT_EQ(number, 42);
|
||||
int* FuncWithDefaultNonnullReturn() {
|
||||
static int var = 0;
|
||||
return &var;
|
||||
}
|
||||
|
||||
TEST(Prefetch, TemporalLocalityMedium) {
|
||||
absl::base_internal::PrefetchT1(&number);
|
||||
EXPECT_EQ(number, 42);
|
||||
}
|
||||
|
||||
TEST(Prefetch, TemporalLocalityHigh) {
|
||||
absl::base_internal::PrefetchT0(&number);
|
||||
EXPECT_EQ(number, 42);
|
||||
TEST(DefaultNonnullTest, NonnullReturn) {
|
||||
auto var = FuncWithDefaultNonnullReturn();
|
||||
(void)var;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -16,15 +16,89 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/attributes.h"
|
||||
|
||||
namespace {
|
||||
namespace macro_annotations {
|
||||
void funcWithNonnullArg(int* absl_nonnull /*arg*/) {}
|
||||
template <typename T>
|
||||
void funcWithDeducedNonnullArg(T* absl_nonnull /*arg*/) {}
|
||||
|
||||
TEST(NonnullTest, NonnullArgument) {
|
||||
int var = 0;
|
||||
funcWithNonnullArg(&var);
|
||||
funcWithDeducedNonnullArg(&var);
|
||||
}
|
||||
|
||||
int* absl_nonnull funcWithNonnullReturn() {
|
||||
static int var = 0;
|
||||
return &var;
|
||||
}
|
||||
|
||||
TEST(NonnullTest, NonnullReturn) {
|
||||
auto var = funcWithNonnullReturn();
|
||||
(void)var;
|
||||
}
|
||||
|
||||
TEST(PassThroughTest, PassesThroughRawPointerToInt) {
|
||||
EXPECT_TRUE((std::is_same<int* absl_nonnull, int*>::value));
|
||||
EXPECT_TRUE((std::is_same<int* absl_nullable, int*>::value));
|
||||
EXPECT_TRUE((std::is_same<int* absl_nullability_unknown, int*>::value));
|
||||
}
|
||||
|
||||
TEST(PassThroughTest, PassesThroughRawPointerToVoid) {
|
||||
EXPECT_TRUE((std::is_same<void* absl_nonnull, void*>::value));
|
||||
EXPECT_TRUE((std::is_same<void* absl_nullable, void*>::value));
|
||||
EXPECT_TRUE((std::is_same<void* absl_nullability_unknown, void*>::value));
|
||||
}
|
||||
|
||||
TEST(PassThroughTest, PassesThroughUniquePointerToInt) {
|
||||
using T = std::unique_ptr<int>;
|
||||
EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
|
||||
}
|
||||
|
||||
TEST(PassThroughTest, PassesThroughSharedPointerToInt) {
|
||||
using T = std::shared_ptr<int>;
|
||||
EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
|
||||
}
|
||||
|
||||
TEST(PassThroughTest, PassesThroughSharedPointerToVoid) {
|
||||
using T = std::shared_ptr<void>;
|
||||
EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
|
||||
}
|
||||
|
||||
TEST(PassThroughTest, PassesThroughPointerToMemberObject) {
|
||||
using T = decltype(&std::pair<int, int>::first);
|
||||
EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
|
||||
}
|
||||
|
||||
TEST(PassThroughTest, PassesThroughPointerToMemberFunction) {
|
||||
using T = decltype(&std::unique_ptr<int>::reset);
|
||||
EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
|
||||
EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
|
||||
}
|
||||
} // namespace macro_annotations
|
||||
|
||||
// Allow testing of the deprecated type alias annotations.
|
||||
ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
|
||||
|
||||
using ::absl::Nonnull;
|
||||
using ::absl::NullabilityUnknown;
|
||||
using ::absl::Nullable;
|
||||
namespace type_alias_annotations {
|
||||
|
||||
void funcWithNonnullArg(Nonnull<int*> /*arg*/) {}
|
||||
template <typename T>
|
||||
|
|
@ -93,6 +167,7 @@ TEST(PassThroughTest, PassesThroughPointerToMemberFunction) {
|
|||
EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
|
||||
}
|
||||
|
||||
} // namespace type_alias_annotations
|
||||
} // namespace
|
||||
|
||||
// Nullable ADL lookup test
|
||||
|
|
@ -126,4 +201,6 @@ TEST(NullableAdlTest, NullableAddsNothingToArgumentDependentLookup) {
|
|||
EXPECT_TRUE(DidAdlWin((util::MakeAdlWin*)nullptr));
|
||||
EXPECT_TRUE(DidAdlWin((Nullable<util::MakeAdlWin*>)nullptr));
|
||||
}
|
||||
|
||||
ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -18,13 +18,27 @@
|
|||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file defines portable macros for performance optimization.
|
||||
//
|
||||
// This header is included in both C++ code and legacy C code and thus must
|
||||
// remain compatible with both C and C++. C compatibility will be removed if
|
||||
// the legacy code is removed or converted to C++. Do not include this header in
|
||||
// new code that requires C compatibility or assume C compatibility will remain
|
||||
// indefinitely.
|
||||
|
||||
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
|
||||
|
||||
#ifndef ABSL_BASE_OPTIMIZATION_H_
|
||||
#define ABSL_BASE_OPTIMIZATION_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
// Included for std::unreachable()
|
||||
#include <utility>
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/options.h"
|
||||
|
||||
// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION
|
||||
//
|
||||
|
|
@ -259,20 +273,14 @@
|
|||
#elif defined(_MSC_VER)
|
||||
#define ABSL_ASSUME(cond) __assume(cond)
|
||||
#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
|
||||
#define ABSL_ASSUME(cond) \
|
||||
do { \
|
||||
if (!(cond)) std::unreachable(); \
|
||||
} while (false)
|
||||
#define ABSL_ASSUME(cond) ((cond) ? void() : std::unreachable())
|
||||
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
|
||||
#define ABSL_ASSUME(cond) \
|
||||
do { \
|
||||
if (!(cond)) __builtin_unreachable(); \
|
||||
} while (false)
|
||||
#define ABSL_ASSUME(cond) ((cond) ? void() : __builtin_unreachable())
|
||||
#elif ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
|
||||
// Unimplemented. Uses the same definition as ABSL_ASSERT in the NDEBUG case.
|
||||
#define ABSL_ASSUME(expr) (decltype((expr) ? void() : void())())
|
||||
#else
|
||||
#define ABSL_ASSUME(cond) \
|
||||
do { \
|
||||
static_cast<void>(false && (cond)); \
|
||||
} while (false)
|
||||
#define ABSL_ASSUME(expr) (false ? ((expr) ? void() : void()) : void())
|
||||
#endif
|
||||
|
||||
// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
|
||||
|
|
|
|||
|
|
@ -88,9 +88,9 @@ TEST(PredictTest, Optional) {
|
|||
EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
|
||||
}
|
||||
|
||||
class ImplictlyConvertibleToBool {
|
||||
class ImplicitlyConvertibleToBool {
|
||||
public:
|
||||
explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
|
||||
explicit ImplicitlyConvertibleToBool(bool value) : value_(value) {}
|
||||
operator bool() const { // NOLINT(google-explicit-constructor)
|
||||
return value_;
|
||||
}
|
||||
|
|
@ -100,17 +100,17 @@ class ImplictlyConvertibleToBool {
|
|||
};
|
||||
|
||||
TEST(PredictTest, ImplicitBoolConversion) {
|
||||
const ImplictlyConvertibleToBool is_true(true);
|
||||
const ImplictlyConvertibleToBool is_false(false);
|
||||
const ImplicitlyConvertibleToBool is_true(true);
|
||||
const ImplicitlyConvertibleToBool is_false(false);
|
||||
if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
|
||||
if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
|
||||
}
|
||||
|
||||
class ExplictlyConvertibleToBool {
|
||||
class ExplicitlyConvertibleToBool {
|
||||
public:
|
||||
explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
|
||||
explicit ExplicitlyConvertibleToBool(bool value) : value_(value) {}
|
||||
explicit operator bool() const { return value_; }
|
||||
|
||||
private:
|
||||
|
|
@ -118,12 +118,24 @@ class ExplictlyConvertibleToBool {
|
|||
};
|
||||
|
||||
TEST(PredictTest, ExplicitBoolConversion) {
|
||||
const ExplictlyConvertibleToBool is_true(true);
|
||||
const ExplictlyConvertibleToBool is_false(false);
|
||||
const ExplicitlyConvertibleToBool is_true(true);
|
||||
const ExplicitlyConvertibleToBool is_false(false);
|
||||
if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
|
||||
if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
|
||||
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
|
||||
}
|
||||
|
||||
// This verifies that ABSL_ASSUME compiles in a variety of contexts.
|
||||
// It does not test optimization.
|
||||
TEST(AbslAssume, Compiles) {
|
||||
int x = 0;
|
||||
ABSL_ASSUME(x >= 0);
|
||||
EXPECT_EQ(x, 0);
|
||||
|
||||
// https://github.com/abseil/abseil-cpp/issues/1814
|
||||
ABSL_ASSUME(x >= 0), (x >= 0) ? ++x : --x;
|
||||
EXPECT_EQ(x, 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -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,32 @@
|
|||
|
||||
#define ABSL_OPTION_USE_STD_STRING_VIEW 2
|
||||
|
||||
// ABSL_OPTION_USE_STD_VARIANT
|
||||
// ABSL_OPTION_USE_STD_ORDERING
|
||||
//
|
||||
// This option controls whether absl::variant is implemented as an alias to
|
||||
// std::variant, or as an independent implementation.
|
||||
// This option controls whether absl::{partial,weak,strong}_ordering are
|
||||
// implemented as aliases to the std:: ordering types, 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 1 means to use aliases. This requires that all code using Abseil
|
||||
// is built in C++20 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
|
||||
// and use an alias only if working std:: ordering types are 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, they will name different types,
|
||||
// with different mangled names 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
|
||||
// the ordering types are aliases of std:: ordering types, use the feature macro
|
||||
// ABSL_USES_STD_ORDERING.
|
||||
|
||||
#define ABSL_OPTION_USE_STD_ORDERING 2
|
||||
|
||||
// ABSL_OPTION_USE_INLINE_NAMESPACE
|
||||
// ABSL_OPTION_INLINE_NAMESPACE_NAME
|
||||
|
|
@ -200,7 +149,7 @@
|
|||
// allowed.
|
||||
|
||||
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
|
||||
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20230802
|
||||
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250512
|
||||
|
||||
// ABSL_OPTION_HARDENED
|
||||
//
|
||||
|
|
@ -209,7 +158,10 @@
|
|||
//
|
||||
// A value of 0 means that "hardened" mode is not enabled.
|
||||
//
|
||||
// A value of 1 means that "hardened" mode is enabled.
|
||||
// A value of 1 means that "hardened" mode is enabled with all checks.
|
||||
//
|
||||
// A value of 2 means that "hardened" mode is partially enabled, with
|
||||
// only a subset of checks chosen to minimize performance impact.
|
||||
//
|
||||
// Hardened builds have additional security checks enabled when `NDEBUG` is
|
||||
// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
// reported with `#error`. This enforcement is best effort, so successfully
|
||||
// compiling this header does not guarantee a supported configuration.
|
||||
|
||||
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
|
||||
|
||||
#ifndef ABSL_BASE_POLICY_CHECKS_H_
|
||||
#define ABSL_BASE_POLICY_CHECKS_H_
|
||||
|
||||
|
|
@ -69,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
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -24,17 +24,19 @@
|
|||
#ifndef ABSL_BASE_PREFETCH_H_
|
||||
#define ABSL_BASE_PREFETCH_H_
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
#if defined(ABSL_INTERNAL_HAVE_SSE)
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1900 && \
|
||||
(defined(_M_X64) || defined(_M_IX86))
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#if defined(ABSL_INTERNAL_HAVE_SSE)
|
||||
#pragma intrinsic(_mm_prefetch)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
@ -127,7 +129,7 @@ void PrefetchToLocalCacheNta(const void* addr);
|
|||
//
|
||||
// void* Arena::Allocate(size_t size) {
|
||||
// void* ptr = AllocateBlock(size);
|
||||
// absl::PrefetchToLocalCacheForWrite(p);
|
||||
// absl::PrefetchToLocalCacheForWrite(ptr);
|
||||
// return ptr;
|
||||
// }
|
||||
//
|
||||
|
|
@ -140,21 +142,24 @@ void PrefetchToLocalCacheForWrite(const void* addr);
|
|||
// See __builtin_prefetch:
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
|
||||
//
|
||||
inline void PrefetchToLocalCache(const void* addr) {
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
|
||||
const void* addr) {
|
||||
__builtin_prefetch(addr, 0, 3);
|
||||
}
|
||||
|
||||
inline void PrefetchToLocalCacheNta(const void* addr) {
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
|
||||
const void* addr) {
|
||||
__builtin_prefetch(addr, 0, 0);
|
||||
}
|
||||
|
||||
inline void PrefetchToLocalCacheForWrite(const void* addr) {
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
|
||||
const void* addr) {
|
||||
// [x86] gcc/clang don't generate PREFETCHW for __builtin_prefetch(.., 1)
|
||||
// unless -march=broadwell or newer; this is not generally the default, so we
|
||||
// manually emit prefetchw. PREFETCHW is recognized as a no-op on older Intel
|
||||
// processors and has been present on AMD processors since the K6-2.
|
||||
#if defined(__x86_64__)
|
||||
asm("prefetchw (%0)" : : "r"(addr));
|
||||
#if defined(__x86_64__) && !defined(__PRFCHW__)
|
||||
asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr)));
|
||||
#else
|
||||
__builtin_prefetch(addr, 1, 3);
|
||||
#endif
|
||||
|
|
@ -164,15 +169,18 @@ inline void PrefetchToLocalCacheForWrite(const void* addr) {
|
|||
|
||||
#define ABSL_HAVE_PREFETCH 1
|
||||
|
||||
inline void PrefetchToLocalCache(const void* addr) {
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
|
||||
const void* addr) {
|
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
|
||||
}
|
||||
|
||||
inline void PrefetchToLocalCacheNta(const void* addr) {
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
|
||||
const void* addr) {
|
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);
|
||||
}
|
||||
|
||||
inline void PrefetchToLocalCacheForWrite(const void* addr) {
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
|
||||
const void* addr) {
|
||||
#if defined(_MM_HINT_ET0)
|
||||
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_ET0);
|
||||
#elif !defined(_MSC_VER) && defined(__x86_64__)
|
||||
|
|
@ -180,15 +188,18 @@ inline void PrefetchToLocalCacheForWrite(const void* addr) {
|
|||
// up, PREFETCHW is recognized as a no-op on older Intel processors
|
||||
// and has been present on AMD processors since the K6-2. We have this
|
||||
// disabled for MSVC compilers as this miscompiles on older MSVC compilers.
|
||||
asm("prefetchw (%0)" : : "r"(addr));
|
||||
asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr)));
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void PrefetchToLocalCache(const void* addr) {}
|
||||
inline void PrefetchToLocalCacheNta(const void* addr) {}
|
||||
inline void PrefetchToLocalCacheForWrite(const void* addr) {}
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
|
||||
const void* addr) {}
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
|
||||
const void* addr) {}
|
||||
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
|
||||
const void* addr) {}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -35,16 +35,35 @@ TEST(RawLoggingCompilationTest, Log) {
|
|||
ABSL_RAW_LOG(ERROR, "RAW ERROR: %d", 1);
|
||||
}
|
||||
|
||||
TEST(RawLoggingCompilationTest, LogWithNulls) {
|
||||
ABSL_RAW_LOG(INFO, "RAW INFO: %s%c%s", "Hello", 0, "World");
|
||||
}
|
||||
|
||||
TEST(RawLoggingCompilationTest, PassingCheck) {
|
||||
ABSL_RAW_CHECK(true, "RAW CHECK");
|
||||
}
|
||||
|
||||
TEST(RawLoggingCompilationTest, DebugLog) {
|
||||
ABSL_RAW_DLOG(INFO, "RAW DLOG: %d", 1);
|
||||
}
|
||||
|
||||
TEST(RawLoggingCompilationTest, PassingDebugCheck) {
|
||||
ABSL_RAW_DCHECK(true, "failure message");
|
||||
}
|
||||
|
||||
// Not all platforms support output from raw log, so we don't verify any
|
||||
// particular output for RAW check failures (expecting the empty string
|
||||
// accomplishes this). This test is primarily a compilation test, but we
|
||||
// are verifying process death when EXPECT_DEATH works for a platform.
|
||||
const char kExpectedDeathOutput[] = "";
|
||||
|
||||
#if !defined(NDEBUG) // if debug build
|
||||
TEST(RawLoggingDeathTest, FailingDebugCheck) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_DCHECK(1 == 0, "explanation"),
|
||||
kExpectedDeathOutput);
|
||||
}
|
||||
#endif // if debug build
|
||||
|
||||
TEST(RawLoggingDeathTest, FailingCheck) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_CHECK(1 == 0, "explanation"),
|
||||
kExpectedDeathOutput);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue