SERVER-106442 Upgrade abseil-cpp...with linker fixes (#38534)

GitOrigin-RevId: 2a89994de90be42cc5e4f5cac16c145f0ad10dbd
This commit is contained in:
Ronald Steinke 2025-07-16 08:49:29 -06:00 committed by MongoDB Bot
parent 1b4cb574d1
commit 8a710772c6
667 changed files with 42028 additions and 36594 deletions

View File

@ -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

View File

@ -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):

View File

@ -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",

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",
],
)

View File

@ -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",
],
)

View File

@ -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()

View File

@ -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})

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)
project(googletest-external NONE)

View File

@ -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

View File

@ -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)

View File

@ -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}" ..

View File

@ -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

View File

@ -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")

View File

@ -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>

View File

@ -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.

View File

@ -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"],
)

View File

@ -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__"],
)

View File

@ -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()

View File

@ -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):

View File

@ -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",
],
)

View File

@ -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
)

View File

@ -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

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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",
],
)

View File

@ -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
)

View File

@ -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_

View File

@ -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

View File

@ -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; }

View File

@ -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)) {

View File

@ -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;
}

View File

@ -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

View File

@ -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
// -------------------------------------------------------------------------

View File

@ -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{});

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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};

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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_

View File

@ -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

View 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_

View File

@ -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),

View 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_

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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`.

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -17,6 +17,7 @@
#include <ostream>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN

View File

@ -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));

View File

@ -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;

View File

@ -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_

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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

View File

@ -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