diff --git a/.gitignore b/.gitignore index d54fa5a91fe..3a729f416b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +# Bzlmod lockfile +MODULE.bazel.lock # Ignore all bazel-* symlinks. /bazel-* # Ignore Bazel verbose explanations diff --git a/BUILD.bazel b/BUILD.bazel index 79fb0ecd73e..03122a958e5 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -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", + ], +) diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index 32b51411abc..f01021bb02e 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake @@ -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,16 +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_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" @@ -43,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" @@ -56,6 +58,8 @@ 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" "base/policy_checks.h" @@ -65,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" @@ -75,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" @@ -89,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" @@ -107,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" @@ -121,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" @@ -131,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" @@ -139,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" @@ -147,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" @@ -161,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" @@ -177,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" @@ -217,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" @@ -248,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" @@ -259,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" @@ -285,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" @@ -305,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" @@ -323,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" @@ -412,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" @@ -462,8 +503,14 @@ set(ABSL_INTERNAL_DLL_TARGETS "container_common" "container_memory" "cord" + "cord_internal" + "cordz_functions" + "cordz_handle" + "cordz_info" + "cordz_sample_token" "core_headers" "counting_allocator" + "crc_cord_state" "crc_cpu_detect" "crc_internal" "crc32c" @@ -497,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" @@ -518,6 +566,7 @@ set(ABSL_INTERNAL_DLL_TARGETS "log_internal_structured" "log_severity" "log_structured" + "low_level_hash" "malloc_internal" "memory" "meta" @@ -569,10 +618,13 @@ set(ABSL_INTERNAL_DLL_TARGETS "stack_consumption" "stacktrace" "status" + "statusor" "str_format" "str_format_internal" + "strerror" "strings" "strings_internal" + "string_view" "symbolize" "synchronization" "thread_pool" @@ -583,16 +635,45 @@ 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" "log/scoped_mock_log.h" + "random/internal/chi_square.cc" + "random/internal/chi_square.h" + "random/internal/distribution_test_util.cc" + "random/internal/distribution_test_util.h" "random/internal/mock_helpers.h" "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" ) @@ -602,8 +683,10 @@ set(ABSL_INTERNAL_TEST_DLL_TARGETS "cordz_test_helpers" "hash_testing" "random_mocking_bit_gen" + "random_internal_distribution_test_util" "random_internal_mock_overload_set" "scoped_mock_log" + "status_matchers" ) include(CheckCXXSourceCompiles) @@ -611,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) @@ -637,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) @@ -659,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) @@ -716,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 $ once our + # minimum CMake version >= 3.24 + $<$:-Wl,-framework,CoreFoundation> + ) set(_dll_compile_definitions "") set(_dll_includes "") set(_dll_consume "ABSL_CONSUME_DLL") @@ -733,8 +824,12 @@ function(absl_make_dll) PRIVATE ${_dll_libs} ${ABSL_DEFAULT_LINKOPTS} + $<$:-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 @@ -772,7 +867,7 @@ Name: ${_dll}\n\ Description: Abseil DLL library\n\ URL: https://abseil.io/\n\ Version: ${absl_VERSION}\n\ -Libs: -L\${libdir} ${PC_LINKOPTS} $<$>:-l${_dll}>\n\ +Libs: -L\${libdir} $<$>:-l${_dll}> ${PC_LINKOPTS}\n\ Cflags: -I\${includedir}${PC_CFLAGS}\n") INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/${_dll}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") @@ -790,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() @@ -801,4 +896,6 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n") LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) + + add_library(absl::${_dll} ALIAS ${_dll}) endfunction() diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index f1b3158ca58..624a3c7e959 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -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])") @@ -211,7 +219,7 @@ Description: Abseil ${_NAME} library\n\ URL: https://abseil.io/\n\ Version: ${PC_VERSION}\n\ Requires:${PC_DEPS}\n\ -Libs: -L\${libdir} ${PC_LINKOPTS} $<$>:${LNK_LIB}>\n\ +Libs: -L\${libdir} $<$>:${LNK_LIB}> ${PC_LINKOPTS}\n\ Cflags: -I\${includedir}${PC_CFLAGS}\n") INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") @@ -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 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}) @@ -413,6 +428,10 @@ function(absl_cc_test) DEPS ${ABSL_CC_TEST_DEPS} OUTPUT ABSL_CC_TEST_DEPS ) + absl_internal_dll_targets( + DEPS ${ABSL_CC_TEST_LINKOPTS} + OUTPUT ABSL_CC_TEST_LINKOPTS + ) else() target_compile_definitions(${_NAME} PUBLIC @@ -431,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}) diff --git a/CMake/Googletest/CMakeLists.txt.in b/CMake/Googletest/CMakeLists.txt.in index 75691b1117b..3db48341a25 100644 --- a/CMake/Googletest/CMakeLists.txt.in +++ b/CMake/Googletest/CMakeLists.txt.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(googletest-external NONE) diff --git a/CMake/README.md b/CMake/README.md index c7ddee64406..ecaeaf067e4 100644 --- a/CMake/README.md +++ b/CMake/README.md @@ -39,12 +39,12 @@ section of your executable or of your library.
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 diff --git a/CMake/install_test_project/CMakeLists.txt b/CMake/install_test_project/CMakeLists.txt index 30c23b2c6b8..3229887c8d6 100644 --- a/CMake/install_test_project/CMakeLists.txt +++ b/CMake/install_test_project/CMakeLists.txt @@ -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) diff --git a/CMake/install_test_project/test.sh b/CMake/install_test_project/test.sh index cc028bac861..962bc8d2d83 100755 --- a/CMake/install_test_project/test.sh +++ b/CMake/install_test_project/test.sh @@ -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}" .. diff --git a/CMakeLists.txt b/CMakeLists.txt index ae799811a2f..a31c6a90289 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,40 +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) +set(ABSL_SOVERSION 0) include(CTest) # Output directory is correct by default for most build setups. However, when @@ -65,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" @@ -81,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$<$:Debug>") +else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") +endif() + include(CMakePackageConfigHelpers) include(GNUInstallDirs) include(AbseilDll) @@ -139,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) @@ -217,30 +211,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" + + # 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}") - else() - string(REGEX REPLACE - "#define ABSL_OPTION_USE_STD_([^ ]*) 2" - "#define ABSL_OPTION_USE_STD_\\1 0" + 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 diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 00000000000..29e624af495 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,43 @@ +# 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 = "head", + compatibility_level = 1, +) + +cc_configure = use_extension("@rules_cc//cc:extensions.bzl", + "cc_configure_extension", + dev_dependency = True) +use_repo(cc_configure, "local_config_cc") + +bazel_dep(name = "rules_cc", version = "0.1.1") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.11") + +bazel_dep( + name = "google_benchmark", + version = "1.9.2", + dev_dependency = True, +) + +# Note: Googletest is NOT a dev_dependency. Some Abseil test utilities +# intended to be used by Abseil users depend on GoogleTest. +bazel_dep( + name = "googletest", + version = "1.17.0", +) diff --git a/PrivacyInfo.xcprivacy b/PrivacyInfo.xcprivacy new file mode 100644 index 00000000000..3ff4a9d98b1 --- /dev/null +++ b/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTracking + + NSPrivacyCollectedDataTypes + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + + diff --git a/README.md b/README.md index f834fcdec06..c2c851ec35b 100644 --- a/README.md +++ b/README.md @@ -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:
The `memory` library contains memory management facilities that augment C++'s `` library. * [`meta`](absl/meta/) -
The `meta` library contains compatible versions of type checks - available within C++14 and C++17 versions of the C++ `` library. +
The `meta` library contains type checks + similar to those available in the C++ `` library. * [`numeric`](absl/numeric/)
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:
The `profiling` library contains utility code for profiling C++ entities. It is currently a private dependency of other Abseil libraries. * [`random`](absl/random/) -
The `random` library contains functions for generating psuedorandom +
The `random` library contains functions for generating pseudorandom values. * [`status`](absl/status/)
The `status` library contains abstractions for error handling, specifically `absl::Status` and `absl::StatusOr`. * [`strings`](absl/strings/)
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/)
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/) -
The `types` library contains non-container utility types, like a - C++14-compatible version of the C++17 `std::optional` type. +
The `types` library contains non-container utility types. * [`utility`](absl/utility/)
The `utility` library contains utility and helper code. diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index ce8e8596663..00000000000 --- a/WORKSPACE +++ /dev/null @@ -1,62 +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-02-28T13:15:29Z - sha256 = "82ad62a4e26c199de52a707778334e80f6b195dd298d48d520d8507d2bcb88c4", - strip_prefix = "googletest-2d4f208765af7fa376b878860a7677ecc0bc390a", - # Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh. - urls = ["https://github.com/google/googletest/archive/2d4f208765af7fa376b878860a7677ecc0bc390a.zip"], -) - -# RE2 (the regular expression library used by GoogleTest) -# Note this must use a commit from the `abseil` branch of the RE2 project. -# https://github.com/google/re2/tree/abseil -http_archive( - name = "com_googlesource_code_re2", - sha256 = "0a890c2aa0bb05b2ce906a15efb520d0f5ad4c7d37b8db959c43772802991887", - strip_prefix = "re2-a427f10b9fb4622dd6d8643032600aa1b50fbd12", - urls = ["https://github.com/google/re2/archive/a427f10b9fb4622dd6d8643032600aa1b50fbd12.zip"], # 2022-06-09 -) - -# Google benchmark. -http_archive( - name = "com_github_google_benchmark", # 2023-01-10T16:48:17Z - sha256 = "ede6830512f21490eeea1f238f083702eb178890820c14451c1c3d69fd375b19", - strip_prefix = "benchmark-a3235d7b69c84e8c9ff8722a22b8ac5e1bc716a6", - urls = ["https://github.com/google/benchmark/archive/a3235d7b69c84e8c9ff8722a22b8ac5e1bc716a6.zip"], -) - -# Bazel Skylib. -http_archive( - name = "bazel_skylib", # 2022-11-16T18:29:32Z - sha256 = "a22290c26d29d3ecca286466f7f295ac6cbe32c0a9da3a91176a90e0725e3649", - strip_prefix = "bazel-skylib-5bfcb1a684550626ce138fe0fe8f5f702b3764c3", - urls = ["https://github.com/bazelbuild/bazel-skylib/archive/5bfcb1a684550626ce138fe0fe8f5f702b3764c3.zip"], -) - -# Bazel platform rules. -http_archive( - name = "platforms", # 2022-11-09T19:18:22Z - sha256 = "b4a3b45dc4202e2b3e34e3bc49d2b5b37295fc23ea58d88fb9e01f3642ad9b55", - strip_prefix = "platforms-3fbc687756043fb58a407c2ea8c944bc2fe1d922", - urls = ["https://github.com/bazelbuild/platforms/archive/3fbc687756043fb58a407c2ea8c944bc2fe1d922.zip"], -) diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index b2300ba9ba1..2a25ac64559 100644 --- a/absl/BUILD.bazel +++ b/absl/BUILD.bazel @@ -12,6 +12,7 @@ # 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. +# load("@bazel_skylib//lib:selects.bzl", "selects") @@ -27,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,94 +45,13 @@ config_setting( ) 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", + name = "fuchsia", constraint_values = [ - "@platforms//cpu:wasm64", + "@platforms//os:fuchsia", ], 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", - }, - visibility = [":__subpackages__"], -) - selects.config_setting_group( name = "mingw_compiler", match_any = [ diff --git a/absl/CMakeLists.txt b/absl/CMakeLists.txt index 3a7c12fe99c..810d7f31b9a 100644 --- a/absl/CMakeLists.txt +++ b/absl/CMakeLists.txt @@ -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() diff --git a/absl/abseil.podspec.gen.py b/absl/abseil.podspec.gen.py index 63752980d09..e1afa210bc9 100755 --- a/absl/abseil.podspec.gen.py +++ b/absl/abseil.podspec.gen.py @@ -30,6 +30,9 @@ :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 @@ '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): diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel index 3a9ab0136c4..0ec8b921e72 100644 --- a/absl/algorithm/BUILD.bazel +++ b/absl/algorithm/BUILD.bazel @@ -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", ], ) diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt index 181b49ca02e..f3dd138a2b4 100644 --- a/absl/algorithm/CMakeLists.txt +++ b/absl/algorithm/CMakeLists.txt @@ -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 ) diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h index e9b47338727..48f59504d2d 100644 --- a/absl/algorithm/algorithm.h +++ b/absl/algorithm/algorithm.h @@ -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 - bool operator()(const T& a, const U& b) const { - return a == b; - } -}; - -template -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 -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)); -} - -// 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 -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 -It RotateImpl(It first, It middle, It last, std::true_type) { - return std::rotate(first, middle, last); -} - -template -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 -// -// 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. +// 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 is a C++11-compatible implementation of C++14 `std::equal`. See -// https://en.cppreference.com/w/cpp/algorithm/equal for more information. -template -bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred&& pred) { - return algorithm_internal::EqualImpl( - first1, last1, first2, last2, std::forward(pred), - typename std::iterator_traits::iterator_category{}, - typename std::iterator_traits::iterator_category{}); -} - -// Overload of equal() that performs comparison of two ranges specified by pairs -// of iterators using operator==. -template -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 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 -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 -ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last) { - return algorithm_internal::RotateImpl( - first, middle, last, - std::is_same()); -} - ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/algorithm/algorithm_test.cc b/absl/algorithm/algorithm_test.cc index d18df0240fa..1c1a3079f8a 100644 --- a/absl/algorithm/algorithm_test.cc +++ b/absl/algorithm/algorithm_test.cc @@ -14,147 +14,14 @@ #include "absl/algorithm/algorithm.h" -#include -#include +#include #include -#include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/config.h" namespace { -TEST(EqualTest, DefaultComparisonRandomAccess) { - std::vector v1{1, 2, 3}; - std::vector v2 = v1; - std::vector v3 = {1, 2}; - std::vector 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 lst1{1, 2, 3}; - std::list lst2 = lst1; - std::list lst3{1, 2}; - std::list 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 v1{1, 2, 3}; - std::vector empty1; - std::vector 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 v1{1, 2, 3}; - std::list lst1{v1.begin(), v1.end()}; - std::list lst2{1, 2, 4}; - std::list 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 v1{1, 2, 3}; - std::vector v2{1, 2, 3}; - std::vector v3{1, 2}; - std::vector 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 v1{true, false}; - std::vector v2 = v1; - std::vector v3{true}; - std::vector 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 v1{&n[0], &n[1], &n[2]}; - std::vector v2 = v1; - std::vector v3{&n[0], &n[1], &n[3]}; - std::vector 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 v1{1, 2, 3}; - std::vector 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 v1{1, 1, 3}; - std::vector v2 = v1; - std::vector 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 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 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 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 diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 679e02676c6..6f9c1938fa8 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -51,7 +51,9 @@ #include #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())); // An MSVC bug involving template parameter substitution requires us to use // decltype() here instead of just std::pair. template -using ContainerIterPairType = - decltype(std::make_pair(ContainerIter(), ContainerIter())); +using ContainerIterPairType = decltype(std::make_pair( + std::declval>(), std::declval>())); template 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 -ContainerIter c_begin(C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { return begin(c); } template -ContainerIter c_end(C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { return end(c); } @@ -116,18 +118,6 @@ template struct IsUnorderedContainer> : std::true_type {}; -// container_algorithm_internal::c_size. It is meant for internal use only. - -template -auto c_size(C& c) -> decltype(c.size()) { - return c.size(); -} - -template -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 -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(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(value)); } //------------------------------------------------------------------------------ @@ -156,8 +149,9 @@ bool c_linear_search(const C& c, EqualityComparable&& value) { // Container-based version of the `std::distance()` function to // return the number of elements within a container. template -container_algorithm_internal::ContainerDifferenceType c_distance( - const C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerDifferenceType + 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 c_distance( // Container-based version of the `std::all_of()` function to // test if all elements within a container satisfy a condition. template -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)); @@ -182,7 +176,7 @@ bool c_all_of(const C& c, Pred&& pred) { // Container-based version of the `std::any_of()` function to // test if any element in a container fulfills a condition. template -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)); @@ -193,7 +187,7 @@ bool c_any_of(const C& c, Pred&& pred) { // Container-based version of the `std::none_of()` function to // test if no elements in a container fulfill a condition. template -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)); @@ -204,7 +198,8 @@ bool c_none_of(const C& c, Pred&& pred) { // Container-based version of the `std::for_each()` function to // apply a function to a container's elements. template -decay_t c_for_each(C&& c, Function&& f) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t 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(f)); @@ -215,18 +210,33 @@ decay_t c_for_each(C&& c, Function&& f) { // Container-based version of the `std::find()` function to find // the first element containing the passed value within a container value. template -container_algorithm_internal::ContainerIter c_find(C& c, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find(C& c, T&& value) { return std::find(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); } +// c_contains() +// +// Container-based version of the `std::ranges::contains()` C++23 +// function to search a container for a value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence, + T&& value) { + return absl::c_find(sequence, std::forward(value)) != + container_algorithm_internal::c_end(sequence); +} + // c_find_if() // // Container-based version of the `std::find_if()` function to find // the first element in a container matching the given condition. template -container_algorithm_internal::ContainerIter c_find_if(C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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)); @@ -237,8 +247,9 @@ container_algorithm_internal::ContainerIter c_find_if(C& c, Pred&& pred) { // Container-based version of the `std::find_if_not()` function to // find the first element in a container not matching the given condition. template -container_algorithm_internal::ContainerIter c_find_if_not(C& c, - Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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)); @@ -249,8 +260,9 @@ container_algorithm_internal::ContainerIter c_find_if_not(C& c, // Container-based version of the `std::find_end()` function to // find the last subsequence within a container. template -container_algorithm_internal::ContainerIter c_find_end( - Sequence1& sequence, Sequence2& subsequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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 c_find_end( // Overload of c_find_end() for using a predicate evaluation other than `==` as // the function's test condition. template -container_algorithm_internal::ContainerIter c_find_end( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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 c_find_end( // find the first element within the container that is also within the options // container. template -container_algorithm_internal::ContainerIter c_find_first_of(C1& container, - C2& options) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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 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 -container_algorithm_internal::ContainerIter c_find_first_of( - C1& container, C2& options, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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 c_find_first_of( // Container-based version of the `std::adjacent_find()` function to // find equal adjacent elements within a container. template -container_algorithm_internal::ContainerIter c_adjacent_find( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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 c_adjacent_find( // Overload of c_adjacent_find() for using a predicate evaluation other than // `==` as the function's test condition. template -container_algorithm_internal::ContainerIter c_adjacent_find( - Sequence& sequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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(pred)); @@ -321,8 +339,9 @@ container_algorithm_internal::ContainerIter c_adjacent_find( // Container-based version of the `std::count()` function to count // values that match within a container. template -container_algorithm_internal::ContainerDifferenceType c_count( - const C& c, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count(const C& c, T&& value) { return std::count(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); @@ -333,8 +352,9 @@ container_algorithm_internal::ContainerDifferenceType c_count( // Container-based version of the `std::count_if()` function to // count values matching a condition within a container. template -container_algorithm_internal::ContainerDifferenceType c_count_if( - const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + 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)); @@ -346,80 +366,50 @@ container_algorithm_internal::ContainerDifferenceType 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 -container_algorithm_internal::ContainerIterPairType 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 + 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 -container_algorithm_internal::ContainerIterPairType 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 + 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 `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 -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 -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(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(pred)); } // c_is_permutation() @@ -427,21 +417,23 @@ bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { // Container-based version of the `std::is_permutation()` function // to test whether a container is a permutation of another. template -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 -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(pred)); } @@ -450,8 +442,9 @@ bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { // Container-based version of the `std::search()` function to search // a container for a subsequence. template -container_algorithm_internal::ContainerIter c_search( - Sequence1& sequence, Sequence2& subsequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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 c_search( // Overload of c_search() for using a predicate evaluation other than // `==` as the function's test condition. template -container_algorithm_internal::ContainerIter c_search( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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 c_search( std::forward(pred)); } +// c_contains_subrange() +// +// Container-based version of the `std::ranges::contains_subrange()` +// C++23 function to search a container for a subsequence. +template +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 +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { + return absl::c_search(sequence, subsequence, + std::forward(pred)) != + container_algorithm_internal::c_end(sequence); +} + // c_search_n() // // Container-based version of the `std::search_n()` function to // search a container for the first sequence of N elements. template -container_algorithm_internal::ContainerIter c_search_n( - Sequence& sequence, Size count, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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(value)); @@ -486,8 +503,10 @@ container_algorithm_internal::ContainerIter c_search_n( // `==` as the function's test condition. template -container_algorithm_internal::ContainerIter c_search_n( - Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + 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(value), @@ -818,6 +837,20 @@ void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) { std::forward(gen)); } +// c_sample() +// +// Container-based version of the `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 +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(gen)); +} + //------------------------------------------------------------------------------ // 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 -container_algorithm_internal::ContainerIter c_min_element( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + 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 c_min_element( // Overload of c_min_element() for performing a `comp` comparison other than // `operator<`. template -container_algorithm_internal::ContainerIter c_min_element( - Sequence& sequence, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + 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(comp)); @@ -1536,8 +1571,9 @@ container_algorithm_internal::ContainerIter c_min_element( // to return an iterator pointing to the element with the largest value, using // `operator<` to make the comparisons. template -container_algorithm_internal::ContainerIter c_max_element( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + 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 c_max_element( // Overload of c_max_element() for performing a `comp` comparison other than // `operator<`. template -container_algorithm_internal::ContainerIter c_max_element( - Sequence& sequence, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + 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(comp)); @@ -1559,8 +1596,9 @@ container_algorithm_internal::ContainerIter c_max_element( // smallest and largest values, respectively, using `operator<` to make the // comparisons. template -container_algorithm_internal::ContainerIterPairType c_minmax_element( - C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + 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_minmax_element( // Overload of c_minmax_element() for performing `comp` comparisons other than // `operator<`. template -container_algorithm_internal::ContainerIterPairType c_minmax_element( - C& c, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + 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(comp)); @@ -1657,7 +1696,7 @@ bool c_prev_permutation(C& c, LessThan&& comp) { // // Container-based version of the `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 void c_iota(Sequence& sequence, const T& value) { std::iota(container_algorithm_internal::c_begin(sequence), diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc index 0fbc7773e8f..cb063355b7b 100644 --- a/absl/algorithm/container_test.cc +++ b/absl/algorithm/container_test.cc @@ -14,6 +14,9 @@ #include "absl/algorithm/container.h" +#include +#include +#include #include #include #include @@ -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&>(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{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{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 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 actual; + absl::c_sample(std::vector{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 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()) == 3); +} + +TEST(ConstexprTest, MinElement) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_min_element(kArray) == 1); +} + +TEST(ConstexprTest, MinElementWithPredicate) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_min_element(kArray, std::greater()) == 3); +} + +TEST(ConstexprTest, MaxElement) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_max_element(kArray) == 3); +} + +TEST(ConstexprTest, MaxElementWithPredicate) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_max_element(kArray, std::greater()) == 1); +} + +TEST(ConstexprTest, MinMaxElement) { + static constexpr std::array 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 kArray = {1, 2, 3}; + constexpr auto kMinMaxPair = + absl::c_minmax_element(kArray, std::greater()); + 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 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 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 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 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 kArray = [] { + std::array 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 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 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 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 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 kHaystack = {1, 2, 3, 2, 3}; + static constexpr std::array kNeedle = {2, 3}; + static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3); +} + +TEST(ConstexprTest, FindFirstOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin()); +} + +TEST(ConstexprTest, AdjacentFind) { + static constexpr std::array kArray = {1, 2, 2, 3}; + static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1); +} + +TEST(ConstexprTest, AdjacentFindWithPredicate) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_adjacent_find(kArray, std::less()) == + kArray.begin()); +} + +TEST(ConstexprTest, Count) { + static constexpr std::array 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 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 kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array 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 kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to()) == + std::pair{kArray1.begin(), kArray2.begin()}); + static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to()) == + std::pair{kArray1.end(), kArray3.end()}); +} + +TEST(ConstexprTest, Equal) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array 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 kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to())); + static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to())); +} + +TEST(ConstexprTest, IsPermutation) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {3, 2, 1}; + static constexpr std::array 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 kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {3, 2, 1}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to())); + static_assert( + !absl::c_is_permutation(kArray1, kArray3, std::equal_to())); +} + +TEST(ConstexprTest, Search) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array 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 kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to()) == + kArray1.end()); + static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to()) == + kArray1.begin()); +} + +TEST(ConstexprTest, ContainsSubrange) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array 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 kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array 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 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 kArray = {1, 2, 2, 3}; + static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to()) == + kArray.begin() + 1); + static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to()) == + kArray.end()); + static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to()) == + kArray.begin()); +} + +#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && + // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + } // namespace diff --git a/absl/algorithm/equal_benchmark.cc b/absl/algorithm/equal_benchmark.cc deleted file mode 100644 index 948cd65c54b..00000000000 --- a/absl/algorithm/equal_benchmark.cc +++ /dev/null @@ -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 -#include - -#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 -void BM_absl_equal_benchmark(benchmark::State& state) { - std::vector xs(state.range(0), T(0)); - std::vector ys = xs; - while (state.KeepRunning()) { - const bool same = absl::equal(xs.begin(), xs.end(), ys.begin(), ys.end()); - benchmark::DoNotOptimize(same); - } -} - -template -void BM_std_equal_benchmark(benchmark::State& state) { - std::vector xs(state.range(0), T(0)); - std::vector ys = xs; - while (state.KeepRunning()) { - const bool same = std::equal(xs.begin(), xs.end(), ys.begin()); - benchmark::DoNotOptimize(same); - } -} - -template -void BM_memcmp_benchmark(benchmark::State& state) { - std::vector xs(state.range(0), T(0)); - std::vector 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 -void BM_absl_equal_self_benchmark(benchmark::State& state) { - std::vector 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 diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 28cbf28f882..3724ad11df6 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -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,6 +69,29 @@ 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_deprecated.h"], + hdrs = ["nullability.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":core_headers", + ], +) + cc_library( name = "raw_logging_internal", srcs = ["internal/raw_logging.cc"], @@ -148,9 +178,6 @@ cc_library( cc_library( name = "core_headers", - srcs = [ - "internal/thread_annotations.h", - ], hdrs = [ "attributes.h", "const_init.h", @@ -179,9 +206,9 @@ 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": [], + "@rules_cc//cc/compiler:emscripten": [], "//conditions:default": ["-pthread"], }) + ABSL_DEFAULT_LINKOPTS, visibility = [ @@ -202,8 +229,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, @@ -240,17 +265,17 @@ 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": [], + "@rules_cc//cc/compiler:emscripten": [], "//conditions:default": ["-pthread"], }) + ABSL_DEFAULT_LINKOPTS, deps = [ @@ -261,6 +286,7 @@ cc_library( ":cycleclock_internal", ":dynamic_annotations", ":log_severity", + ":nullability", ":raw_logging_internal", ":spinlock_wait", "//absl/meta:type_traits", @@ -269,7 +295,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, @@ -290,7 +316,8 @@ cc_test( ":atomic_hook", ":atomic_hook_test_helper", ":core_headers", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -305,7 +332,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", ], ) @@ -332,7 +387,8 @@ cc_test( deps = [ ":config", ":throw_delegate", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -345,13 +401,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, @@ -360,7 +417,7 @@ cc_library( ], deps = [ ":config", - "@com_google_googletest//:gtest", + "@googletest//:gtest", ], ) @@ -368,12 +425,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, @@ -385,7 +444,7 @@ cc_library( "//absl/meta:type_traits", "//absl/strings", "//absl/utility", - "@com_google_googletest//:gtest", + "@googletest//:gtest", ], ) @@ -397,38 +456,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", ], ) @@ -436,7 +465,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, @@ -446,7 +475,7 @@ cc_library( ":config", ":core_headers", "//absl/synchronization", - "@com_google_googletest//:gtest", + "@googletest//:gtest", ], alwayslink = 1, ) @@ -466,13 +495,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, @@ -482,16 +512,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"], @@ -509,10 +540,14 @@ cc_library( ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], deps = [ ":base", ":config", ":core_headers", + ":nullability", ], ) @@ -523,7 +558,8 @@ cc_test( deps = [ ":config", ":endian", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -535,7 +571,8 @@ cc_test( deps = [ ":config", "//absl/synchronization:thread_pool", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -548,7 +585,58 @@ 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", + ], +) + +cc_test( + name = "nullability_test", + srcs = ["nullability_test.cc"], + deps = [ + ":core_headers", + ":nullability", + "@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", ], ) @@ -560,7 +648,8 @@ cc_test( deps = [ ":raw_logging_internal", "//absl/strings", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -573,7 +662,8 @@ cc_test( deps = [ ":base", "//absl/synchronization", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -595,7 +685,6 @@ cc_test( cc_test( name = "thread_identity_test", - size = "small", srcs = ["internal/thread_identity_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -606,12 +695,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, @@ -620,13 +711,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, @@ -647,7 +738,8 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":scoped_set_env", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -662,7 +754,8 @@ cc_test( "//absl/flags:flag_internal", "//absl/flags:marshalling", "//absl/strings", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -691,13 +784,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, @@ -705,18 +799,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", ], @@ -725,26 +816,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", ], ) @@ -752,14 +844,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", ], ) @@ -773,7 +900,8 @@ cc_test( deps = [ ":core_headers", "//absl/strings", - "@com_google_googletest//:gtest_main", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -786,6 +914,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", ], ) diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 71b9379540f..23942c04b21 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -49,11 +49,63 @@ 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_deprecated.h" + DEPS + absl::config absl::core_headers COPTS ${ABSL_DEFAULT_COPTS} ) +absl_cc_test( + NAME + nullability_test + SRCS + "nullability_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::core_headers + absl::nullability + 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 @@ -128,7 +180,6 @@ absl_cc_library( "optimization.h" "port.h" "thread_annotations.h" - "internal/thread_annotations.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS @@ -164,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} @@ -209,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 @@ -318,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 @@ -359,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 @@ -437,6 +470,7 @@ absl_cc_library( absl::base absl::config absl::core_headers + absl::nullability PUBLIC ) @@ -481,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 @@ -619,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 @@ -637,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 ) @@ -650,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( @@ -665,7 +713,6 @@ absl_cc_test( prefetch_test SRCS "prefetch_test.cc" - "internal/prefetch_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS @@ -685,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 +) diff --git a/absl/base/attributes.h b/absl/base/attributes.h index 3e5aafba115..d009f6d4912 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h @@ -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) @@ -274,7 +281,7 @@ // // Tells the ControlFlowIntegrity sanitizer to not instrument a given function. // See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. -#if ABSL_HAVE_ATTRIBUTE(no_sanitize) +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__) #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI @@ -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__)) @@ -685,6 +691,33 @@ #define ABSL_DEPRECATED(message) #endif +// 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 achieve that +// result. +// +// class ABSL_DEPRECATED("Use Bar instead") Foo; +// +// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING +// Baz ComputeBazFromFoo(Foo f); +// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING +#if defined(__GNUC__) || defined(__clang__) +// Clang also supports these GCC pragmas. +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("GCC diagnostic push") \ + _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 +#endif // defined(__GNUC__) || defined(__clang__) + // ABSL_CONST_INIT // // A variable declaration annotated with the `ABSL_CONST_INIT` attribute will @@ -725,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 +#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 @@ -743,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 +// 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 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 +// 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 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 @@ -778,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 // @@ -810,4 +1027,51 @@ #define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS #endif +// ABSL_ATTRIBUTE_UNINITIALIZED +// +// GCC and Clang support a flag `-ftrivial-auto-var-init=