diff options
author | Alexander Smirnov <alex@ydb.tech> | 2025-02-19 00:51:42 +0000 |
---|---|---|
committer | Alexander Smirnov <alex@ydb.tech> | 2025-02-19 00:51:42 +0000 |
commit | 95b254219eb0d087aadae07ff41ee597718fbbfd (patch) | |
tree | 21da0cb51a0ab8c1360b8adc4718beda1f023cf8 /contrib | |
parent | 0402fc0225de7587fb71303b66a54f2716820e96 (diff) | |
parent | afe5f174d1537a99ec81b46bd61861bc7f1a29ee (diff) | |
download | ydb-95b254219eb0d087aadae07ff41ee597718fbbfd.tar.gz |
Merge branch 'rightlib' into merge-libs-250219-0050
Diffstat (limited to 'contrib')
175 files changed, 3422 insertions, 1592 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/include/__config_site b/contrib/libs/cxxsupp/libcxx/include/__config_site index 9c748b346a..41a3962dd4 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__config_site +++ b/contrib/libs/cxxsupp/libcxx/include/__config_site @@ -3,7 +3,6 @@ #define _LIBCPP_ABI_VERSION 1 #define _LIBCPP_ABI_NAMESPACE __y1 -#define _LIBCPP_DISABLE_NODISCARD_EXT #define _LIBCPP_PSTL_CPU_BACKEND_THREAD #ifndef _YNDX_LIBCPP_ENABLE_EXTENSIONS diff --git a/contrib/libs/protobuf_old/protoherobora.py b/contrib/libs/protobuf_old/protoherobora.py new file mode 100644 index 0000000000..9b85a204bc --- /dev/null +++ b/contrib/libs/protobuf_old/protoherobora.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 + +import subprocess +import os +import sys +import json + + +# TODO: dedup +def is_cmdfile_arg(arg): + # type: (str) -> bool + return arg.startswith('@') + + +def cmdfile_path(arg): + # type: (str) -> str + return arg[1:] + + +def read_from_command_file(arg): + # type: (str) -> list[str] + with open(arg) as afile: + return afile.read().splitlines() + + +def skip_markers(args): + # type: (list[str]) -> list[str] + res = [] + for arg in args: + if arg == '--ya-start-command-file' or arg == '--ya-end-command-file': + continue + res.append(arg) + return res + + +def iter_args( + args, # type: list[str] + ): + for arg in args: + if not is_cmdfile_arg(arg): + if arg == '--ya-start-command-file' or arg == '--ya-end-command-file': + continue + yield arg + else: + for cmdfile_arg in read_from_command_file(cmdfile_path(arg)): + yield cmdfile_arg + + +def get_args(args): + # type: (list[str]) -> list[str] + return list(iter_args(args)) +# end TODO + + +def run(*args): + return subprocess.check_output(list(args), shell=False).strip() + + +def gen_renames_1(d): + for l in d.split('\n'): + l = l.strip() + + if ' ' in l: + yield l.split(' ')[-1] + + +def gen_renames_2(p, d): + for s in gen_renames_1(d): + """ + Since clang-17, the option -fsanitize-address-globals-dead-stripping + has been enabled by default. Due to this, we have broken optimization + that merges calls to the `asan.module_ctor` function, as we are renaming + symbols with a prefix of 'py2_'. When this flag is enabled, and + the functions are not merged, false-positive ODR (One Definition Rule) + violations occur on objects such as `typeinfo std::exception`, because + the runtime is trying to handle global objects that have already been handled. + """ + if 'asan_globals' in s: + continue + yield s + ' ' + p + s + + +def gen_renames(p, d): + return '\n'.join(gen_renames_2(p, d)).strip() + '\n' + + +def rename_syms(where, ret, libs): + p = 'py2_' + + # join libs + run(where + 'llvm-ar', 'qcL', ret, *libs) + + # find symbols to rename + syms = run(where + 'llvm-nm', '--extern-only', '--defined-only', '-A', ret) + + # prepare rename plan + renames = gen_renames(p, syms) + + with open('syms', 'w') as f: + f.write(renames) + + # rename symbols + run(where + 'llvm-objcopy', '--redefine-syms=syms', ret) + + # back-rename some symbols + args = [ + where + 'llvm-objcopy', + '--redefine-sym', + p + 'init_api_implementation=init6google8protobuf8internal19_api_implementation', + '--redefine-sym', + p + 'init_message=init6google8protobuf5pyext8_message', + '--redefine-sym', + p + 'init6google8protobuf8internal19_api_implementation=init6google8protobuf8internal19_api_implementation', + '--redefine-sym', + p + 'init6google8protobuf5pyext8_message=init6google8protobuf5pyext8_message', + '--redefine-sym', + p + '_init6google8protobuf8internal19_api_implementation=_init6google8protobuf8internal19_api_implementation', + '--redefine-sym', + p + '_init6google8protobuf5pyext8_message=_init6google8protobuf5pyext8_message', + ret, + ] + + run(*args) + return ret + + +def find_lld(args): + for x in args: + if 'lld-link' in x: + return x + + raise IndexError() + + +def fix_py2(cmd, have_comand_files=False, prefix='lib', suffix='a'): + args = cmd + + if have_comand_files: + args = get_args(cmd) + + if 'protobuf_old' not in str(args): + return cmd + + py2_libs = [prefix + 'contrib-libs-protobuf_old.' + suffix, prefix + 'pypython-protobuf-py2.' + suffix] + + def need_rename(x): + for v in py2_libs: + if v in x: + return True + + return False + + old = [] + lib = [] + + try: + where = os.path.dirname(cmd[cmd.index('--objcopy-exe') + 1]) + '/' + except ValueError: + where = os.path.dirname(find_lld(cmd)) + '/' + + for x in args: + if need_rename(x): + lib.append(x) + else: + old.append(x) + + name = rename_syms(where, 'libprotoherobora.' + suffix, lib) + + if not have_comand_files: + return old + [name] + + for file in cmd: + if is_cmdfile_arg(file): + cmd_file_path = cmdfile_path(file) + args = read_from_command_file(cmd_file_path) + if not 'protobuf_old' in str(args): + continue + with open(cmd_file_path, 'w') as afile: + for arg in args: + if not need_rename(arg): + afile.write(arg + '\n') + afile.write(name) + + return cmd + + +if __name__ == '__main__': + args = sys.argv[1:] + + if 'lld-link' in str(args): + cmd = fix_py2(args, have_comand_files=True, prefix='', suffix='lib') + else: + cmd = fix_py2(args) + + sys.stdout.write(json.dumps(cmd)) diff --git a/contrib/libs/protobuf_old/ya.make b/contrib/libs/protobuf_old/ya.make index 50a3d8cd79..39f6a558a8 100644 --- a/contrib/libs/protobuf_old/ya.make +++ b/contrib/libs/protobuf_old/ya.make @@ -2,6 +2,8 @@ LIBRARY() +LD_PLUGIN(protoherobora.py) + LICENSE( BSD-3-Clause AND Protobuf-License diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/__init__.py b/contrib/restricted/abseil-cpp/.yandex_meta/__init__.py index 8ffd340d62..489e4e6d66 100644 --- a/contrib/restricted/abseil-cpp/.yandex_meta/__init__.py +++ b/contrib/restricted/abseil-cpp/.yandex_meta/__init__.py @@ -160,6 +160,7 @@ abseil_cpp = CMakeNinjaNixProject( "absl_spinlock_wait", "absl_strerror", "absl_throw_delegate", + "absl_tracing_internal", ], "absl_debugging_internal": [ "absl_decode_rust_punycode", @@ -202,6 +203,7 @@ abseil_cpp = CMakeNinjaNixProject( "absl_log_internal_message", "absl_log_internal_nullguard", "absl_log_internal_proto", + "absl_log_internal_structured_proto", "absl_log_sink", "absl_vlog_config_internal", ], diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report index 1d1da6829f..1197f5fb7b 100644 --- a/contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report +++ b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report @@ -602,6 +602,8 @@ BELONGS absl/strings/ya.make Files with this license: absl/base/internal/poison.cc [1:1] absl/base/internal/poison.h [1:1] + absl/base/internal/tracing.cc [1:1] + absl/base/internal/tracing.h [1:1] absl/container/hash_container_defaults.h [1:1] absl/debugging/internal/bounded_utf8_length_sequence.h [1:1] absl/debugging/internal/decode_rust_punycode.cc [1:1] @@ -610,11 +612,13 @@ BELONGS absl/strings/ya.make absl/debugging/internal/demangle_rust.h [1:1] absl/debugging/internal/utf8_for_code_point.cc [1:1] absl/debugging/internal/utf8_for_code_point.h [1:1] + absl/log/internal/structured_proto.cc [2:2] + absl/log/internal/structured_proto.h [1:1] absl/random/internal/mock_validators.h [1:1] absl/status/internal/status_matchers.h [1:1] Belongs difference: + absl/strings/ya.make - - absl/base/ya.make absl/container/ya.make absl/debugging/ya.make absl/random/ya.make absl/status/ya.make + - absl/base/ya.make absl/container/ya.make absl/debugging/ya.make absl/log/ya.make absl/random/ya.make absl/status/ya.make KEEP COPYRIGHT_SERVICE_LABEL 9fd4860fdb6776c0e8deab1d14ff7b1b BELONGS absl/debugging/ya.make diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report index 7797dd2f87..3767fa892e 100644 --- a/contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report +++ b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report @@ -41,6 +41,8 @@ BELONGS absl/base/ya.make absl/debugging/ya.make absl/hash/ya.make absl/log/ya.m absl/base/internal/cycleclock_config.h [3:13] absl/base/internal/poison.cc [3:13] absl/base/internal/poison.h [3:13] + absl/base/internal/tracing.cc [3:13] + absl/base/internal/tracing.h [3:13] absl/base/internal/unscaledcycleclock_config.h [3:13] absl/base/prefetch.h [3:13] absl/container/hash_container_defaults.h [3:13] @@ -402,6 +404,8 @@ BELONGS absl/algorithm/ya.make absl/base/ya.make absl/container/ya.make absl/deb absl/log/internal/proto.h [3:13] absl/log/internal/strip.h [3:13] absl/log/internal/structured.h [3:13] + absl/log/internal/structured_proto.cc [4:14] + absl/log/internal/structured_proto.h [3:13] absl/log/internal/test_actions.h [3:13] absl/log/internal/test_helpers.h [3:13] absl/log/internal/test_matchers.h [3:13] diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/override.nix b/contrib/restricted/abseil-cpp/.yandex_meta/override.nix index 8935fabf1e..67be2bdadc 100644 --- a/contrib/restricted/abseil-cpp/.yandex_meta/override.nix +++ b/contrib/restricted/abseil-cpp/.yandex_meta/override.nix @@ -1,11 +1,11 @@ self: super: with self; rec { - version = "20240722.1"; + version = "20250127.0"; src = fetchFromGitHub { owner = "abseil"; repo = "abseil-cpp"; rev = version; - hash = "sha256-ir4hG2VIPv3se7JfWqCM/siLqFEFkmhMW/IGCocy6Pc="; + hash = "sha256-Tt4F0VT7koEARWNjL/L2E8jrPZbSsPb/Y32Kn86sb+k="; }; patches = []; diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h b/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h index 59aeed7d26..48f59504d2 100644 --- a/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h +++ b/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h @@ -53,8 +53,8 @@ using std::rotate; // n = (`last` - `first`) comparisons. A linear search over short containers // may be faster than a binary search, even when the container is sorted. template <typename InputIterator, typename EqualityComparable> -bool linear_search(InputIterator first, InputIterator last, - const EqualityComparable& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search( + InputIterator first, InputIterator last, const EqualityComparable& value) { return std::find(first, last, value) != last; } diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/container.h b/contrib/restricted/abseil-cpp/absl/algorithm/container.h index 6bbe3b5adf..3193656f88 100644 --- a/contrib/restricted/abseil-cpp/absl/algorithm/container.h +++ b/contrib/restricted/abseil-cpp/absl/algorithm/container.h @@ -131,11 +131,14 @@ struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>> // // Container-based version of absl::linear_search() for performing a linear // search within a container. +// +// For a generalization that uses a predicate, see absl::c_any_of(). template <typename C, typename EqualityComparable> -bool c_linear_search(const C& c, EqualityComparable&& value) { - return linear_search(container_algorithm_internal::c_begin(c), - container_algorithm_internal::c_end(c), - std::forward<EqualityComparable>(value)); +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search( + const C& c, EqualityComparable&& value) { + return absl::linear_search(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward<EqualityComparable>(value)); } //------------------------------------------------------------------------------ @@ -163,7 +166,7 @@ ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 // Container-based version of the <algorithm> `std::all_of()` function to // test if all elements within a container satisfy a condition. template <typename C, typename Pred> -bool c_all_of(const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) { return std::all_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<Pred>(pred)); @@ -174,7 +177,7 @@ bool c_all_of(const C& c, Pred&& pred) { // Container-based version of the <algorithm> `std::any_of()` function to // test if any element in a container fulfills a condition. template <typename C, typename Pred> -bool c_any_of(const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) { return std::any_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<Pred>(pred)); @@ -185,7 +188,7 @@ bool c_any_of(const C& c, Pred&& pred) { // Container-based version of the <algorithm> `std::none_of()` function to // test if no elements in a container fulfill a condition. template <typename C, typename Pred> -bool c_none_of(const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) { return std::none_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<Pred>(pred)); @@ -196,7 +199,8 @@ bool c_none_of(const C& c, Pred&& pred) { // Container-based version of the <algorithm> `std::for_each()` function to // apply a function to a container's elements. template <typename C, typename Function> -decay_t<Function> c_for_each(C&& c, Function&& f) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> c_for_each(C&& c, + Function&& f) { return std::for_each(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<Function>(f)); @@ -207,7 +211,9 @@ decay_t<Function> c_for_each(C&& c, Function&& f) { // Container-based version of the <algorithm> `std::find()` function to find // the first element containing the passed value within a container value. template <typename C, typename T> -container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<C> + c_find(C& c, T&& value) { return std::find(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<T>(value)); @@ -218,7 +224,8 @@ container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) { // Container-based version of the <algorithm> `std::ranges::contains()` C++23 // function to search a container for a value. template <typename Sequence, typename T> -bool c_contains(const Sequence& sequence, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence, + T&& value) { return absl::c_find(sequence, std::forward<T>(value)) != container_algorithm_internal::c_end(sequence); } @@ -228,7 +235,9 @@ bool c_contains(const Sequence& sequence, T&& value) { // Container-based version of the <algorithm> `std::find_if()` function to find // the first element in a container matching the given condition. template <typename C, typename Pred> -container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<C> + c_find_if(C& c, Pred&& pred) { return std::find_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<Pred>(pred)); @@ -239,8 +248,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) { // Container-based version of the <algorithm> `std::find_if_not()` function to // find the first element in a container not matching the given condition. template <typename C, typename Pred> -container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c, - Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<C> + c_find_if_not(C& c, Pred&& pred) { return std::find_if_not(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<Pred>(pred)); @@ -251,8 +261,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c, // Container-based version of the <algorithm> `std::find_end()` function to // find the last subsequence within a container. template <typename Sequence1, typename Sequence2> -container_algorithm_internal::ContainerIter<Sequence1> c_find_end( - Sequence1& sequence, Sequence2& subsequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence1> + c_find_end(Sequence1& sequence, Sequence2& subsequence) { return std::find_end(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -262,8 +273,10 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end( // Overload of c_find_end() for using a predicate evaluation other than `==` as // the function's test condition. template <typename Sequence1, typename Sequence2, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence1> c_find_end( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence1> + c_find_end(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { return std::find_end(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -277,8 +290,9 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end( // find the first element within the container that is also within the options // container. template <typename C1, typename C2> -container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container, - C2& options) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<C1> + c_find_first_of(C1& container, const C2& options) { return std::find_first_of(container_algorithm_internal::c_begin(container), container_algorithm_internal::c_end(container), container_algorithm_internal::c_begin(options), @@ -288,8 +302,9 @@ container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container, // Overload of c_find_first_of() for using a predicate evaluation other than // `==` as the function's test condition. template <typename C1, typename C2, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<C1> c_find_first_of( - C1& container, C2& options, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<C1> + c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) { return std::find_first_of(container_algorithm_internal::c_begin(container), container_algorithm_internal::c_end(container), container_algorithm_internal::c_begin(options), @@ -302,8 +317,9 @@ container_algorithm_internal::ContainerIter<C1> c_find_first_of( // Container-based version of the <algorithm> `std::adjacent_find()` function to // find equal adjacent elements within a container. template <typename Sequence> -container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence> + c_adjacent_find(Sequence& sequence) { return std::adjacent_find(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } @@ -311,8 +327,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find( // Overload of c_adjacent_find() for using a predicate evaluation other than // `==` as the function's test condition. template <typename Sequence, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find( - Sequence& sequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence> + c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) { return std::adjacent_find(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward<BinaryPredicate>(pred)); @@ -323,8 +340,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find( // Container-based version of the <algorithm> `std::count()` function to count // values that match within a container. template <typename C, typename T> -container_algorithm_internal::ContainerDifferenceType<const C> c_count( - const C& c, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType<const C> + c_count(const C& c, T&& value) { return std::count(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<T>(value)); @@ -335,8 +353,9 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count( // Container-based version of the <algorithm> `std::count_if()` function to // count values matching a condition within a container. template <typename C, typename Pred> -container_algorithm_internal::ContainerDifferenceType<const C> c_count_if( - const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType<const C> + c_count_if(const C& c, Pred&& pred) { return std::count_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward<Pred>(pred)); @@ -348,8 +367,9 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if( // return the first element where two ordered containers differ. Applies `==` to // the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). template <typename C1, typename C2> -container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1, - C2& c2) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType<C1, C2> + c_mismatch(C1& c1, C2& c2) { return std::mismatch(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -360,8 +380,9 @@ container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1, // the function's test condition. Applies `pred`to the first N elements of `c1` // and `c2`, where N = min(size(c1), size(c2)). template <typename C1, typename C2, typename BinaryPredicate> -container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch( - C1& c1, C2& c2, BinaryPredicate pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType<C1, C2> + c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) { return std::mismatch(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -373,7 +394,7 @@ container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch( // Container-based version of the <algorithm> `std::equal()` function to // test whether two containers are equal. template <typename C1, typename C2> -bool c_equal(const C1& c1, const C2& 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), @@ -383,7 +404,8 @@ bool c_equal(const C1& c1, const C2& c2) { // Overload of c_equal() for using a predicate evaluation other than `==` as // the function's test condition. template <typename C1, typename C2, typename BinaryPredicate> -bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { +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), @@ -396,7 +418,8 @@ bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { // Container-based version of the <algorithm> `std::is_permutation()` function // to test whether a container is a permutation of another. template <typename C1, typename C2> -bool c_is_permutation(const C1& c1, const C2& c2) { +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), @@ -406,7 +429,8 @@ bool c_is_permutation(const C1& c1, const C2& c2) { // Overload of c_is_permutation() for using a predicate evaluation other than // `==` as the function's test condition. template <typename C1, typename C2, typename BinaryPredicate> -bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { +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), @@ -419,8 +443,9 @@ bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { // Container-based version of the <algorithm> `std::search()` function to search // a container for a subsequence. template <typename Sequence1, typename Sequence2> -container_algorithm_internal::ContainerIter<Sequence1> c_search( - Sequence1& sequence, Sequence2& subsequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence1> + c_search(Sequence1& sequence, Sequence2& subsequence) { return std::search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -430,8 +455,10 @@ container_algorithm_internal::ContainerIter<Sequence1> c_search( // Overload of c_search() for using a predicate evaluation other than // `==` as the function's test condition. template <typename Sequence1, typename Sequence2, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence1> c_search( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence1> + c_search(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { return std::search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -444,7 +471,8 @@ container_algorithm_internal::ContainerIter<Sequence1> c_search( // Container-based version of the <algorithm> `std::ranges::contains_subrange()` // C++23 function to search a container for a subsequence. template <typename Sequence1, typename Sequence2> -bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence) { +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); } @@ -452,8 +480,8 @@ bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence) { // Overload of c_contains_subrange() for using a predicate evaluation other than // `==` as the function's test condition. template <typename Sequence1, typename Sequence2, typename BinaryPredicate> -bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence, - BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { return absl::c_search(sequence, subsequence, std::forward<BinaryPredicate>(pred)) != container_algorithm_internal::c_end(sequence); @@ -464,8 +492,9 @@ bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence, // Container-based version of the <algorithm> `std::search_n()` function to // search a container for the first sequence of N elements. template <typename Sequence, typename Size, typename T> -container_algorithm_internal::ContainerIter<Sequence> c_search_n( - Sequence& sequence, Size count, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence> + c_search_n(Sequence& sequence, Size count, T&& value) { return std::search_n(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), count, std::forward<T>(value)); @@ -475,8 +504,10 @@ container_algorithm_internal::ContainerIter<Sequence> c_search_n( // `==` as the function's test condition. template <typename Sequence, typename Size, typename T, typename BinaryPredicate> -container_algorithm_internal::ContainerIter<Sequence> c_search_n( - Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter<Sequence> + c_search_n(Sequence& sequence, Size count, T&& value, + BinaryPredicate&& pred) { return std::search_n(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), count, std::forward<T>(value), diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/ya.make b/contrib/restricted/abseil-cpp/absl/algorithm/ya.make index 4e3328995c..2deef3b2a7 100644 --- a/contrib/restricted/abseil-cpp/absl/algorithm/ya.make +++ b/contrib/restricted/abseil-cpp/absl/algorithm/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240722.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20250127.0.tar.gz) NO_RUNTIME() diff --git a/contrib/restricted/abseil-cpp/absl/base/attributes.h b/contrib/restricted/abseil-cpp/absl/base/attributes.h index 5ea5ee3ef8..95b102e52b 100644 --- a/contrib/restricted/abseil-cpp/absl/base/attributes.h +++ b/contrib/restricted/abseil-cpp/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)) @@ -827,30 +831,76 @@ #define ABSL_ATTRIBUTE_LIFETIME_BOUND #endif -// ABSL_INTERNAL_ATTRIBUTE_VIEW indicates that a type acts like a view i.e. a -// raw (non-owning) pointer. This enables diagnoses similar to those enabled by -// ABSL_ATTRIBUTE_LIFETIME_BOUND. +// Internal attribute; name and documentation TBD. +// +// See the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by) +#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) \ + [[clang::lifetime_capture_by(Owner)]] +#else +#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) +#endif + +// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it +// points to, similarly to a span, string_view, or other non-owning reference +// type. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template<class R> +// StringView(const R&); +// }; +// +// StringView f(std::string s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; } // // See the following links for details: // https://reviews.llvm.org/D64448 // https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html -#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) -#define ABSL_INTERNAL_ATTRIBUTE_VIEW [[gsl::Pointer]] +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]] #else -#define ABSL_INTERNAL_ATTRIBUTE_VIEW +#define ABSL_ATTRIBUTE_VIEW #endif -// ABSL_INTERNAL_ATTRIBUTE_OWNER indicates that a type acts like a smart -// (owning) pointer. This enables diagnoses similar to those enabled by -// ABSL_ATTRIBUTE_LIFETIME_BOUND. +// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or +// similar class that owns all the data that it points to. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template<class R> +// StringView(const R&); +// }; +// +// struct ABSL_ATTRIBUTE_OWNER String {}; +// +// StringView f(String s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; } // // See the following links for details: // https://reviews.llvm.org/D64448 // https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html -#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) -#define ABSL_INTERNAL_ATTRIBUTE_OWNER [[gsl::Owner]] +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]] #else -#define ABSL_INTERNAL_ATTRIBUTE_OWNER +#define ABSL_ATTRIBUTE_OWNER #endif // ABSL_ATTRIBUTE_TRIVIAL_ABI diff --git a/contrib/restricted/abseil-cpp/absl/base/call_once.h b/contrib/restricted/abseil-cpp/absl/base/call_once.h index 7b0e69ccd5..b666d36f0e 100644 --- a/contrib/restricted/abseil-cpp/absl/base/call_once.h +++ b/contrib/restricted/abseil-cpp/absl/base/call_once.h @@ -31,6 +31,8 @@ #include <type_traits> #include <utility> +#include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/invoke.h" #include "absl/base/internal/low_level_scheduling.h" #include "absl/base/internal/raw_logging.h" @@ -147,10 +149,10 @@ enum { }; template <typename Callable, typename... Args> -ABSL_ATTRIBUTE_NOINLINE void CallOnceImpl( - absl::Nonnull<std::atomic<uint32_t>*> control, - base_internal::SchedulingMode scheduling_mode, Callable&& fn, - Args&&... args) { + void + CallOnceImpl(absl::Nonnull<std::atomic<uint32_t>*> control, + base_internal::SchedulingMode scheduling_mode, Callable&& fn, + Args&&... args) { #ifndef NDEBUG { uint32_t old_control = control->load(std::memory_order_relaxed); @@ -209,7 +211,8 @@ void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn, } // namespace base_internal template <typename Callable, typename... Args> -void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) { + void + call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) { std::atomic<uint32_t>* once = base_internal::ControlWord(&flag); uint32_t s = once->load(std::memory_order_acquire); if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) { diff --git a/contrib/restricted/abseil-cpp/absl/base/config.h b/contrib/restricted/abseil-cpp/absl/base/config.h index 46e6fbcb9b..0b24865153 100644 --- a/contrib/restricted/abseil-cpp/absl/base/config.h +++ b/contrib/restricted/abseil-cpp/absl/base/config.h @@ -117,8 +117,8 @@ // // LTS releases can be obtained from // https://github.com/abseil/abseil-cpp/releases. -#define ABSL_LTS_RELEASE_VERSION 20240722 -#define ABSL_LTS_RELEASE_PATCH_LEVEL 1 +#define ABSL_LTS_RELEASE_VERSION 20250127 +#define ABSL_LTS_RELEASE_PATCH_LEVEL 0 // Helper macro to convert a CPP variable to a string literal. #define ABSL_INTERNAL_DO_TOKEN_STR(x) #x @@ -380,7 +380,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || defined(__asmjs__) || defined(__EMSCRIPTEN__) || defined(__Fuchsia__) || \ defined(__sun) || defined(__myriad2__) || defined(__HAIKU__) || \ defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) || \ - defined(__VXWORKS__) || defined(__hexagon__) + defined(__VXWORKS__) || defined(__hexagon__) || defined(__XTENSA__) #define ABSL_HAVE_MMAP 1 #endif @@ -926,7 +926,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code #ifdef ABSL_INTERNAL_HAVE_ARM_NEON #error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set -#elif defined(__ARM_NEON) && !defined(__CUDA_ARCH__) +#elif defined(__ARM_NEON) && !(defined(__NVCC__) && defined(__CUDACC__)) #define ABSL_INTERNAL_HAVE_ARM_NEON 1 #endif diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/nullability_impl.h b/contrib/restricted/abseil-cpp/absl/base/internal/nullability_impl.h index 03fa2434ce..b601fc4ce9 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/nullability_impl.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/nullability_impl.h @@ -26,80 +26,41 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace nullability_internal { -// `IsNullabilityCompatible` checks whether its first argument is a class -// explicitly tagged as supporting nullability annotations. The tag is the type -// declaration `absl_nullability_compatible`. -template <typename, typename = void> -struct IsNullabilityCompatible : std::false_type {}; - -template <typename T> -struct IsNullabilityCompatible< - T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type { -}; - -template <typename T> -constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value; - -template <typename T> -constexpr bool IsSupportedType<T*> = true; - -template <typename T, typename U> -constexpr bool IsSupportedType<T U::*> = true; - -template <typename T, typename... Deleter> -constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true; - -template <typename T> -constexpr bool IsSupportedType<std::shared_ptr<T>> = true; - template <typename T> -struct EnableNullable { - static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, - "Template argument must be a raw or supported smart pointer " - "type. See absl/base/nullability.h."); - using type = T; -}; - -template <typename T> -struct EnableNonnull { - static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, - "Template argument must be a raw or supported smart pointer " - "type. See absl/base/nullability.h."); - using type = T; -}; - -template <typename T> -struct EnableNullabilityUnknown { - static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, - "Template argument must be a raw or supported smart pointer " - "type. See absl/base/nullability.h."); - using type = T; -}; - -// Note: we do not apply Clang nullability attributes (e.g. _Nullable). These -// only support raw pointers, and conditionally enabling them only for raw -// pointers inhibits template arg deduction. Ideally, they would support all -// pointer-like types. -template <typename T, typename = typename EnableNullable<T>::type> using NullableImpl #if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) [[clang::annotate("Nullable")]] #endif +// Don't add the _Nullable attribute in Objective-C compiles. Many Objective-C +// projects enable the `-Wnullable-to-nonnull-conversion warning`, which is +// liable to produce false positives. +#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) + = T _Nullable; +#else = T; +#endif -template <typename T, typename = typename EnableNonnull<T>::type> +template <typename T> using NonnullImpl #if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) [[clang::annotate("Nonnull")]] #endif +#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) + = T _Nonnull; +#else = T; +#endif -template <typename T, typename = typename EnableNullabilityUnknown<T>::type> +template <typename T> using NullabilityUnknownImpl #if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) [[clang::annotate("Nullability_Unspecified")]] #endif +#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__) + = T _Null_unspecified; +#else = T; +#endif } // namespace nullability_internal ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc index d32b40a8bb..35a08f0ac0 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc +++ b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc @@ -175,7 +175,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line, } else { DoRawLog(&buf, &size, "%s", kTruncated); } - AsyncSignalSafeWriteError(buffer, strlen(buffer)); + AsyncSignalSafeWriteError(buffer, static_cast<size_t>(buf - buffer)); } #else static_cast<void>(format); diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc b/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc index b86667cb08..62880330ac 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc +++ b/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc @@ -46,6 +46,10 @@ #error #include <rtems.h> #endif +#if defined(__Fuchsia__) +#include <zircon/process.h> +#endif + #include <string.h> #include <cassert> @@ -461,6 +465,16 @@ pid_t GetTID() { return reinterpret_cast<pid_t>(thread); } +#elif defined(__Fuchsia__) + +pid_t GetTID() { + // Use our thread handle as the TID, which should be unique within this + // process (but may not be globally unique). The handle value was chosen over + // a kernel object ID (KOID) because zx_handle_t (32-bits) can be cast to a + // pid_t type without loss of precision, but a zx_koid_t (64-bits) cannot. + return static_cast<pid_t>(zx_thread_self()); +} + #else // Fallback implementation of `GetTID` using `pthread_self`. diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h b/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h index b6e917ce80..acfc15a8f6 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h @@ -130,7 +130,11 @@ struct PerThreadSynch { }; // The instances of this class are allocated in NewThreadIdentity() with an -// alignment of PerThreadSynch::kAlignment. +// alignment of PerThreadSynch::kAlignment and never destroyed. Initialization +// should happen in OneTimeInitThreadIdentity(). +// +// Instances may be reused by new threads - fields should be reset in +// ResetThreadIdentityBetweenReuse(). // // NOTE: The layout of fields in this structure is critical, please do not // add, remove, or modify the field placements without fully auditing the diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/tracing.cc b/contrib/restricted/abseil-cpp/absl/base/internal/tracing.cc new file mode 100644 index 0000000000..d304e6a29a --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/base/internal/tracing.cc @@ -0,0 +1,39 @@ +// Copyright 2024 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/base/internal/tracing.h" + +#include "absl/base/attributes.h" +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace base_internal { + +extern "C" { + +ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)( + const void*, ObjectKind) {} +ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)( + const void*, ObjectKind) {} +ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)( + const void*, ObjectKind) {} +ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)( + const void*, ObjectKind) {} + +} // extern "C" + +} // namespace base_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/tracing.h b/contrib/restricted/abseil-cpp/absl/base/internal/tracing.h new file mode 100644 index 0000000000..e7ab7758fe --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/base/internal/tracing.h @@ -0,0 +1,81 @@ +// Copyright 2024 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_BASE_INTERNAL_TRACING_H_ +#define ABSL_BASE_INTERNAL_TRACING_H_ + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace base_internal { + +// Well known Abseil object types that have causality. +enum class ObjectKind { kUnknown, kBlockingCounter, kNotification }; + +// `TraceWait` and `TraceContinue` record the start and end of a potentially +// blocking wait operation on `object`. `object` typically represents a higher +// level synchronization object such as `absl::Notification`. +void TraceWait(const void* object, ObjectKind kind); +void TraceContinue(const void* object, ObjectKind kind); + +// `TraceSignal` records a signal on `object`. +void TraceSignal(const void* object, ObjectKind kind); + +// `TraceObserved` records the non-blocking observation of a signaled object. +void TraceObserved(const void* object, ObjectKind kind); + +// --------------------------------------------------------------------------- +// Weak implementation detail: +// +// We define the weak API as extern "C": in some build configurations we pass +// `--detect-odr-violations` to the gold linker. This causes it to flag weak +// symbol overrides as ODR violations. Because ODR only applies to C++ and not +// C, `--detect-odr-violations` ignores symbols not mangled with C++ names. +// By changing our extension points to be extern "C", we dodge this check. +// --------------------------------------------------------------------------- +extern "C" { + + void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object, + ObjectKind kind); + void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object, + ObjectKind kind); + void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object, + ObjectKind kind); + void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object, + ObjectKind kind); + +} // extern "C" + +inline void TraceWait(const void* object, ObjectKind kind) { + ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(object, kind); +} + +inline void TraceContinue(const void* object, ObjectKind kind) { + ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(object, kind); +} + +inline void TraceSignal(const void* object, ObjectKind kind) { + ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(object, kind); +} + +inline void TraceObserved(const void* object, ObjectKind kind) { + ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(object, kind); +} + +} // namespace base_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_BASE_INTERNAL_TRACING_H_ diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.cc b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.cc index a0bf3a65f7..68f92730a8 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +++ b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.cc @@ -105,16 +105,6 @@ double UnscaledCycleClock::Frequency() { #elif defined(__aarch64__) -// System timer of ARMv8 runs at a different frequency than the CPU's. -// The frequency is fixed, typically in the range 1-50MHz. It can be -// read at CNTFRQ special register. We assume the OS has set up -// the virtual timer properly. -int64_t UnscaledCycleClock::Now() { - int64_t virtual_timer_value; - asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); - return virtual_timer_value; -} - double UnscaledCycleClock::Frequency() { uint64_t aarch64_timer_frequency; asm volatile("mrs %0, cntfrq_el0" : "=r"(aarch64_timer_frequency)); diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h index cc1276ba08..965c42de4e 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h @@ -85,6 +85,18 @@ inline int64_t UnscaledCycleClock::Now() { return static_cast<int64_t>((high << 32) | low); } +#elif defined(__aarch64__) + +// System timer of ARMv8 runs at a different frequency than the CPU's. +// The frequency is fixed, typically in the range 1-50MHz. It can be +// read at CNTFRQ special register. We assume the OS has set up +// the virtual timer properly. +inline int64_t UnscaledCycleClock::Now() { + int64_t virtual_timer_value; + asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); + return virtual_timer_value; +} + #endif } // namespace base_internal diff --git a/contrib/restricted/abseil-cpp/absl/base/macros.h b/contrib/restricted/abseil-cpp/absl/base/macros.h index b318f11664..ff89944ae4 100644 --- a/contrib/restricted/abseil-cpp/absl/base/macros.h +++ b/contrib/restricted/abseil-cpp/absl/base/macros.h @@ -34,6 +34,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/optimization.h" +#include "absl/base/options.h" #include "absl/base/port.h" // ABSL_ARRAYSIZE() @@ -81,8 +82,9 @@ ABSL_NAMESPACE_END // ABSL_ASSERT() // // In C++11, `assert` can't be used portably within constexpr functions. +// `assert` also generates spurious unused-symbol warnings. // ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr -// functions. Example: +// functions, and maintains references to symbols. Example: // // constexpr double Divide(double a, double b) { // return ABSL_ASSERT(b != 0), a / b; @@ -91,8 +93,18 @@ ABSL_NAMESPACE_END // This macro is inspired by // https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ #if defined(NDEBUG) -#define ABSL_ASSERT(expr) \ - (false ? static_cast<void>(expr) : static_cast<void>(0)) +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +// We use `decltype` here to avoid generating unnecessary code that the +// optimizer then has to optimize away. +// This not only improves compilation performance by reducing codegen bloat +// and optimization work, but also guarantees fast run-time performance without +// having to rely on the optimizer. +#define ABSL_ASSERT(expr) (decltype((expr) ? void() : void())()) +#else +// Pre-C++20, lambdas can't be inside unevaluated operands, so we're forced to +// rely on the optimizer. +#define ABSL_ASSERT(expr) (false ? ((expr) ? void() : void()) : void()) +#endif #else #define ABSL_ASSERT(expr) \ (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \ @@ -120,7 +132,7 @@ ABSL_NAMESPACE_END // // See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on // hardened mode. -#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) +#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG) #define ABSL_HARDENING_ASSERT(expr) \ (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \ : [] { ABSL_INTERNAL_HARDENING_ABORT(); }()) @@ -128,6 +140,25 @@ ABSL_NAMESPACE_END #define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr) #endif +// ABSL_HARDENING_ASSERT_SLOW() +// +// `ABSL_HARDENING_ASSERT()` is like `ABSL_HARDENING_ASSERT()`, +// but specifically for assertions whose predicates are too slow +// to be enabled in many applications. +// +// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT_SLOW()` is identical to +// `ABSL_ASSERT()`. +// +// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on +// hardened mode. +#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG) +#define ABSL_HARDENING_ASSERT_SLOW(expr) \ + (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \ + : [] { ABSL_INTERNAL_HARDENING_ABORT(); }()) +#else +#define ABSL_HARDENING_ASSERT_SLOW(expr) ABSL_ASSERT(expr) +#endif + #ifdef ABSL_HAVE_EXCEPTIONS #define ABSL_INTERNAL_TRY try #define ABSL_INTERNAL_CATCH_ANY catch (...) diff --git a/contrib/restricted/abseil-cpp/absl/base/nullability.h b/contrib/restricted/abseil-cpp/absl/base/nullability.h index 34dc083a4e..241c65ac25 100644 --- a/contrib/restricted/abseil-cpp/absl/base/nullability.h +++ b/contrib/restricted/abseil-cpp/absl/base/nullability.h @@ -135,17 +135,9 @@ // ... // }; // -// Note: For the time being, nullability-compatible classes should additionally -// be marked with an `absl_nullability_compatible` nested type (this will soon -// be deprecated). The actual definition of this inner type is not relevant as -// it is used merely as a marker. It is common to use a using declaration of -// `absl_nullability_compatible` set to void. -// -// // Example: -// struct MyPtr { -// using absl_nullability_compatible = void; -// ... -// }; +// Note: Compilers that don't support the `nullability_on_classes` feature will +// allow nullability annotations to be applied to any type, not just ones +// marked with `ABSL_NULLABILITY_COMPATIBLE`. // // DISCLAIMER: // =========================================================================== @@ -161,10 +153,47 @@ #include "absl/base/config.h" #include "absl/base/internal/nullability_impl.h" +// ABSL_POINTERS_DEFAULT_NONNULL +// +// This macro specifies that all unannotated pointer types within the given +// file are designated as nonnull (instead of the default "unknown"). This macro +// exists as a standalone statement and applies default nonnull behavior to all +// subsequent pointers; as a result, place this macro as the first non-comment, +// non-`#include` line in a file. +// +// Example: +// +// #include "absl/base/nullability.h" +// +// ABSL_POINTERS_DEFAULT_NONNULL +// +// void FillMessage(Message *m); // implicitly non-null +// absl::Nullable<T*> GetNullablePtr(); // explicitly nullable +// absl::NullabilityUnknown<T*> GetUnknownPtr(); // explicitly unknown +// +// The macro can be safely used in header files -- it will not affect any files +// that include it. +// +// In files with the macro, plain `T*` syntax means `absl::Nonnull<T*>`, and the +// exceptions (`Nullable` and `NullabilityUnknown`) must be marked +// explicitly. The same holds, correspondingly, for smart pointer types. +// +// For comparison, without the macro, all unannotated pointers would default to +// unknown, and otherwise require explicit annotations to change this behavior: +// +// #include "absl/base/nullability.h" +// +// void FillMessage(absl::Nonnull<Message*> m); // explicitly non-null +// absl::Nullable<T*> GetNullablePtr(); // explicitly nullable +// T* GetUnknownPtr(); // implicitly unknown +// +// No-op except for being a human readable signal. +#define ABSL_POINTERS_DEFAULT_NONNULL + namespace absl { ABSL_NAMESPACE_BEGIN -// absl::Nonnull +// absl::Nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`) // // The indicated pointer is never null. It is the responsibility of the provider // of this pointer across an API boundary to ensure that the pointer is never @@ -197,7 +226,7 @@ using Nonnull = nullability_internal::NonnullImpl<T>; template <typename T> using Nullable = nullability_internal::NullableImpl<T>; -// absl::NullabilityUnknown (default) +// absl::NullabilityUnknown (default without `ABSL_POINTERS_DEFAULT_NONNULL`) // // The indicated pointer has not yet been determined to be definitively // "non-null" or "nullable." Providers of such pointers across API boundaries @@ -208,9 +237,10 @@ using Nullable = nullability_internal::NullableImpl<T>; // migrated into one of the above two nullability states: `Nonnull<T>` or // `Nullable<T>`. // -// NOTE: Because this annotation is the global default state, unannotated -// pointers are assumed to have "unknown" semantics. This assumption is designed -// to minimize churn and reduce clutter within the codebase. +// NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`, +// because this annotation is the global default state, unannotated pointers are +// are assumed to have "unknown" semantics. This assumption is designed to +// minimize churn and reduce clutter within the codebase. // // Example: // @@ -241,10 +271,36 @@ ABSL_NAMESPACE_END // struct ABSL_NULLABILITY_COMPATIBLE MyPtr { // ... // }; +// +// Note: Compilers that don't support the `nullability_on_classes` feature will +// allow nullability annotations to be applied to any type, not just ones marked +// with `ABSL_NULLABILITY_COMPATIBLE`. #if ABSL_HAVE_FEATURE(nullability_on_classes) #define ABSL_NULLABILITY_COMPATIBLE _Nullable #else #define ABSL_NULLABILITY_COMPATIBLE #endif +// ABSL_NONNULL +// ABSL_NULLABLE +// ABSL_NULLABILITY_UNKNOWN +// +// These macros are analogues of the alias template nullability annotations +// above. +// +// Example: +// int* ABSL_NULLABLE foo; +// Is equivalent to: +// absl::Nullable<int*> foo; +#if defined(__clang__) && !defined(__OBJC__) && \ + ABSL_HAVE_FEATURE(nullability_on_classes) +#define ABSL_NONNULL _Nonnull +#define ABSL_NULLABLE _Nullable +#define ABSL_NULLABILITY_UNKNOWN _Null_unspecified +#else +#define ABSL_NONNULL +#define ABSL_NULLABLE +#define ABSL_NULLABILITY_UNKNOWN +#endif + #endif // ABSL_BASE_NULLABILITY_H_ diff --git a/contrib/restricted/abseil-cpp/absl/base/optimization.h b/contrib/restricted/abseil-cpp/absl/base/optimization.h index 3aa66e1c7d..429ea9ce79 100644 --- a/contrib/restricted/abseil-cpp/absl/base/optimization.h +++ b/contrib/restricted/abseil-cpp/absl/base/optimization.h @@ -25,6 +25,8 @@ // new code that requires C compatibility or assume C compatibility will remain // indefinitely. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_BASE_OPTIMIZATION_H_ #define ABSL_BASE_OPTIMIZATION_H_ @@ -271,20 +273,14 @@ #elif defined(_MSC_VER) #define ABSL_ASSUME(cond) __assume(cond) #elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L -#define ABSL_ASSUME(cond) \ - do { \ - if (!(cond)) std::unreachable(); \ - } while (false) +#define ABSL_ASSUME(cond) ((cond) ? void() : std::unreachable()) #elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable) -#define ABSL_ASSUME(cond) \ - do { \ - if (!(cond)) __builtin_unreachable(); \ - } while (false) +#define ABSL_ASSUME(cond) ((cond) ? void() : __builtin_unreachable()) +#elif ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +// Unimplemented. Uses the same definition as ABSL_ASSERT in the NDEBUG case. +#define ABSL_ASSUME(expr) (decltype((expr) ? void() : void())()) #else -#define ABSL_ASSUME(cond) \ - do { \ - static_cast<void>(false && (cond)); \ - } while (false) +#define ABSL_ASSUME(expr) (false ? ((expr) ? void() : void()) : void()) #endif // ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond) diff --git a/contrib/restricted/abseil-cpp/absl/base/options.h b/contrib/restricted/abseil-cpp/absl/base/options.h index 61a996b6c8..5caa58f6e3 100644 --- a/contrib/restricted/abseil-cpp/absl/base/options.h +++ b/contrib/restricted/abseil-cpp/absl/base/options.h @@ -226,7 +226,7 @@ // allowed. #define ABSL_OPTION_USE_INLINE_NAMESPACE 1 -#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20240722 +#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250127 // ABSL_OPTION_HARDENED // @@ -235,7 +235,10 @@ // // A value of 0 means that "hardened" mode is not enabled. // -// A value of 1 means that "hardened" mode is enabled. +// A value of 1 means that "hardened" mode is enabled with all checks. +// +// A value of 2 means that "hardened" mode is partially enabled, with +// only a subset of checks chosen to minimize performance impact. // // Hardened builds have additional security checks enabled when `NDEBUG` is // defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a diff --git a/contrib/restricted/abseil-cpp/absl/base/policy_checks.h b/contrib/restricted/abseil-cpp/absl/base/policy_checks.h index 372e848d8c..7538166bed 100644 --- a/contrib/restricted/abseil-cpp/absl/base/policy_checks.h +++ b/contrib/restricted/abseil-cpp/absl/base/policy_checks.h @@ -21,6 +21,8 @@ // reported with `#error`. This enforcement is best effort, so successfully // compiling this header does not guarantee a supported configuration. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_BASE_POLICY_CHECKS_H_ #define ABSL_BASE_POLICY_CHECKS_H_ diff --git a/contrib/restricted/abseil-cpp/absl/base/ya.make b/contrib/restricted/abseil-cpp/absl/base/ya.make index c887180740..f31517630e 100644 --- a/contrib/restricted/abseil-cpp/absl/base/ya.make +++ b/contrib/restricted/abseil-cpp/absl/base/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( library/cpp/sanitizer/include @@ -32,6 +32,7 @@ SRCS( internal/sysinfo.cc internal/thread_identity.cc internal/throw_delegate.cc + internal/tracing.cc internal/unscaledcycleclock.cc log_severity.cc ) diff --git a/contrib/restricted/abseil-cpp/absl/container/btree_map.h b/contrib/restricted/abseil-cpp/absl/container/btree_map.h index b959b674ee..470de2a199 100644 --- a/contrib/restricted/abseil-cpp/absl/container/btree_map.h +++ b/contrib/restricted/abseil-cpp/absl/container/btree_map.h @@ -87,7 +87,7 @@ struct map_params; // template <typename Key, typename Value, typename Compare = std::less<Key>, typename Alloc = std::allocator<std::pair<const Key, Value>>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_map +class ABSL_ATTRIBUTE_OWNER btree_map : public container_internal::btree_map_container< container_internal::btree<container_internal::map_params< Key, Value, Compare, Alloc, /*TargetNodeSize=*/256, @@ -525,7 +525,7 @@ typename btree_map<K, V, C, A>::size_type erase_if( // template <typename Key, typename Value, typename Compare = std::less<Key>, typename Alloc = std::allocator<std::pair<const Key, Value>>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multimap +class ABSL_ATTRIBUTE_OWNER btree_multimap : public container_internal::btree_multimap_container< container_internal::btree<container_internal::map_params< Key, Value, Compare, Alloc, /*TargetNodeSize=*/256, diff --git a/contrib/restricted/abseil-cpp/absl/container/btree_set.h b/contrib/restricted/abseil-cpp/absl/container/btree_set.h index 986d27da6f..e57d6d9b68 100644 --- a/contrib/restricted/abseil-cpp/absl/container/btree_set.h +++ b/contrib/restricted/abseil-cpp/absl/container/btree_set.h @@ -89,7 +89,7 @@ struct set_params; // template <typename Key, typename Compare = std::less<Key>, typename Alloc = std::allocator<Key>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_set +class ABSL_ATTRIBUTE_OWNER btree_set : public container_internal::btree_set_container< container_internal::btree<container_internal::set_params< Key, Compare, Alloc, /*TargetNodeSize=*/256, @@ -445,7 +445,7 @@ typename btree_set<K, C, A>::size_type erase_if(btree_set<K, C, A> &set, // template <typename Key, typename Compare = std::less<Key>, typename Alloc = std::allocator<Key>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multiset +class ABSL_ATTRIBUTE_OWNER btree_multiset : public container_internal::btree_multiset_container< container_internal::btree<container_internal::set_params< Key, Compare, Alloc, /*TargetNodeSize=*/256, diff --git a/contrib/restricted/abseil-cpp/absl/container/fixed_array.h b/contrib/restricted/abseil-cpp/absl/container/fixed_array.h index 9f1c813dca..95abb0a59d 100644 --- a/contrib/restricted/abseil-cpp/absl/container/fixed_array.h +++ b/contrib/restricted/abseil-cpp/absl/container/fixed_array.h @@ -41,6 +41,7 @@ #include <type_traits> #include "absl/algorithm/algorithm.h" +#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/throw_delegate.h" @@ -74,7 +75,7 @@ constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1); // `std::vector`. template <typename T, size_t N = kFixedArrayUseDefault, typename A = std::allocator<T>> -class FixedArray { +class ABSL_ATTRIBUTE_WARN_UNUSED FixedArray { static_assert(!std::is_array<T>::value || std::extent<T>::value > 0, "Arrays with unknown bounds cannot be used with FixedArray."); diff --git a/contrib/restricted/abseil-cpp/absl/container/flat_hash_map.h b/contrib/restricted/abseil-cpp/absl/container/flat_hash_map.h index ebd9ed6756..735ee3424d 100644 --- a/contrib/restricted/abseil-cpp/absl/container/flat_hash_map.h +++ b/contrib/restricted/abseil-cpp/absl/container/flat_hash_map.h @@ -125,7 +125,7 @@ struct FlatHashMapPolicy; template <class K, class V, class Hash = DefaultHashContainerHash<K>, class Eq = DefaultHashContainerEq<K>, class Allocator = std::allocator<std::pair<const K, V>>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_map +class ABSL_ATTRIBUTE_OWNER flat_hash_map : public absl::container_internal::raw_hash_map< absl::container_internal::FlatHashMapPolicy<K, V>, Hash, Eq, Allocator> { @@ -426,8 +426,7 @@ class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_map // flat_hash_map::swap(flat_hash_map& other) // // Exchanges the contents of this `flat_hash_map` with those of the `other` - // flat hash map, avoiding invocation of any move, copy, or swap operations on - // individual elements. + // flat hash map. // // All iterators and references on the `flat_hash_map` remain valid, excepting // for the past-the-end iterator, which is invalidated. @@ -574,6 +573,21 @@ typename flat_hash_map<K, V, H, E, A>::size_type erase_if( return container_internal::EraseIf(pred, &c); } +// swap(flat_hash_map<>, flat_hash_map<>) +// +// Swaps the contents of two `flat_hash_map` containers. +// +// NOTE: we need to define this function template in order for +// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we +// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a +// derived-to-base conversion, whereas `std::swap` is a function template so +// `std::swap` will be preferred by compiler. +template <typename K, typename V, typename H, typename E, typename A> +void swap(flat_hash_map<K, V, H, E, A>& x, + flat_hash_map<K, V, H, E, A>& y) noexcept(noexcept(x.swap(y))) { + x.swap(y); +} + namespace container_internal { // c_for_each_fast(flat_hash_map<>, Function) diff --git a/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h b/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h index a3e36e05e3..b5d0f7f955 100644 --- a/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h +++ b/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h @@ -122,7 +122,7 @@ struct FlatHashSetPolicy; template <class T, class Hash = DefaultHashContainerHash<T>, class Eq = DefaultHashContainerEq<T>, class Allocator = std::allocator<T>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_set +class ABSL_ATTRIBUTE_OWNER flat_hash_set : public absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy<T>, Hash, Eq, Allocator> { using Base = typename flat_hash_set::raw_hash_set; @@ -360,8 +360,7 @@ class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_set // flat_hash_set::swap(flat_hash_set& other) // // Exchanges the contents of this `flat_hash_set` with those of the `other` - // flat hash set, avoiding invocation of any move, copy, or swap operations on - // individual elements. + // flat hash set. // // All iterators and references on the `flat_hash_set` remain valid, excepting // for the past-the-end iterator, which is invalidated. @@ -478,6 +477,21 @@ typename flat_hash_set<T, H, E, A>::size_type erase_if( return container_internal::EraseIf(pred, &c); } +// swap(flat_hash_set<>, flat_hash_set<>) +// +// Swaps the contents of two `flat_hash_set` containers. +// +// NOTE: we need to define this function template in order for +// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we +// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a +// derived-to-base conversion, whereas `std::swap` is a function template so +// `std::swap` will be preferred by compiler. +template <typename T, typename H, typename E, typename A> +void swap(flat_hash_set<T, H, E, A>& x, + flat_hash_set<T, H, E, A>& y) noexcept(noexcept(x.swap(y))) { + return x.swap(y); +} + namespace container_internal { // c_for_each_fast(flat_hash_set<>, Function) diff --git a/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h b/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h index 974b6521a0..cbf8bc2c1f 100644 --- a/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h +++ b/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h @@ -46,6 +46,7 @@ #include <utility> #include "absl/algorithm/algorithm.h" +#include "absl/base/attributes.h" #include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/optimization.h" @@ -67,7 +68,7 @@ ABSL_NAMESPACE_BEGIN // as a `std::vector`. The API of the `absl::InlinedVector` within this file is // designed to cover the same API footprint as covered by `std::vector`. template <typename T, size_t N, typename A = std::allocator<T>> -class InlinedVector { +class ABSL_ATTRIBUTE_WARN_UNUSED InlinedVector { static_assert(N > 0, "`absl::InlinedVector` requires an inlined capacity."); using Storage = inlined_vector_internal::Storage<T, N, A>; diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h b/contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h index c521f6122e..bbf54750f9 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h @@ -28,6 +28,15 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { +template <class Policy, class = void> +struct policy_trait_element_is_owner : std::false_type {}; + +template <class Policy> +struct policy_trait_element_is_owner< + Policy, + std::enable_if_t<!std::is_void<typename Policy::element_is_owner>::value>> + : Policy::element_is_owner {}; + // Defines how slots are initialized/destroyed/moved. template <class Policy, class = void> struct common_policy_traits { diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h b/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h index ba8e08a2d2..e703179701 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h @@ -17,6 +17,7 @@ #include <cassert> #include <cstddef> +#include <cstdint> #include <cstring> #include <memory> #include <new> diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h b/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h index 2f24e4616f..0bd0a1c4a4 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h @@ -83,8 +83,10 @@ using IsMoveAssignOk = std::is_move_assignable<ValueType<A>>; template <typename A> using IsSwapOk = absl::type_traits_internal::IsSwappable<ValueType<A>>; -template <typename A, bool IsTriviallyDestructible = - absl::is_trivially_destructible<ValueType<A>>::value> +template <typename A, + bool IsTriviallyDestructible = + absl::is_trivially_destructible<ValueType<A>>::value && + std::is_same<A, std::allocator<ValueType<A>>>::value> struct DestroyAdapter; template <typename A> diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/layout.h b/contrib/restricted/abseil-cpp/absl/container/internal/layout.h index 384929af49..f8b425c577 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/layout.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/layout.h @@ -306,7 +306,7 @@ constexpr size_t Max(size_t a, size_t b, Ts... rest) { template <class T> std::string TypeName() { std::string out; -#if ABSL_INTERNAL_HAS_RTTI +#ifdef ABSL_INTERNAL_HAS_RTTI absl::StrAppend(&out, "<", absl::debugging_internal::DemangleString(typeid(T).name()), ">"); diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc index 1cae03819d..8911aa3dc8 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc +++ b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc @@ -24,10 +24,12 @@ #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/endian.h" +#include "absl/base/internal/raw_logging.h" #include "absl/base/optimization.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hashtablez_sampler.h" #include "absl/hash/hash.h" +#include "absl/numeric/bits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -96,6 +98,16 @@ bool ShouldRehashForBugDetection(const ctrl_t* ctrl, size_t capacity) { RehashProbabilityConstant(); } +// Find a non-deterministic hash for single group table. +// Last two bits are used to find a position for a newly inserted element after +// resize. +// This function is mixing all bits of hash and control pointer to maximize +// entropy. +size_t SingleGroupTableH1(size_t hash, ctrl_t* control) { + return static_cast<size_t>(absl::popcount( + hash ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(control)))); +} + } // namespace GenerationType* EmptyGeneration() { @@ -135,7 +147,7 @@ size_t PrepareInsertAfterSoo(size_t hash, size_t slot_size, // index 1 occupied, so we need to insert either at index 0 or index 2. assert(HashSetResizeHelper::SooSlotIndex() == 1); PrepareInsertCommon(common); - const size_t offset = H1(hash, common.control()) & 2; + const size_t offset = SingleGroupTableH1(hash, common.control()) & 2; common.growth_info().OverwriteEmptyAsFull(); SetCtrlInSingleGroupTable(common, offset, H2(hash), slot_size); common.infoz().RecordInsert(hash, /*distance_from_desired=*/0); @@ -338,7 +350,7 @@ void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy, c.infoz().RecordClearedReservation(); c.infoz().RecordStorageChanged(0, soo_enabled ? SooCapacity() : 0); (*policy.dealloc)(c, policy); - c = soo_enabled ? CommonFields{soo_tag_t{}} : CommonFields{}; + c = soo_enabled ? CommonFields{soo_tag_t{}} : CommonFields{non_soo_tag_t{}}; } } @@ -346,124 +358,124 @@ void HashSetResizeHelper::GrowIntoSingleGroupShuffleControlBytes( ctrl_t* __restrict new_ctrl, size_t new_capacity) const { assert(is_single_group(new_capacity)); constexpr size_t kHalfWidth = Group::kWidth / 2; - constexpr size_t kQuarterWidth = Group::kWidth / 4; - assert(old_capacity_ < kHalfWidth); - static_assert(sizeof(uint64_t) >= kHalfWidth, - "Group size is too large. The ctrl bytes for half a group must " - "fit into a uint64_t for this implementation."); - static_assert(sizeof(uint64_t) <= Group::kWidth, - "Group size is too small. The ctrl bytes for a group must " - "cover a uint64_t for this implementation."); - - const size_t half_old_capacity = old_capacity_ / 2; - - // NOTE: operations are done with compile time known size = kHalfWidth. + ABSL_ASSUME(old_capacity_ < kHalfWidth); + ABSL_ASSUME(old_capacity_ > 0); + static_assert(Group::kWidth == 8 || Group::kWidth == 16, + "Group size is not supported."); + + // NOTE: operations are done with compile time known size = 8. // Compiler optimizes that into single ASM operation. - // Load the bytes from half_old_capacity + 1. This contains the last half of - // old_ctrl bytes, followed by the sentinel byte, and then the first half of - // the cloned bytes. This effectively shuffles the control bytes. - uint64_t copied_bytes = 0; - copied_bytes = - absl::little_endian::Load64(old_ctrl() + half_old_capacity + 1); + // Load the bytes from old_capacity. This contains + // - the sentinel byte + // - all the old control bytes + // - the rest is filled with kEmpty bytes + // Example: + // old_ctrl = 012S012EEEEEEEEE... + // copied_bytes = S012EEEE + uint64_t copied_bytes = + absl::little_endian::Load64(old_ctrl() + old_capacity_); // We change the sentinel byte to kEmpty before storing to both the start of // the new_ctrl, and past the end of the new_ctrl later for the new cloned // bytes. Note that this is faster than setting the sentinel byte to kEmpty // after the copy directly in new_ctrl because we are limited on store // bandwidth. - constexpr uint64_t kEmptyXorSentinel = + static constexpr uint64_t kEmptyXorSentinel = static_cast<uint8_t>(ctrl_t::kEmpty) ^ static_cast<uint8_t>(ctrl_t::kSentinel); - const uint64_t mask_convert_old_sentinel_to_empty = - kEmptyXorSentinel << (half_old_capacity * 8); - copied_bytes ^= mask_convert_old_sentinel_to_empty; - - // Copy second half of bytes to the beginning. This correctly sets the bytes - // [0, old_capacity]. We potentially copy more bytes in order to have compile - // time known size. Mirrored bytes from the old_ctrl() will also be copied. In - // case of old_capacity_ == 3, we will copy 1st element twice. - // Examples: - // (old capacity = 1) - // old_ctrl = 0S0EEEEEEE... - // new_ctrl = E0EEEEEE??... - // - // (old capacity = 3) - // old_ctrl = 012S012EEEEE... - // new_ctrl = 12E012EE????... - // - // (old capacity = 7) - // old_ctrl = 0123456S0123456EE... - // new_ctrl = 456E0123?????????... - absl::little_endian::Store64(new_ctrl, copied_bytes); - // Set the space [old_capacity + 1, new_capacity] to empty as these bytes will - // not be written again. This is safe because - // NumControlBytes = new_capacity + kWidth and new_capacity >= - // old_capacity+1. - // Examples: - // (old_capacity = 3, new_capacity = 15) - // new_ctrl = 12E012EE?????????????...?? - // *new_ctrl = 12E0EEEEEEEEEEEEEEEE?...?? - // position / S - // - // (old_capacity = 7, new_capacity = 15) - // new_ctrl = 456E0123?????????????????...?? - // *new_ctrl = 456E0123EEEEEEEEEEEEEEEE?...?? - // position / S - std::memset(new_ctrl + old_capacity_ + 1, static_cast<int8_t>(ctrl_t::kEmpty), - Group::kWidth); - - // Set the last kHalfWidth bytes to empty, to ensure the bytes all the way to - // the end are initialized. - // Examples: - // new_ctrl = 12E0EEEEEEEEEEEEEEEE?...??????? - // *new_ctrl = 12E0EEEEEEEEEEEEEEEE???EEEEEEEE - // position S / - // - // new_ctrl = 456E0123EEEEEEEEEEEEEEEE??????? - // *new_ctrl = 456E0123EEEEEEEEEEEEEEEEEEEEEEE - // position S / - std::memset(new_ctrl + NumControlBytes(new_capacity) - kHalfWidth, - static_cast<int8_t>(ctrl_t::kEmpty), kHalfWidth); + // Replace the first byte kSentinel with kEmpty. + // Resulting bytes will be shifted by one byte old control blocks. + // Example: + // old_ctrl = 012S012EEEEEEEEE... + // before = S012EEEE + // after = E012EEEE + copied_bytes ^= kEmptyXorSentinel; + + if (Group::kWidth == 8) { + // With group size 8, we can grow with two write operations. + assert(old_capacity_ < 8 && "old_capacity_ is too large for group size 8"); + absl::little_endian::Store64(new_ctrl, copied_bytes); + + static constexpr uint64_t kSentinal64 = + static_cast<uint8_t>(ctrl_t::kSentinel); + + // Prepend kSentinel byte to the beginning of copied_bytes. + // We have maximum 3 non-empty bytes at the beginning of copied_bytes for + // group size 8. + // Example: + // old_ctrl = 012S012EEEE + // before = E012EEEE + // after = SE012EEE + copied_bytes = (copied_bytes << 8) ^ kSentinal64; + absl::little_endian::Store64(new_ctrl + new_capacity, copied_bytes); + // Example for capacity 3: + // old_ctrl = 012S012EEEE + // After the first store: + // >! + // new_ctrl = E012EEEE??????? + // After the second store: + // >! + // new_ctrl = E012EEESE012EEE + return; + } - // Copy the first bytes to the end (starting at new_capacity +1) to set the - // cloned bytes. Note that we use the already copied bytes from old_ctrl here - // rather than copying from new_ctrl to avoid a Read-after-Write hazard, since - // new_ctrl was just written to. The first old_capacity-1 bytes are set - // correctly. Then there may be up to old_capacity bytes that need to be - // overwritten, and any remaining bytes will be correctly set to empty. This - // sets [new_capacity + 1, new_capacity +1 + old_capacity] correctly. - // Examples: - // new_ctrl = 12E0EEEEEEEEEEEEEEEE?...??????? - // *new_ctrl = 12E0EEEEEEEEEEEE12E012EEEEEEEEE - // position S/ - // - // new_ctrl = 456E0123EEEEEEEE?...???EEEEEEEE - // *new_ctrl = 456E0123EEEEEEEE456E0123EEEEEEE - // position S/ - absl::little_endian::Store64(new_ctrl + new_capacity + 1, copied_bytes); + assert(Group::kWidth == 16); - // Set The remaining bytes at the end past the cloned bytes to empty. The - // incorrectly set bytes are [new_capacity + old_capacity + 2, - // min(new_capacity + 1 + kHalfWidth, new_capacity + old_capacity + 2 + - // half_old_capacity)]. Taking the difference, we need to set min(kHalfWidth - - // (old_capacity + 1), half_old_capacity)]. Since old_capacity < kHalfWidth, - // half_old_capacity < kQuarterWidth, so we set kQuarterWidth beginning at - // new_capacity + old_capacity + 2 to kEmpty. - // Examples: - // new_ctrl = 12E0EEEEEEEEEEEE12E012EEEEEEEEE - // *new_ctrl = 12E0EEEEEEEEEEEE12E0EEEEEEEEEEE - // position S / - // - // new_ctrl = 456E0123EEEEEEEE456E0123EEEEEEE - // *new_ctrl = 456E0123EEEEEEEE456E0123EEEEEEE (no change) - // position S / - std::memset(new_ctrl + new_capacity + old_capacity_ + 2, - static_cast<int8_t>(ctrl_t::kEmpty), kQuarterWidth); - - // Finally, we set the new sentinel byte. + // Fill the second half of the main control bytes with kEmpty. + // For small capacity that may write into mirrored control bytes. + // It is fine as we will overwrite all the bytes later. + std::memset(new_ctrl + kHalfWidth, static_cast<int8_t>(ctrl_t::kEmpty), + kHalfWidth); + // Fill the second half of the mirrored control bytes with kEmpty. + std::memset(new_ctrl + new_capacity + kHalfWidth, + static_cast<int8_t>(ctrl_t::kEmpty), kHalfWidth); + // Copy the first half of the non-mirrored control bytes. + absl::little_endian::Store64(new_ctrl, copied_bytes); new_ctrl[new_capacity] = ctrl_t::kSentinel; + // Copy the first half of the mirrored control bytes. + absl::little_endian::Store64(new_ctrl + new_capacity + 1, copied_bytes); + + // Example for growth capacity 1->3: + // old_ctrl = 0S0EEEEEEEEEEEEEE + // new_ctrl at the end = E0ESE0EEEEEEEEEEEEE + // >! + // new_ctrl after 1st memset = ????????EEEEEEEE??? + // >! + // new_ctrl after 2nd memset = ????????EEEEEEEEEEE + // >! + // new_ctrl after 1st store = E0EEEEEEEEEEEEEEEEE + // new_ctrl after kSentinel = E0ESEEEEEEEEEEEEEEE + // >! + // new_ctrl after 2nd store = E0ESE0EEEEEEEEEEEEE + + // Example for growth capacity 3->7: + // old_ctrl = 012S012EEEEEEEEEEEE + // new_ctrl at the end = E012EEESE012EEEEEEEEEEE + // >! + // new_ctrl after 1st memset = ????????EEEEEEEE??????? + // >! + // new_ctrl after 2nd memset = ????????EEEEEEEEEEEEEEE + // >! + // new_ctrl after 1st store = E012EEEEEEEEEEEEEEEEEEE + // new_ctrl after kSentinel = E012EEESEEEEEEEEEEEEEEE + // >! + // new_ctrl after 2nd store = E012EEESE012EEEEEEEEEEE + + + // Example for growth capacity 7->15: + // old_ctrl = 0123456S0123456EEEEEEEE + // new_ctrl at the end = E0123456EEEEEEESE0123456EEEEEEE + // >! + // new_ctrl after 1st memset = ????????EEEEEEEE??????????????? + // >! + // new_ctrl after 2nd memset = ????????EEEEEEEE???????EEEEEEEE + // >! + // new_ctrl after 1st store = E0123456EEEEEEEE???????EEEEEEEE + // new_ctrl after kSentinel = E0123456EEEEEEES???????EEEEEEEE + // >! + // new_ctrl after 2nd store = E0123456EEEEEEESE0123456EEEEEEE } void HashSetResizeHelper::InitControlBytesAfterSoo(ctrl_t* new_ctrl, ctrl_t h2, @@ -480,15 +492,10 @@ void HashSetResizeHelper::InitControlBytesAfterSoo(ctrl_t* new_ctrl, ctrl_t h2, void HashSetResizeHelper::GrowIntoSingleGroupShuffleTransferableSlots( void* new_slots, size_t slot_size) const { - assert(old_capacity_ > 0); - const size_t half_old_capacity = old_capacity_ / 2; - + ABSL_ASSUME(old_capacity_ > 0); SanitizerUnpoisonMemoryRegion(old_slots(), slot_size * old_capacity_); - std::memcpy(new_slots, - SlotAddress(old_slots(), half_old_capacity + 1, slot_size), - slot_size * half_old_capacity); - std::memcpy(SlotAddress(new_slots, half_old_capacity + 1, slot_size), - old_slots(), slot_size * (half_old_capacity + 1)); + std::memcpy(SlotAddress(new_slots, 1, slot_size), old_slots(), + slot_size * old_capacity_); } void HashSetResizeHelper::GrowSizeIntoSingleGroupTransferable( @@ -588,6 +595,23 @@ const void* GetHashRefForEmptyHasher(const CommonFields& common) { return &common; } +FindInfo HashSetResizeHelper::FindFirstNonFullAfterResize(const CommonFields& c, + size_t old_capacity, + size_t hash) { + size_t new_capacity = c.capacity(); + if (!IsGrowingIntoSingleGroupApplicable(old_capacity, new_capacity)) { + return find_first_non_full(c, hash); + } + + // We put the new element either at the beginning or at the end of the table + // with approximately equal probability. + size_t offset = + SingleGroupTableH1(hash, c.control()) & 1 ? 0 : new_capacity - 1; + + assert(IsEmpty(c.control()[offset])); + return FindInfo{offset, 0}; +} + size_t PrepareInsertNonSoo(CommonFields& common, size_t hash, FindInfo target, const PolicyFunctions& policy) { // When there are no deleted slots in the table @@ -638,6 +662,10 @@ size_t PrepareInsertNonSoo(CommonFields& common, size_t hash, FindInfo target, return target.offset; } +void HashTableSizeOverflow() { + ABSL_RAW_LOG(FATAL, "Hash table size overflow"); +} + } // namespace container_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h index 7934b88c3e..79ccb596b7 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h @@ -41,12 +41,6 @@ // When heterogeneous lookup is disabled, only the explicit `key_type` overloads // exist. // -// find() also supports passing the hash explicitly: -// -// iterator find(const key_type& key, size_t hash); -// template <class U> -// iterator find(const U& key, size_t hash); -// // In addition the pointer to element and iterator stability guarantees are // weaker: all iterators and pointers are invalidated after a new element is // inserted. @@ -190,6 +184,7 @@ #include <cstddef> #include <cstdint> #include <cstring> +#include <functional> #include <initializer_list> #include <iterator> #include <limits> @@ -208,11 +203,14 @@ #include "absl/base/port.h" #include "absl/base/prefetch.h" #include "absl/container/internal/common.h" // IWYU pragma: export // for node_handle +#include "absl/container/internal/common_policy_traits.h" #include "absl/container/internal/compressed_tuple.h" #include "absl/container/internal/container_memory.h" +#include "absl/container/internal/hash_function_defaults.h" #include "absl/container/internal/hash_policy_traits.h" #include "absl/container/internal/hashtable_debug_hooks.h" #include "absl/container/internal/hashtablez_sampler.h" +#include "absl/hash/hash.h" #include "absl/memory/memory.h" #include "absl/meta/type_traits.h" #include "absl/numeric/bits.h" @@ -252,6 +250,15 @@ namespace container_internal { #define ABSL_SWISSTABLE_ENABLE_GENERATIONS #endif +#ifdef ABSL_SWISSTABLE_ASSERT +#error ABSL_SWISSTABLE_ASSERT cannot be directly set +#else +// We use this macro for assertions that users may see when the table is in an +// invalid state that sanitizers may help diagnose. +#define ABSL_SWISSTABLE_ASSERT(CONDITION) \ + assert((CONDITION) && "Try enabling sanitizers.") +#endif + // We use uint8_t so we don't need to worry about padding. using GenerationType = uint8_t; @@ -322,7 +329,7 @@ class probe_seq { // sequence and `mask` (usually the capacity of the table) as the mask to // apply to each value in the progression. probe_seq(size_t hash, size_t mask) { - assert(((mask + 1) & mask) == 0 && "not a mask"); + ABSL_SWISSTABLE_ASSERT(((mask + 1) & mask) == 0 && "not a mask"); mask_ = mask; offset_ = hash & mask_; } @@ -452,7 +459,7 @@ class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> { public: explicit BitMask(T mask) : Base(mask) { if (Shift == 3 && !NullifyBitsOnIteration) { - assert(this->mask_ == (this->mask_ & kMsbs8Bytes)); + ABSL_SWISSTABLE_ASSERT(this->mask_ == (this->mask_ & kMsbs8Bytes)); } } // BitMask is an iterator over the indices of its abstract bits. @@ -536,6 +543,18 @@ static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2), // See definition comment for why this is size 32. ABSL_DLL extern const ctrl_t kEmptyGroup[32]; +// We use these sentinel capacity values in debug mode to indicate different +// classes of bugs. +enum InvalidCapacity : size_t { + kAboveMaxValidCapacity = ~size_t{} - 100, + kReentrance, + kDestroyed, + + // These two must be last because we use `>= kMovedFrom` to mean moved-from. + kMovedFrom, + kSelfMovedFrom, +}; + // Returns a pointer to a control byte group that can be used by empty tables. inline ctrl_t* EmptyGroup() { // Const must be cast away here; no uses of this function will actually write @@ -687,10 +706,8 @@ struct GroupSse2Impl { // Returns a bitmask representing the positions of slots that match hash. BitMask<uint16_t, kWidth> Match(h2_t hash) const { auto match = _mm_set1_epi8(static_cast<char>(hash)); - BitMask<uint16_t, kWidth> result = BitMask<uint16_t, kWidth>(0); - result = BitMask<uint16_t, kWidth>( + return BitMask<uint16_t, kWidth>( static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl)))); - return result; } // Returns a bitmask representing the positions of empty slots. @@ -1105,19 +1122,20 @@ class GrowthInfo { // Overwrites single empty slot with a full slot. void OverwriteEmptyAsFull() { - assert(GetGrowthLeft() > 0); + ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() > 0); --growth_left_info_; } // Overwrites several empty slots with full slots. void OverwriteManyEmptyAsFull(size_t cnt) { - assert(GetGrowthLeft() >= cnt); + ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() >= cnt); growth_left_info_ -= cnt; } // Overwrites specified control element with full slot. void OverwriteControlAsFull(ctrl_t ctrl) { - assert(GetGrowthLeft() >= static_cast<size_t>(IsEmpty(ctrl))); + ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() >= + static_cast<size_t>(IsEmpty(ctrl))); growth_left_info_ -= static_cast<size_t>(IsEmpty(ctrl)); } @@ -1187,7 +1205,7 @@ class RawHashSetLayout { slot_offset_( (generation_offset_ + NumGenerationBytes() + slot_align - 1) & (~slot_align + 1)) { - assert(IsValidCapacity(capacity)); + ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity)); } // Returns the capacity of a table. @@ -1208,7 +1226,7 @@ class RawHashSetLayout { // Given the capacity of a table, computes the total size of the backing // array. size_t alloc_size(size_t slot_size) const { - ABSL_HARDENING_ASSERT( + ABSL_SWISSTABLE_ASSERT( slot_size <= ((std::numeric_limits<size_t>::max)() - slot_offset_) / capacity_); return slot_offset_ + capacity_ * slot_size; @@ -1235,6 +1253,10 @@ constexpr size_t SooCapacity() { return 1; } struct soo_tag_t {}; // Sentinel type to indicate SOO CommonFields construction with full size. struct full_soo_tag_t {}; +// Sentinel type to indicate non-SOO CommonFields construction. +struct non_soo_tag_t {}; +// Sentinel value to indicate an uninitialized CommonFields for use in swapping. +struct uninitialized_tag_t {}; // Suppress erroneous uninitialized memory errors on GCC. For example, GCC // thinks that the call to slot_array() in find_or_prepare_insert() is reading @@ -1316,10 +1338,13 @@ union HeapOrSoo { // of this state to helper functions as a single argument. class CommonFields : public CommonFieldsGenerationInfo { public: - CommonFields() : capacity_(0), size_(0), heap_or_soo_(EmptyGroup()) {} explicit CommonFields(soo_tag_t) : capacity_(SooCapacity()), size_(0) {} explicit CommonFields(full_soo_tag_t) : capacity_(SooCapacity()), size_(size_t{1} << HasInfozShift()) {} + explicit CommonFields(non_soo_tag_t) + : capacity_(0), size_(0), heap_or_soo_(EmptyGroup()) {} + // For use in swapping. + explicit CommonFields(uninitialized_tag_t) {} // Not copyable CommonFields(const CommonFields&) = delete; @@ -1331,7 +1356,8 @@ class CommonFields : public CommonFieldsGenerationInfo { template <bool kSooEnabled> static CommonFields CreateDefault() { - return kSooEnabled ? CommonFields{soo_tag_t{}} : CommonFields{}; + return kSooEnabled ? CommonFields{soo_tag_t{}} + : CommonFields{non_soo_tag_t{}}; } // The inline data for SOO is written on top of control_/slots_. @@ -1345,7 +1371,8 @@ class CommonFields : public CommonFieldsGenerationInfo { void set_control(ctrl_t* c) { heap_or_soo_.control() = c; } void* backing_array_start() const { // growth_info (and maybe infoz) is stored before control bytes. - assert(reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0); + ABSL_SWISSTABLE_ASSERT( + reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0); return control() - ControlOffset(has_infoz()); } @@ -1368,18 +1395,20 @@ class CommonFields : public CommonFieldsGenerationInfo { size_ = size_t{1} << HasInfozShift(); } void increment_size() { - assert(size() < capacity()); + ABSL_SWISSTABLE_ASSERT(size() < capacity()); size_ += size_t{1} << HasInfozShift(); } void decrement_size() { - assert(size() > 0); + ABSL_SWISSTABLE_ASSERT(size() > 0); size_ -= size_t{1} << HasInfozShift(); } // The total number of available slots. size_t capacity() const { return capacity_; } void set_capacity(size_t c) { - assert(c == 0 || IsValidCapacity(c)); + // We allow setting above the max valid capacity for debugging purposes. + ABSL_SWISSTABLE_ASSERT(c == 0 || IsValidCapacity(c) || + c > kAboveMaxValidCapacity); capacity_ = c; } @@ -1391,7 +1420,8 @@ class CommonFields : public CommonFieldsGenerationInfo { GrowthInfo& growth_info() { auto* gl_ptr = reinterpret_cast<GrowthInfo*>(control()) - 1; - assert(reinterpret_cast<uintptr_t>(gl_ptr) % alignof(GrowthInfo) == 0); + ABSL_SWISSTABLE_ASSERT( + reinterpret_cast<uintptr_t>(gl_ptr) % alignof(GrowthInfo) == 0); return *gl_ptr; } GrowthInfo growth_info() const { @@ -1411,7 +1441,7 @@ class CommonFields : public CommonFieldsGenerationInfo { : HashtablezInfoHandle(); } void set_infoz(HashtablezInfoHandle infoz) { - assert(has_infoz()); + ABSL_SWISSTABLE_ASSERT(has_infoz()); *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start()) = infoz; } @@ -1447,6 +1477,20 @@ class CommonFields : public CommonFieldsGenerationInfo { std::count(control(), control() + capacity(), ctrl_t::kDeleted)); } + // Helper to enable sanitizer mode validation to protect against reentrant + // calls during element constructor/destructor. + template <typename F> + void RunWithReentrancyGuard(F f) { +#ifdef NDEBUG + f(); + return; +#endif + const size_t cap = capacity(); + set_capacity(InvalidCapacity::kReentrance); + f(); + set_capacity(cap); + } + private: // We store the has_infoz bit in the lowest bit of size_. static constexpr size_t HasInfozShift() { return 1; } @@ -1457,8 +1501,8 @@ class CommonFields : public CommonFieldsGenerationInfo { // We can't assert that SOO is enabled because we don't have SooEnabled(), but // we assert what we can. void AssertInSooMode() const { - assert(capacity() == SooCapacity()); - assert(!has_infoz()); + ABSL_SWISSTABLE_ASSERT(capacity() == SooCapacity()); + ABSL_SWISSTABLE_ASSERT(!has_infoz()); } // The number of slots in the backing array. This is always 2^N-1 for an @@ -1484,7 +1528,7 @@ class raw_hash_set; // Returns the next valid capacity after `n`. inline size_t NextCapacity(size_t n) { - assert(IsValidCapacity(n) || n == 0); + ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n) || n == 0); return n * 2 + 1; } @@ -1509,6 +1553,9 @@ size_t MaxValidCapacity() { kSlotSize); } +// Use a non-inlined function to avoid code bloat. +[[noreturn]] void HashTableSizeOverflow(); + // General notes on capacity/growth methods below: // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an // average of two empty slots per group. @@ -1520,7 +1567,7 @@ size_t MaxValidCapacity() { // Given `capacity`, applies the load factor; i.e., it returns the maximum // number of values we should put into the table before a resizing rehash. inline size_t CapacityToGrowth(size_t capacity) { - assert(IsValidCapacity(capacity)); + ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity)); // `capacity*7/8` if (Group::kWidth == 8 && capacity == 7) { // x-x/8 does not work when x==7. @@ -1712,7 +1759,7 @@ inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b, "hashtable."); fail_if(true, "Comparing non-end() iterators from different hashtables."); } else { - ABSL_HARDENING_ASSERT( + ABSL_HARDENING_ASSERT_SLOW( AreItersFromSameContainer(ctrl_a, ctrl_b, slot_a, slot_b) && "Invalid iterator comparison. The iterators may be from different " "containers or the container might have rehashed or moved. Consider " @@ -1778,7 +1825,7 @@ inline FindInfo find_first_non_full(const CommonFields& common, size_t hash) { seq.index()}; } seq.next(); - assert(seq.index() <= common.capacity() && "full table!"); + ABSL_SWISSTABLE_ASSERT(seq.index() <= common.capacity() && "full table!"); } } @@ -1810,7 +1857,7 @@ inline void ResetCtrl(CommonFields& common, size_t slot_size) { // Sets sanitizer poisoning for slot corresponding to control byte being set. inline void DoSanitizeOnSetCtrl(const CommonFields& c, size_t i, ctrl_t h, size_t slot_size) { - assert(i < c.capacity()); + ABSL_SWISSTABLE_ASSERT(i < c.capacity()); auto* slot_i = static_cast<const char*>(c.slot_array()) + i * slot_size; if (IsFull(h)) { SanitizerUnpoisonMemoryRegion(slot_i, slot_size); @@ -1840,7 +1887,7 @@ inline void SetCtrl(const CommonFields& c, size_t i, h2_t h, size_t slot_size) { // setting the cloned control byte. inline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, ctrl_t h, size_t slot_size) { - assert(is_single_group(c.capacity())); + ABSL_SWISSTABLE_ASSERT(is_single_group(c.capacity())); DoSanitizeOnSetCtrl(c, i, h, slot_size); ctrl_t* ctrl = c.control(); ctrl[i] = h; @@ -1880,8 +1927,8 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline void IterateOverFullSlots( // Small tables capacity fits into portable group, where // GroupPortableImpl::MaskFull is more efficient for the // capacity <= GroupPortableImpl::kWidth. - assert(cap <= GroupPortableImpl::kWidth && - "unexpectedly large small capacity"); + ABSL_SWISSTABLE_ASSERT(cap <= GroupPortableImpl::kWidth && + "unexpectedly large small capacity"); static_assert(Group::kWidth >= GroupPortableImpl::kWidth, "unexpected group width"); // Group starts from kSentinel slot, so indices in the mask will @@ -1898,19 +1945,21 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline void IterateOverFullSlots( ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = remaining; while (remaining != 0) { for (uint32_t i : GroupFullEmptyOrDeleted(ctrl).MaskFull()) { - assert(IsFull(ctrl[i]) && "hash table was modified unexpectedly"); + ABSL_SWISSTABLE_ASSERT(IsFull(ctrl[i]) && + "hash table was modified unexpectedly"); cb(ctrl + i, slot + i); --remaining; } ctrl += Group::kWidth; slot += Group::kWidth; - assert((remaining == 0 || *(ctrl - 1) != ctrl_t::kSentinel) && - "hash table was modified unexpectedly"); + ABSL_SWISSTABLE_ASSERT( + (remaining == 0 || *(ctrl - 1) != ctrl_t::kSentinel) && + "hash table was modified unexpectedly"); } // NOTE: erasure of the current element is allowed in callback for // absl::erase_if specialization. So we use `>=`. - assert(original_size_for_assert >= c.size() && - "hash table was modified unexpectedly"); + ABSL_SWISSTABLE_ASSERT(original_size_for_assert >= c.size() && + "hash table was modified unexpectedly"); } template <typename CharAlloc> @@ -1965,34 +2014,16 @@ class HashSetResizeHelper { // `GrowSizeIntoSingleGroup*` in case `IsGrowingIntoSingleGroupApplicable`. // Falls back to `find_first_non_full` in case of big groups. static FindInfo FindFirstNonFullAfterResize(const CommonFields& c, - size_t old_capacity, - size_t hash) { - if (!IsGrowingIntoSingleGroupApplicable(old_capacity, c.capacity())) { - return find_first_non_full(c, hash); - } - // Find a location for the new element non-deterministically. - // Note that any position is correct. - // It will located at `half_old_capacity` or one of the other - // empty slots with approximately 50% probability each. - size_t offset = probe(c, hash).offset(); - - // Note that we intentionally use unsigned int underflow. - if (offset - (old_capacity + 1) >= old_capacity) { - // Offset fall on kSentinel or into the mostly occupied first half. - offset = old_capacity / 2; - } - assert(IsEmpty(c.control()[offset])); - return FindInfo{offset, 0}; - } + size_t old_capacity, size_t hash); HeapOrSoo& old_heap_or_soo() { return old_heap_or_soo_; } void* old_soo_data() { return old_heap_or_soo_.get_soo_data(); } ctrl_t* old_ctrl() const { - assert(!was_soo_); + ABSL_SWISSTABLE_ASSERT(!was_soo_); return old_heap_or_soo_.control(); } void* old_slots() const { - assert(!was_soo_); + ABSL_SWISSTABLE_ASSERT(!was_soo_); return old_heap_or_soo_.slot_array().get(); } size_t old_capacity() const { return old_capacity_; } @@ -2043,7 +2074,7 @@ class HashSetResizeHelper { ctrl_t soo_slot_h2, size_t key_size, size_t value_size) { - assert(c.capacity()); + ABSL_SWISSTABLE_ASSERT(c.capacity()); HashtablezInfoHandle infoz = ShouldSampleHashtablezInfo<Alloc>() ? SampleHashtablezInfo<SooEnabled>(SizeOfSlot, key_size, value_size, @@ -2100,21 +2131,20 @@ class HashSetResizeHelper { // 1. GrowIntoSingleGroupShuffleControlBytes was already called. template <class PolicyTraits, class Alloc> void GrowSizeIntoSingleGroup(CommonFields& c, Alloc& alloc_ref) { - assert(old_capacity_ < Group::kWidth / 2); - assert(IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity())); + ABSL_SWISSTABLE_ASSERT(old_capacity_ < Group::kWidth / 2); + ABSL_SWISSTABLE_ASSERT( + IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity())); using slot_type = typename PolicyTraits::slot_type; - assert(is_single_group(c.capacity())); + ABSL_SWISSTABLE_ASSERT(is_single_group(c.capacity())); - auto* new_slots = static_cast<slot_type*>(c.slot_array()); + auto* new_slots = static_cast<slot_type*>(c.slot_array()) + 1; auto* old_slots_ptr = static_cast<slot_type*>(old_slots()); + auto* old_ctrl_ptr = old_ctrl(); - size_t shuffle_bit = old_capacity_ / 2 + 1; - for (size_t i = 0; i < old_capacity_; ++i) { - if (IsFull(old_ctrl()[i])) { - size_t new_i = i ^ shuffle_bit; - SanitizerUnpoisonMemoryRegion(new_slots + new_i, sizeof(slot_type)); - PolicyTraits::transfer(&alloc_ref, new_slots + new_i, - old_slots_ptr + i); + for (size_t i = 0; i < old_capacity_; ++i, ++new_slots) { + if (IsFull(old_ctrl_ptr[i])) { + SanitizerUnpoisonMemoryRegion(new_slots, sizeof(slot_type)); + PolicyTraits::transfer(&alloc_ref, new_slots, old_slots_ptr + i); } } PoisonSingleGroupEmptySlots(c, sizeof(slot_type)); @@ -2156,27 +2186,25 @@ class HashSetResizeHelper { // 1. new_ctrl is allocated for new_capacity, // but not initialized. // 2. new_capacity is a single group. + // 3. old_capacity > 0. // // All elements are transferred into the first `old_capacity + 1` positions - // of the new_ctrl. Elements are rotated by `old_capacity_ / 2 + 1` positions - // in order to change an order and keep it non deterministic. - // Although rotation itself deterministic, position of the new added element - // will be based on `H1` and is not deterministic. + // of the new_ctrl. Elements are shifted by 1 in order to keep a space at the + // beginning for the new element. + // Position of the new added element will be based on `H1` and is not + // deterministic. // // Examples: // S = kSentinel, E = kEmpty // - // old_ctrl = SEEEEEEEE... - // new_ctrl = ESEEEEEEE... - // // old_ctrl = 0SEEEEEEE... // new_ctrl = E0ESE0EEE... // // old_ctrl = 012S012EEEEEEEEE... - // new_ctrl = 2E01EEES2E01EEE... + // new_ctrl = E012EEESE012EEE... // // old_ctrl = 0123456S0123456EEEEEEEEEEE... - // new_ctrl = 456E0123EEEEEES456E0123EEE... + // new_ctrl = E0123456EEEEEESE0123456EEE... void GrowIntoSingleGroupShuffleControlBytes(ctrl_t* new_ctrl, size_t new_capacity) const; @@ -2385,6 +2413,10 @@ class raw_hash_set { alignof(slot_type) <= alignof(HeapOrSoo); } + constexpr static size_t DefaultCapacity() { + return SooEnabled() ? SooCapacity() : 0; + } + // Whether `size` fits in the SOO capacity of this table. bool fits_in_soo(size_t size) const { return SooEnabled() && size <= SooCapacity(); @@ -2411,23 +2443,14 @@ class raw_hash_set { static_assert(std::is_lvalue_reference<reference>::value, "Policy::element() must return a reference"); - template <typename T> - struct SameAsElementReference - : std::is_same<typename std::remove_cv< - typename std::remove_reference<reference>::type>::type, - typename std::remove_cv< - typename std::remove_reference<T>::type>::type> {}; - // An enabler for insert(T&&): T must be convertible to init_type or be the // same as [cv] value_type [ref]. - // Note: we separate SameAsElementReference into its own type to avoid using - // reference unless we need to. MSVC doesn't seem to like it in some - // cases. template <class T> - using RequiresInsertable = typename std::enable_if< - absl::disjunction<std::is_convertible<T, init_type>, - SameAsElementReference<T>>::value, - int>::type; + using Insertable = absl::disjunction< + std::is_same<absl::remove_cvref_t<reference>, absl::remove_cvref_t<T>>, + std::is_convertible<T, init_type>>; + template <class T> + using IsNotBitField = std::is_pointer<T*>; // RequiresNotInit is a workaround for gcc prior to 7.1. // See https://godbolt.org/g/Y4xsUh. @@ -2438,6 +2461,17 @@ class raw_hash_set { template <class... Ts> using IsDecomposable = IsDecomposable<void, PolicyTraits, Hash, Eq, Ts...>; + template <class T> + using IsDecomposableAndInsertable = + IsDecomposable<std::enable_if_t<Insertable<T>::value, T>>; + + // Evaluates to true if an assignment from the given type would require the + // source object to remain alive for the life of the element. + template <class U> + using IsLifetimeBoundAssignmentFrom = std::conditional_t< + policy_trait_element_is_owner<Policy>::value, std::false_type, + type_traits_internal::IsLifetimeBoundAssignment<init_type, U>>; + public: static_assert(std::is_same<pointer, value_type*>::value, "Allocators with custom pointer types are not supported"); @@ -2622,9 +2656,11 @@ class raw_hash_set { const allocator_type& alloc = allocator_type()) : settings_(CommonFields::CreateDefault<SooEnabled()>(), hash, eq, alloc) { - if (bucket_count > (SooEnabled() ? SooCapacity() : 0)) { - ABSL_RAW_CHECK(bucket_count <= MaxValidCapacity<sizeof(slot_type)>(), - "Hash table size overflow"); + if (bucket_count > DefaultCapacity()) { + if (ABSL_PREDICT_FALSE(bucket_count > + MaxValidCapacity<sizeof(slot_type)>())) { + HashTableSizeOverflow(); + } resize(NormalizeCapacity(bucket_count)); } } @@ -2683,7 +2719,8 @@ class raw_hash_set { // absl::flat_hash_set<int> a, b{a}; // // RequiresNotInit<T> is a workaround for gcc prior to 7.1. - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> + template <class T, RequiresNotInit<T> = 0, + std::enable_if_t<Insertable<T>::value, int> = 0> raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0, const hasher& hash = hasher(), const key_equal& eq = key_equal(), const allocator_type& alloc = allocator_type()) @@ -2694,7 +2731,8 @@ class raw_hash_set { const allocator_type& alloc = allocator_type()) : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {} - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> + template <class T, RequiresNotInit<T> = 0, + std::enable_if_t<Insertable<T>::value, int> = 0> raw_hash_set(std::initializer_list<T> init, size_t bucket_count, const hasher& hash, const allocator_type& alloc) : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {} @@ -2703,7 +2741,8 @@ class raw_hash_set { const hasher& hash, const allocator_type& alloc) : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {} - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> + template <class T, RequiresNotInit<T> = 0, + std::enable_if_t<Insertable<T>::value, int> = 0> raw_hash_set(std::initializer_list<T> init, size_t bucket_count, const allocator_type& alloc) : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {} @@ -2712,7 +2751,8 @@ class raw_hash_set { const allocator_type& alloc) : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {} - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0> + template <class T, RequiresNotInit<T> = 0, + std::enable_if_t<Insertable<T>::value, int> = 0> raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc) : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {} @@ -2727,6 +2767,7 @@ class raw_hash_set { raw_hash_set(const raw_hash_set& that, const allocator_type& a) : raw_hash_set(GrowthToLowerboundCapacity(that.size()), that.hash_ref(), that.eq_ref(), a) { + that.AssertNotDebugCapacity(); const size_t size = that.size(); if (size == 0) { return; @@ -2734,14 +2775,14 @@ class raw_hash_set { // We don't use `that.is_soo()` here because `that` can have non-SOO // capacity but have a size that fits into SOO capacity. if (fits_in_soo(size)) { - assert(size == 1); + ABSL_SWISSTABLE_ASSERT(size == 1); common().set_full_soo(); emplace_at(soo_iterator(), *that.begin()); const HashtablezInfoHandle infoz = try_sample_soo(); if (infoz.IsSampled()) resize_with_soo_infoz(infoz); return; } - assert(!that.is_soo()); + ABSL_SWISSTABLE_ASSERT(!that.is_soo()); const size_t cap = capacity(); // Note about single group tables: // 1. It is correct to have any order of elements. @@ -2773,7 +2814,8 @@ class raw_hash_set { offset = (offset + shift) & cap; } const h2_t h2 = static_cast<h2_t>(*that_ctrl); - assert( // We rely that hash is not changed for small tables. + ABSL_SWISSTABLE_ASSERT( // We rely that hash is not changed for small + // tables. H2(PolicyTraits::apply(HashElement{hash_ref()}, PolicyTraits::element(that_slot))) == h2 && "hash function value changed unexpectedly during the copy"); @@ -2797,7 +2839,6 @@ class raw_hash_set { : // Hash, equality and allocator are copied instead of moved because // `that` must be left valid. If Hash is std::function<Key>, moving it // would create a nullptr functor that cannot be called. - // TODO(b/296061262): move instead of copying hash/eq/alloc. // Note: we avoid using exchange for better generated code. settings_(PolicyTraits::transfer_uses_memcpy() || !that.is_full_soo() ? std::move(that.common()) @@ -2807,7 +2848,7 @@ class raw_hash_set { transfer(soo_slot(), that.soo_slot()); } that.common() = CommonFields::CreateDefault<SooEnabled()>(); - maybe_increment_generation_or_rehash_on_move(); + annotate_for_bug_detection_on_move(that); } raw_hash_set(raw_hash_set&& that, const allocator_type& a) @@ -2815,13 +2856,14 @@ class raw_hash_set { that.eq_ref(), a) { if (a == that.alloc_ref()) { swap_common(that); - maybe_increment_generation_or_rehash_on_move(); + annotate_for_bug_detection_on_move(that); } else { move_elements_allocs_unequal(std::move(that)); } } raw_hash_set& operator=(const raw_hash_set& that) { + that.AssertNotDebugCapacity(); if (ABSL_PREDICT_FALSE(this == &that)) return *this; constexpr bool propagate_alloc = AllocTraits::propagate_on_container_copy_assignment::value; @@ -2846,7 +2888,12 @@ class raw_hash_set { typename AllocTraits::propagate_on_container_move_assignment()); } - ~raw_hash_set() { destructor_impl(); } + ~raw_hash_set() { + destructor_impl(); +#ifndef NDEBUG + common().set_capacity(InvalidCapacity::kDestroyed); +#endif + } iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { if (ABSL_PREDICT_FALSE(empty())) return end(); @@ -2854,10 +2901,11 @@ class raw_hash_set { iterator it = {control(), common().slots_union(), common().generation_ptr()}; it.skip_empty_or_deleted(); - assert(IsFull(*it.control())); + ABSL_SWISSTABLE_ASSERT(IsFull(*it.control())); return it; } iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { + AssertNotDebugCapacity(); return iterator(common().generation_ptr()); } @@ -2865,7 +2913,7 @@ class raw_hash_set { return const_cast<raw_hash_set*>(this)->begin(); } const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return iterator(common().generation_ptr()); + return const_cast<raw_hash_set*>(this)->end(); } const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return begin(); @@ -2873,13 +2921,16 @@ class raw_hash_set { const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); } bool empty() const { return !size(); } - size_t size() const { return common().size(); } + size_t size() const { + AssertNotDebugCapacity(); + return common().size(); + } size_t capacity() const { const size_t cap = common().capacity(); - // Compiler complains when using functions in assume so use local variables. - ABSL_ATTRIBUTE_UNUSED static constexpr bool kEnabled = SooEnabled(); - ABSL_ATTRIBUTE_UNUSED static constexpr size_t kCapacity = SooCapacity(); - ABSL_ASSUME(!kEnabled || cap >= kCapacity); + // Compiler complains when using functions in ASSUME so use local variable. + ABSL_ATTRIBUTE_UNUSED static constexpr size_t kDefaultCapacity = + DefaultCapacity(); + ABSL_ASSUME(cap >= kDefaultCapacity); return cap; } size_t max_size() const { @@ -2887,6 +2938,11 @@ class raw_hash_set { } ABSL_ATTRIBUTE_REINITIALIZES void clear() { + if (SwisstableGenerationsEnabled() && + capacity() >= InvalidCapacity::kMovedFrom) { + common().set_capacity(DefaultCapacity()); + } + AssertNotDebugCapacity(); // Iterating over this container is O(bucket_count()). When bucket_count() // is much greater than size(), iteration becomes prohibitively expensive. // For clear() it is more important to reuse the allocated array when the @@ -2914,15 +2970,26 @@ class raw_hash_set { // // flat_hash_map<std::string, int> m; // m.insert(std::make_pair("abc", 42)); - // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc - // bug. - template <class T, RequiresInsertable<T> = 0, class T2 = T, - typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0, - T* = nullptr> + template <class T, + std::enable_if_t<IsDecomposableAndInsertable<T>::value && + IsNotBitField<T>::value && + !IsLifetimeBoundAssignmentFrom<T>::value, + int> = 0> std::pair<iterator, bool> insert(T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND { return emplace(std::forward<T>(value)); } + template <class T, + std::enable_if_t<IsDecomposableAndInsertable<T>::value && + IsNotBitField<T>::value && + IsLifetimeBoundAssignmentFrom<T>::value, + int> = 0> + std::pair<iterator, bool> insert( + T&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return emplace(std::forward<T>(value)); + } + // This overload kicks in when the argument is a bitfield or an lvalue of // insertable and decomposable type. // @@ -2934,13 +3001,23 @@ class raw_hash_set { // const char* p = "hello"; // s.insert(p); // - template < - class T, RequiresInsertable<const T&> = 0, - typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0> + template <class T, std::enable_if_t< + IsDecomposableAndInsertable<const T&>::value && + !IsLifetimeBoundAssignmentFrom<const T&>::value, + int> = 0> std::pair<iterator, bool> insert(const T& value) ABSL_ATTRIBUTE_LIFETIME_BOUND { return emplace(value); } + template <class T, + std::enable_if_t<IsDecomposableAndInsertable<const T&>::value && + IsLifetimeBoundAssignmentFrom<const T&>::value, + int> = 0> + std::pair<iterator, bool> insert( + const T& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return emplace(value); + } // This overload kicks in when the argument is an rvalue of init_type. Its // purpose is to handle brace-init-list arguments. @@ -2948,22 +3025,43 @@ class raw_hash_set { // flat_hash_map<std::string, int> s; // s.insert({"abc", 42}); std::pair<iterator, bool> insert(init_type&& value) - ABSL_ATTRIBUTE_LIFETIME_BOUND { + ABSL_ATTRIBUTE_LIFETIME_BOUND +#if __cplusplus >= 202002L + requires(!IsLifetimeBoundAssignmentFrom<init_type>::value) +#endif + { + return emplace(std::move(value)); + } +#if __cplusplus >= 202002L + std::pair<iterator, bool> insert( + init_type&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)) + ABSL_ATTRIBUTE_LIFETIME_BOUND + requires(IsLifetimeBoundAssignmentFrom<init_type>::value) + { return emplace(std::move(value)); } +#endif - // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc - // bug. - template <class T, RequiresInsertable<T> = 0, class T2 = T, - typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0, - T* = nullptr> + template <class T, + std::enable_if_t<IsDecomposableAndInsertable<T>::value && + IsNotBitField<T>::value && + !IsLifetimeBoundAssignmentFrom<T>::value, + int> = 0> iterator insert(const_iterator, T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND { return insert(std::forward<T>(value)).first; } + template <class T, + std::enable_if_t<IsDecomposableAndInsertable<T>::value && + IsNotBitField<T>::value && + IsLifetimeBoundAssignmentFrom<T>::value, + int> = 0> + iterator insert(const_iterator, T&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY( + this)) ABSL_ATTRIBUTE_LIFETIME_BOUND { + return insert(std::forward<T>(value)).first; + } - template < - class T, RequiresInsertable<const T&> = 0, - typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0> + template <class T, std::enable_if_t< + IsDecomposableAndInsertable<const T&>::value, int> = 0> iterator insert(const_iterator, const T& value) ABSL_ATTRIBUTE_LIFETIME_BOUND { return insert(value).first; @@ -2979,7 +3077,8 @@ class raw_hash_set { for (; first != last; ++first) emplace(*first); } - template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0> + template <class T, RequiresNotInit<T> = 0, + std::enable_if_t<Insertable<const T&>::value, int> = 0> void insert(std::initializer_list<T> ilist) { insert(ilist.begin(), ilist.end()); } @@ -3018,8 +3117,8 @@ class raw_hash_set { // flat_hash_map<std::string, std::string> m = {{"abc", "def"}}; // // Creates no std::string copies and makes no heap allocations. // m.emplace("abc", "xyz"); - template <class... Args, typename std::enable_if< - IsDecomposable<Args...>::value, int>::type = 0> + template <class... Args, + std::enable_if_t<IsDecomposable<Args...>::value, int> = 0> std::pair<iterator, bool> emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { return PolicyTraits::apply(EmplaceDecomposable{*this}, @@ -3029,8 +3128,8 @@ class raw_hash_set { // This overload kicks in if we cannot deduce the key from args. It constructs // value_type unconditionally and then either moves it into the table or // destroys. - template <class... Args, typename std::enable_if< - !IsDecomposable<Args...>::value, int>::type = 0> + template <class... Args, + std::enable_if_t<!IsDecomposable<Args...>::value, int> = 0> std::pair<iterator, bool> emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { alignas(slot_type) unsigned char raw[sizeof(slot_type)]; @@ -3081,7 +3180,7 @@ class raw_hash_set { public: template <class... Args> void operator()(Args&&... args) const { - assert(*slot_); + ABSL_SWISSTABLE_ASSERT(*slot_); PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...); *slot_ = nullptr; } @@ -3100,7 +3199,7 @@ class raw_hash_set { if (res.second) { slot_type* slot = res.first.slot(); std::forward<F>(f)(constructor(&alloc_ref(), &slot)); - assert(!slot); + ABSL_SWISSTABLE_ASSERT(!slot); } return res.first; } @@ -3122,24 +3221,16 @@ class raw_hash_set { return 1; } - // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`, - // this method returns void to reduce algorithmic complexity to O(1). The - // iterator is invalidated, so any increment should be done before calling - // erase. In order to erase while iterating across a map, use the following - // idiom (which also works for some standard containers): - // - // for (auto it = m.begin(), end = m.end(); it != end;) { - // // `erase()` will invalidate `it`, so advance `it` first. - // auto copy_it = it++; - // if (<pred>) { - // m.erase(copy_it); - // } - // } + // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`, + // this method returns void to reduce algorithmic complexity to O(1). The + // iterator is invalidated so any increment should be done before calling + // erase (e.g. `erase(it++)`). void erase(const_iterator cit) { erase(cit.inner_); } // This overload is necessary because otherwise erase<K>(const K&) would be // a better match if non-const iterator is passed as an argument. void erase(iterator it) { + AssertNotDebugCapacity(); AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()"); destroy(it.slot()); if (is_soo()) { @@ -3151,6 +3242,7 @@ class raw_hash_set { iterator erase(const_iterator first, const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND { + AssertNotDebugCapacity(); // We check for empty first because ClearBackingArray requires that // capacity() > 0 as a precondition. if (empty()) return end(); @@ -3180,6 +3272,8 @@ class raw_hash_set { // If the element already exists in `this`, it is left unmodified in `src`. template <typename H, typename E> void merge(raw_hash_set<Policy, H, E, Alloc>& src) { // NOLINT + AssertNotDebugCapacity(); + src.AssertNotDebugCapacity(); assert(this != &src); // Returns whether insertion took place. const auto insert_slot = [this](slot_type* src_slot) { @@ -3206,6 +3300,7 @@ class raw_hash_set { } node_type extract(const_iterator position) { + AssertNotDebugCapacity(); AssertIsFull(position.control(), position.inner_.generation(), position.inner_.generation_ptr(), "extract()"); auto node = CommonAccess::Transfer<node_type>(alloc_ref(), position.slot()); @@ -3217,9 +3312,8 @@ class raw_hash_set { return node; } - template < - class K = key_type, - typename std::enable_if<!std::is_same<K, iterator>::value, int>::type = 0> + template <class K = key_type, + std::enable_if_t<!std::is_same<K, iterator>::value, int> = 0> node_type extract(const key_arg<K>& key) { auto it = find(key); return it == end() ? node_type() : extract(const_iterator{it}); @@ -3229,6 +3323,8 @@ class raw_hash_set { IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() && IsNoThrowSwappable<allocator_type>( typename AllocTraits::propagate_on_container_swap{})) { + AssertNotDebugCapacity(); + that.AssertNotDebugCapacity(); using std::swap; swap_common(that); swap(hash_ref(), that.hash_ref()); @@ -3254,7 +3350,7 @@ class raw_hash_set { resize(kInitialSampledCapacity); } // This asserts that we didn't lose sampling coverage in `resize`. - assert(infoz().IsSampled()); + ABSL_SWISSTABLE_ASSERT(infoz().IsSampled()); return; } alignas(slot_type) unsigned char slot_space[sizeof(slot_type)]; @@ -3273,8 +3369,9 @@ class raw_hash_set { auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size())); // n == 0 unconditionally rehashes as per the standard. if (n == 0 || m > cap) { - ABSL_RAW_CHECK(m <= MaxValidCapacity<sizeof(slot_type)>(), - "Hash table size overflow"); + if (ABSL_PREDICT_FALSE(m > MaxValidCapacity<sizeof(slot_type)>())) { + HashTableSizeOverflow(); + } resize(m); // This is after resize, to ensure that we have completed the allocation @@ -3287,7 +3384,9 @@ class raw_hash_set { const size_t max_size_before_growth = is_soo() ? SooCapacity() : size() + growth_left(); if (n > max_size_before_growth) { - ABSL_RAW_CHECK(n <= max_size(), "Hash table size overflow"); + if (ABSL_PREDICT_FALSE(n > max_size())) { + HashTableSizeOverflow(); + } size_t m = GrowthToLowerboundCapacity(n); resize(NormalizeCapacity(m)); @@ -3320,7 +3419,7 @@ class raw_hash_set { // specific benchmarks indicating its importance. template <class K = key_type> void prefetch(const key_arg<K>& key) const { - if (SooEnabled() ? is_soo() : capacity() == 0) return; + if (capacity() == DefaultCapacity()) return; (void)key; // Avoid probing if we won't be able to prefetch the addresses received. #ifdef ABSL_HAVE_PREFETCH @@ -3331,32 +3430,27 @@ class raw_hash_set { #endif // ABSL_HAVE_PREFETCH } - // The API of find() has two extensions. - // - // 1. The hash can be passed by the user. It must be equal to the hash of the - // key. - // - // 2. The type of the key argument doesn't have to be key_type. This is so - // called heterogeneous key support. template <class K = key_type> + ABSL_DEPRECATE_AND_INLINE() iterator find(const key_arg<K>& key, - size_t hash) ABSL_ATTRIBUTE_LIFETIME_BOUND { - AssertHashEqConsistent(key); - if (is_soo()) return find_soo(key); - return find_non_soo(key, hash); + size_t) ABSL_ATTRIBUTE_LIFETIME_BOUND { + return find(key); } + // The API of find() has one extension: the type of the key argument doesn't + // have to be key_type. This is so called heterogeneous key support. template <class K = key_type> iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { - AssertHashEqConsistent(key); + AssertOnFind(key); if (is_soo()) return find_soo(key); prefetch_heap_block(); return find_non_soo(key, hash_ref()(key)); } template <class K = key_type> + ABSL_DEPRECATE_AND_INLINE() const_iterator find(const key_arg<K>& key, - size_t hash) const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_cast<raw_hash_set*>(this)->find(key, hash); + size_t) const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return find(key); } template <class K = key_type> const_iterator find(const key_arg<K>& key) const @@ -3408,7 +3502,16 @@ class raw_hash_set { if (outer->capacity() > inner->capacity()) std::swap(outer, inner); for (const value_type& elem : *outer) { auto it = PolicyTraits::apply(FindElement{*inner}, elem); - if (it == inner->end() || !(*it == elem)) return false; + if (it == inner->end()) return false; + // Note: we used key_equal to check for key equality in FindElement, but + // we may need to do an additional comparison using + // value_type::operator==. E.g. the keys could be equal and the + // mapped_types could be unequal in a map or even in a set, key_equal + // could ignore some fields that aren't ignored by operator==. + static constexpr bool kKeyEqIsValueEq = + std::is_same<key_type, value_type>::value && + std::is_same<key_equal, hash_default_eq<key_type>>::value; + if (!kKeyEqIsValueEq && !(*it == elem)) return false; } return true; } @@ -3492,23 +3595,26 @@ class raw_hash_set { slot_type&& slot; }; - // TODO(b/303305702): re-enable reentrant validation. template <typename... Args> inline void construct(slot_type* slot, Args&&... args) { - PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...); + common().RunWithReentrancyGuard([&] { + PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...); + }); } inline void destroy(slot_type* slot) { - PolicyTraits::destroy(&alloc_ref(), slot); + common().RunWithReentrancyGuard( + [&] { PolicyTraits::destroy(&alloc_ref(), slot); }); } inline void transfer(slot_type* to, slot_type* from) { - PolicyTraits::transfer(&alloc_ref(), to, from); + common().RunWithReentrancyGuard( + [&] { PolicyTraits::transfer(&alloc_ref(), to, from); }); } // TODO(b/289225379): consider having a helper class that has the impls for // SOO functionality. template <class K = key_type> iterator find_soo(const key_arg<K>& key) { - assert(is_soo()); + ABSL_SWISSTABLE_ASSERT(is_soo()); return empty() || !PolicyTraits::apply(EqualElement<K>{key, eq_ref()}, PolicyTraits::element(soo_slot())) ? end() @@ -3517,7 +3623,7 @@ class raw_hash_set { template <class K = key_type> iterator find_non_soo(const key_arg<K>& key, size_t hash) { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); auto seq = probe(common(), hash); const ctrl_t* ctrl = control(); while (true) { @@ -3530,7 +3636,7 @@ class raw_hash_set { } if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return end(); seq.next(); - assert(seq.index() <= capacity() && "full table!"); + ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity() && "full table!"); } } @@ -3538,14 +3644,14 @@ class raw_hash_set { // insertion into an empty SOO table and in copy construction when the size // can fit in SOO capacity. inline HashtablezInfoHandle try_sample_soo() { - assert(is_soo()); + ABSL_SWISSTABLE_ASSERT(is_soo()); if (!ShouldSampleHashtablezInfo<CharAlloc>()) return HashtablezInfoHandle{}; return Sample(sizeof(slot_type), sizeof(key_type), sizeof(value_type), SooCapacity()); } inline void destroy_slots() { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); if (PolicyTraits::template destroy_is_trivial<Alloc>()) return; IterateOverFullSlots( common(), slot_array(), @@ -3554,7 +3660,7 @@ class raw_hash_set { } inline void dealloc() { - assert(capacity() != 0); + ABSL_SWISSTABLE_ASSERT(capacity() != 0); // Unpoison before returning the memory to the allocator. SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * capacity()); infoz().Unregister(); @@ -3564,6 +3670,10 @@ class raw_hash_set { } inline void destructor_impl() { + if (SwisstableGenerationsEnabled() && + capacity() >= InvalidCapacity::kMovedFrom) { + return; + } if (capacity() == 0) return; if (is_soo()) { if (!empty()) { @@ -3580,7 +3690,7 @@ class raw_hash_set { // This merely updates the pertinent control byte. This can be used in // conjunction with Policy::transfer to move the object to another place. void erase_meta_only(const_iterator it) { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); EraseMetaOnly(common(), static_cast<size_t>(it.control() - control()), sizeof(slot_type)); } @@ -3606,7 +3716,7 @@ class raw_hash_set { // SOO tables, since they need to switch from SOO to heap in order to // store the infoz. void resize_with_soo_infoz(HashtablezInfoHandle forced_infoz) { - assert(forced_infoz.IsSampled()); + ABSL_SWISSTABLE_ASSERT(forced_infoz.IsSampled()); raw_hash_set::resize_impl(common(), NextCapacity(SooCapacity()), forced_infoz); } @@ -3617,8 +3727,8 @@ class raw_hash_set { CommonFields& common, size_t new_capacity, HashtablezInfoHandle forced_infoz) { raw_hash_set* set = reinterpret_cast<raw_hash_set*>(&common); - assert(IsValidCapacity(new_capacity)); - assert(!set->fits_in_soo(new_capacity)); + ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity)); + ABSL_SWISSTABLE_ASSERT(!set->fits_in_soo(new_capacity)); const bool was_soo = set->is_soo(); const bool had_soo_slot = was_soo && !set->empty(); const ctrl_t soo_slot_h2 = @@ -3653,7 +3763,7 @@ class raw_hash_set { // InitializeSlots did all the work including infoz().RecordRehash(). return; } - assert(resize_helper.old_capacity() > 0); + ABSL_SWISSTABLE_ASSERT(resize_helper.old_capacity() > 0); // Nothing more to do in this case. if (was_soo && !had_soo_slot) return; @@ -3706,15 +3816,18 @@ class raw_hash_set { static slot_type* to_slot(void* buf) { return static_cast<slot_type*>(buf); } // Requires that lhs does not have a full SOO slot. - static void move_common(bool that_is_full_soo, allocator_type& rhs_alloc, + static void move_common(bool rhs_is_full_soo, allocator_type& rhs_alloc, CommonFields& lhs, CommonFields&& rhs) { - if (PolicyTraits::transfer_uses_memcpy() || !that_is_full_soo) { + if (PolicyTraits::transfer_uses_memcpy() || !rhs_is_full_soo) { lhs = std::move(rhs); } else { lhs.move_non_heap_or_soo_fields(rhs); - // TODO(b/303305702): add reentrancy guard. - PolicyTraits::transfer(&rhs_alloc, to_slot(lhs.soo_data()), - to_slot(rhs.soo_data())); + rhs.RunWithReentrancyGuard([&] { + lhs.RunWithReentrancyGuard([&] { + PolicyTraits::transfer(&rhs_alloc, to_slot(lhs.soo_data()), + to_slot(rhs.soo_data())); + }); + }); } } @@ -3726,7 +3839,7 @@ class raw_hash_set { swap(common(), that.common()); return; } - CommonFields tmp = CommonFields::CreateDefault<SooEnabled()>(); + CommonFields tmp = CommonFields(uninitialized_tag_t{}); const bool that_is_full_soo = that.is_full_soo(); move_common(that_is_full_soo, that.alloc_ref(), tmp, std::move(that.common())); @@ -3734,8 +3847,17 @@ class raw_hash_set { move_common(that_is_full_soo, that.alloc_ref(), common(), std::move(tmp)); } - void maybe_increment_generation_or_rehash_on_move() { - if (!SwisstableGenerationsEnabled() || capacity() == 0 || is_soo()) { + void annotate_for_bug_detection_on_move( + ABSL_ATTRIBUTE_UNUSED raw_hash_set& that) { + // We only enable moved-from validation when generations are enabled (rather + // than using NDEBUG) to avoid issues in which NDEBUG is enabled in some + // translation units but not in others. + if (SwisstableGenerationsEnabled()) { + that.common().set_capacity(this == &that ? InvalidCapacity::kSelfMovedFrom + : InvalidCapacity::kMovedFrom); + } + if (!SwisstableGenerationsEnabled() || capacity() == DefaultCapacity() || + capacity() > kAboveMaxValidCapacity) { return; } common().increment_generation(); @@ -3751,13 +3873,12 @@ class raw_hash_set { destructor_impl(); move_common(that.is_full_soo(), that.alloc_ref(), common(), std::move(that.common())); - // TODO(b/296061262): move instead of copying hash/eq/alloc. hash_ref() = that.hash_ref(); eq_ref() = that.eq_ref(); CopyAlloc(alloc_ref(), that.alloc_ref(), std::integral_constant<bool, propagate_alloc>()); that.common() = CommonFields::CreateDefault<SooEnabled()>(); - maybe_increment_generation_or_rehash_on_move(); + annotate_for_bug_detection_on_move(that); return *this; } @@ -3771,7 +3892,7 @@ class raw_hash_set { } if (!that.is_soo()) that.dealloc(); that.common() = CommonFields::CreateDefault<SooEnabled()>(); - maybe_increment_generation_or_rehash_on_move(); + annotate_for_bug_detection_on_move(that); return *this; } @@ -3790,7 +3911,6 @@ class raw_hash_set { // We can't take over that's memory so we need to move each element. // While moving elements, this should have that's hash/eq so copy hash/eq // before moving elements. - // TODO(b/296061262): move instead of copying hash/eq. hash_ref() = that.hash_ref(); eq_ref() = that.eq_ref(); return move_elements_allocs_unequal(std::move(that)); @@ -3819,7 +3939,7 @@ class raw_hash_set { template <class K> std::pair<iterator, bool> find_or_prepare_insert_non_soo(const K& key) { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); prefetch_heap_block(); auto hash = hash_ref()(key); auto seq = probe(common(), hash); @@ -3842,16 +3962,57 @@ class raw_hash_set { true}; } seq.next(); - assert(seq.index() <= capacity() && "full table!"); + ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity() && "full table!"); } } protected: + // Asserts for correctness that we run on find/find_or_prepare_insert. + template <class K> + void AssertOnFind(ABSL_ATTRIBUTE_UNUSED const K& key) { + AssertHashEqConsistent(key); + AssertNotDebugCapacity(); + } + + // Asserts that the capacity is not a sentinel invalid value. + void AssertNotDebugCapacity() const { + if (ABSL_PREDICT_TRUE(capacity() < + InvalidCapacity::kAboveMaxValidCapacity)) { + return; + } + assert(capacity() != InvalidCapacity::kReentrance && + "Reentrant container access during element construction/destruction " + "is not allowed."); + assert(capacity() != InvalidCapacity::kDestroyed && + "Use of destroyed hash table."); + if (SwisstableGenerationsEnabled() && + ABSL_PREDICT_FALSE(capacity() >= InvalidCapacity::kMovedFrom)) { + if (capacity() == InvalidCapacity::kSelfMovedFrom) { + // If this log triggers, then a hash table was move-assigned to itself + // and then used again later without being reinitialized. + ABSL_RAW_LOG(FATAL, "Use of self-move-assigned hash table."); + } + ABSL_RAW_LOG(FATAL, "Use of moved-from hash table."); + } + } + // Asserts that hash and equal functors provided by the user are consistent, // meaning that `eq(k1, k2)` implies `hash(k1)==hash(k2)`. template <class K> - void AssertHashEqConsistent(ABSL_ATTRIBUTE_UNUSED const K& key) { -#ifndef NDEBUG + void AssertHashEqConsistent(const K& key) { +#ifdef NDEBUG + return; +#endif + // If the hash/eq functors are known to be consistent, then skip validation. + if (std::is_same<hasher, absl::container_internal::StringHash>::value && + std::is_same<key_equal, absl::container_internal::StringEq>::value) { + return; + } + if (std::is_scalar<key_type>::value && + std::is_same<hasher, absl::Hash<key_type>>::value && + std::is_same<key_equal, std::equal_to<key_type>>::value) { + return; + } if (empty()) return; const size_t hash_of_arg = hash_ref()(key); @@ -3863,21 +4024,8 @@ class raw_hash_set { const size_t hash_of_slot = PolicyTraits::apply(HashElement{hash_ref()}, element); - const bool is_hash_equal = hash_of_arg == hash_of_slot; - if (!is_hash_equal) { - // In this case, we're going to crash. Do a couple of other checks for - // idempotence issues. Recalculating hash/eq here is also convenient for - // debugging with gdb/lldb. - const size_t once_more_hash_arg = hash_ref()(key); - assert(hash_of_arg == once_more_hash_arg && "hash is not idempotent."); - const size_t once_more_hash_slot = - PolicyTraits::apply(HashElement{hash_ref()}, element); - assert(hash_of_slot == once_more_hash_slot && - "hash is not idempotent."); - const bool once_more_eq = - PolicyTraits::apply(EqualElement<K>{key, eq_ref()}, element); - assert(is_key_equal == once_more_eq && "equality is not idempotent."); - } + ABSL_ATTRIBUTE_UNUSED const bool is_hash_equal = + hash_of_arg == hash_of_slot; assert((!is_key_equal || is_hash_equal) && "eq(k1, k2) must imply that hash(k1) == hash(k2). " "hash/eq functors are inconsistent."); @@ -3890,7 +4038,6 @@ class raw_hash_set { // We only do validation for small tables so that it's constant time. if (capacity() > 16) return; IterateOverFullSlots(common(), slot_array(), assert_consistent); -#endif } // Attempts to find `key` in the table; if it isn't found, returns an iterator @@ -3898,7 +4045,7 @@ class raw_hash_set { // `key`'s H2. Returns a bool indicating whether an insertion can take place. template <class K> std::pair<iterator, bool> find_or_prepare_insert(const K& key) { - AssertHashEqConsistent(key); + AssertOnFind(key); if (is_soo()) return find_or_prepare_insert_soo(key); return find_or_prepare_insert_non_soo(key); } @@ -3942,16 +4089,16 @@ class raw_hash_set { // // See `CapacityToGrowth()`. size_t growth_left() const { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); return common().growth_left(); } GrowthInfo& growth_info() { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); return common().growth_info(); } GrowthInfo growth_info() const { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); return common().growth_info(); } @@ -3959,7 +4106,7 @@ class raw_hash_set { // cache misses. This is intended to overlap with execution of calculating the // hash for a key. void prefetch_heap_block() const { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__) __builtin_prefetch(control(), 0, 1); #endif @@ -3969,15 +4116,15 @@ class raw_hash_set { const CommonFields& common() const { return settings_.template get<0>(); } ctrl_t* control() const { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); return common().control(); } slot_type* slot_array() const { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); return static_cast<slot_type*>(common().slot_array()); } slot_type* soo_slot() { - assert(is_soo()); + ABSL_SWISSTABLE_ASSERT(is_soo()); return static_cast<slot_type*>(common().soo_data()); } const slot_type* soo_slot() const { @@ -3990,7 +4137,7 @@ class raw_hash_set { return const_cast<raw_hash_set*>(this)->soo_iterator(); } HashtablezInfoHandle infoz() { - assert(!is_soo()); + ABSL_SWISSTABLE_ASSERT(!is_soo()); return common().infoz(); } @@ -4039,7 +4186,7 @@ class raw_hash_set { (std::is_same<SlotAlloc, std::allocator<slot_type>>::value ? &DeallocateStandard<alignof(slot_type)> : &raw_hash_set::dealloc_fn), - &raw_hash_set::resize_impl, + &raw_hash_set::resize_impl }; return value; } @@ -4063,7 +4210,8 @@ struct HashtableFreeFunctionsAccess { if (c->is_soo()) { auto it = c->soo_iterator(); if (!pred(*it)) { - assert(c->size() == 1 && "hash table was modified unexpectedly"); + ABSL_SWISSTABLE_ASSERT(c->size() == 1 && + "hash table was modified unexpectedly"); return 0; } c->destroy(it.slot()); @@ -4083,8 +4231,9 @@ struct HashtableFreeFunctionsAccess { }); // NOTE: IterateOverFullSlots allow removal of the current element, so we // verify the size additionally here. - assert(original_size_for_assert - num_deleted == c->size() && - "hash table was modified unexpectedly"); + ABSL_SWISSTABLE_ASSERT(original_size_for_assert - num_deleted == + c->size() && + "hash table was modified unexpectedly"); return num_deleted; } @@ -4178,5 +4327,6 @@ ABSL_NAMESPACE_END #undef ABSL_SWISSTABLE_ENABLE_GENERATIONS #undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED #undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN +#undef ABSL_SWISSTABLE_ASSERT #endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_ diff --git a/contrib/restricted/abseil-cpp/absl/container/node_hash_map.h b/contrib/restricted/abseil-cpp/absl/container/node_hash_map.h index 5615e4966b..127c893739 100644 --- a/contrib/restricted/abseil-cpp/absl/container/node_hash_map.h +++ b/contrib/restricted/abseil-cpp/absl/container/node_hash_map.h @@ -120,7 +120,7 @@ class NodeHashMapPolicy; template <class Key, class Value, class Hash = DefaultHashContainerHash<Key>, class Eq = DefaultHashContainerEq<Key>, class Alloc = std::allocator<std::pair<const Key, Value>>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_map +class ABSL_ATTRIBUTE_OWNER node_hash_map : public absl::container_internal::raw_hash_map< absl::container_internal::NodeHashMapPolicy<Key, Value>, Hash, Eq, Alloc> { @@ -236,8 +236,13 @@ class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_map // Erases the element at `position` of the `node_hash_map`, returning // `void`. // - // NOTE: this return behavior is different than that of STL containers in - // general and `std::unordered_map` in particular. + // NOTE: Returning `void` in this case is different than that of STL + // containers in general and `std::unordered_map` in particular (which + // return an iterator to the element following the erased element). If that + // iterator is needed, simply post increment the iterator: + // + // map.erase(it++); + // // // iterator erase(const_iterator first, const_iterator last): // @@ -417,8 +422,7 @@ class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_map // node_hash_map::swap(node_hash_map& other) // // Exchanges the contents of this `node_hash_map` with those of the `other` - // node hash map, avoiding invocation of any move, copy, or swap operations on - // individual elements. + // node hash map. // // All iterators and references on the `node_hash_map` remain valid, excepting // for the past-the-end iterator, which is invalidated. @@ -558,6 +562,21 @@ typename node_hash_map<K, V, H, E, A>::size_type erase_if( return container_internal::EraseIf(pred, &c); } +// swap(node_hash_map<>, node_hash_map<>) +// +// Swaps the contents of two `node_hash_map` containers. +// +// NOTE: we need to define this function template in order for +// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we +// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a +// derived-to-base conversion, whereas `std::swap` is a function template so +// `std::swap` will be preferred by compiler. +template <typename K, typename V, typename H, typename E, typename A> +void swap(node_hash_map<K, V, H, E, A>& x, + node_hash_map<K, V, H, E, A>& y) noexcept(noexcept(x.swap(y))) { + return x.swap(y); +} + namespace container_internal { // c_for_each_fast(node_hash_map<>, Function) diff --git a/contrib/restricted/abseil-cpp/absl/container/node_hash_set.h b/contrib/restricted/abseil-cpp/absl/container/node_hash_set.h index 53435ae630..cffa50ec77 100644 --- a/contrib/restricted/abseil-cpp/absl/container/node_hash_set.h +++ b/contrib/restricted/abseil-cpp/absl/container/node_hash_set.h @@ -115,7 +115,7 @@ struct NodeHashSetPolicy; // } template <class T, class Hash = DefaultHashContainerHash<T>, class Eq = DefaultHashContainerEq<T>, class Alloc = std::allocator<T>> -class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_set +class ABSL_ATTRIBUTE_OWNER node_hash_set : public absl::container_internal::raw_hash_set< absl::container_internal::NodeHashSetPolicy<T>, Hash, Eq, Alloc> { using Base = typename node_hash_set::raw_hash_set; @@ -230,8 +230,13 @@ class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_set // Erases the element at `position` of the `node_hash_set`, returning // `void`. // - // NOTE: this return behavior is different than that of STL containers in - // general and `std::unordered_set` in particular. + // NOTE: Returning `void` in this case is different than that of STL + // containers in general and `std::unordered_map` in particular (which + // return an iterator to the element following the erased element). If that + // iterator is needed, simply post increment the iterator: + // + // map.erase(it++); + // // // iterator erase(const_iterator first, const_iterator last): // @@ -349,8 +354,7 @@ class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_set // node_hash_set::swap(node_hash_set& other) // // Exchanges the contents of this `node_hash_set` with those of the `other` - // node hash set, avoiding invocation of any move, copy, or swap operations on - // individual elements. + // node hash set. // // All iterators and references on the `node_hash_set` remain valid, excepting // for the past-the-end iterator, which is invalidated. @@ -467,6 +471,21 @@ typename node_hash_set<T, H, E, A>::size_type erase_if( return container_internal::EraseIf(pred, &c); } +// swap(node_hash_set<>, node_hash_set<>) +// +// Swaps the contents of two `node_hash_set` containers. +// +// NOTE: we need to define this function template in order for +// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we +// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a +// derived-to-base conversion, whereas `std::swap` is a function template so +// `std::swap` will be preferred by compiler. +template <typename T, typename H, typename E, typename A> +void swap(node_hash_set<T, H, E, A>& x, + node_hash_set<T, H, E, A>& y) noexcept(noexcept(x.swap(y))) { + return x.swap(y); +} + namespace container_internal { // c_for_each_fast(node_hash_set<>, Function) diff --git a/contrib/restricted/abseil-cpp/absl/container/ya.make b/contrib/restricted/abseil-cpp/absl/container/ya.make index 3d7b557c1b..f56079a755 100644 --- a/contrib/restricted/abseil-cpp/absl/container/ya.make +++ b/contrib/restricted/abseil-cpp/absl/container/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc index d7eedd1ca4..c59f773ea3 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc @@ -18,12 +18,21 @@ #include <string> #include "absl/base/config.h" +#include "absl/types/optional.h" // IWYU pragma: keep #if defined(__aarch64__) && defined(__linux__) #include <asm/hwcap.h> #include <sys/auxv.h> #endif +#if defined(__aarch64__) && defined(__APPLE__) +#if defined(__has_include) && __has_include(<arm/cpu_capabilities_public.h>) +#include <arm/cpu_capabilities_public.h> +#endif +#include <sys/sysctl.h> +#include <sys/types.h> +#endif + #if defined(_WIN32) || defined(_WIN64) #include <intrin.h> #endif @@ -269,8 +278,55 @@ CpuType GetCpuType() { } bool SupportsArmCRC32PMULL() { +#if defined(HWCAP_CRC32) && defined(HWCAP_PMULL) uint64_t hwcaps = getauxval(AT_HWCAP); return (hwcaps & HWCAP_CRC32) && (hwcaps & HWCAP_PMULL); +#else + return false; +#endif +} + +#elif defined(__aarch64__) && defined(__APPLE__) + +CpuType GetCpuType() { return CpuType::kUnknown; } + +template <typename T> +static absl::optional<T> ReadSysctlByName(const char* name) { + T val; + size_t val_size = sizeof(T); + int ret = sysctlbyname(name, &val, &val_size, nullptr, 0); + if (ret == -1) { + return absl::nullopt; + } + return val; +} + +bool SupportsArmCRC32PMULL() { + // Newer XNU kernels support querying all capabilities in a single + // sysctlbyname. +#if defined(CAP_BIT_CRC32) && defined(CAP_BIT_FEAT_PMULL) + static const absl::optional<uint64_t> caps = + ReadSysctlByName<uint64_t>("hw.optional.arm.caps"); + if (caps.has_value()) { + constexpr uint64_t kCrc32AndPmullCaps = + (uint64_t{1} << CAP_BIT_CRC32) | (uint64_t{1} << CAP_BIT_FEAT_PMULL); + return (*caps & kCrc32AndPmullCaps) == kCrc32AndPmullCaps; + } +#endif + + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3915619 + static const absl::optional<int> armv8_crc32 = + ReadSysctlByName<int>("hw.optional.armv8_crc32"); + if (armv8_crc32.value_or(0) == 0) { + return false; + } + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855 + static const absl::optional<int> feat_pmull = + ReadSysctlByName<int>("hw.optional.arm.FEAT_PMULL"); + if (feat_pmull.value_or(0) == 0) { + return false; + } + return true; } #else diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h b/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h index 7ae83bdcbd..5d3e4e3ff1 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h @@ -111,20 +111,31 @@ inline void *non_temporal_store_memcpy(void *__restrict dst, #endif // __SSE3__ || __aarch64__ || (_MSC_VER && __AVX__) } +// We try to force non_temporal_store_memcpy_avx to use AVX instructions +// so that we can select it at runtime when AVX is available. +// Clang on Windows has gnu::target but does not make AVX types like __m256i +// available when trying to force specific functions to use AVX compiles. +#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::target) && !defined(_MSC_VER) && \ + (defined(__x86_64__) || defined(__i386__)) +#define ABSL_INTERNAL_CAN_FORCE_AVX 1 +#endif + // If the objects overlap, the behavior is undefined. Uses regular memcpy // instead of non-temporal memcpy if the required CPU intrinsics are unavailable // at compile time. -#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::target) && \ - (defined(__x86_64__) || defined(__i386__)) +#ifdef ABSL_INTERNAL_CAN_FORCE_AVX [[gnu::target("avx")]] #endif inline void *non_temporal_store_memcpy_avx(void *__restrict dst, const void *__restrict src, size_t len) { - // This function requires AVX. For clang and gcc we compile it with AVX even - // if the translation unit isn't built with AVX support. This works because we - // only select this implementation at runtime if the CPU supports AVX. -#if defined(__SSE3__) || (defined(_MSC_VER) && defined(__AVX__)) + // This function requires AVX. If possible we compile it with AVX even if the + // translation unit isn't built with AVX support. This works because we only + // select this implementation at runtime if the CPU supports AVX. + // MSVC AVX support implies SSE3 support. +#if ((defined(__AVX__) || defined(ABSL_INTERNAL_CAN_FORCE_AVX)) && \ + defined(__SSE3__)) || \ + (defined(_MSC_VER) && defined(__AVX__)) uint8_t *d = reinterpret_cast<uint8_t *>(dst); const uint8_t *s = reinterpret_cast<const uint8_t *>(src); @@ -170,10 +181,13 @@ inline void *non_temporal_store_memcpy_avx(void *__restrict dst, } return dst; #else + // Fallback to regular memcpy so that this function compiles. return memcpy(dst, src, len); -#endif // __SSE3__ || (_MSC_VER && __AVX__) +#endif } +#undef ABSL_INTERNAL_CAN_FORCE_AVX + } // namespace crc_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc b/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc index 570d1e504d..d31f5a1f4e 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc +++ b/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc @@ -21,6 +21,7 @@ #ifdef _WIN32 #include <windows.h> #else +#include <pthread.h> #include <sched.h> #include <unistd.h> #endif @@ -65,6 +66,23 @@ #endif #endif +// ABSL_HAVE_PTHREAD_CPU_NUMBER_NP +// +// Checks whether pthread_cpu_number_np is available. +#ifdef ABSL_HAVE_PTHREAD_CPU_NUMBER_NP +#error ABSL_HAVE_PTHREAD_CPU_NUMBER_NP cannot be directly set +#elif defined(__APPLE__) && defined(__has_include) && \ + ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 140200) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 70100) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 140200)) +#define ABSL_HAVE_PTHREAD_CPU_NUMBER_NP 1 +#endif + namespace absl { ABSL_NAMESPACE_BEGIN @@ -330,6 +348,20 @@ static void ImmediateAbortSignalHandler(int) { RaiseToDefaultHandler(SIGABRT); } using GetTidType = decltype(absl::base_internal::GetTID()); ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0); +static int GetCpuNumber() { +#ifdef ABSL_HAVE_SCHED_GETCPU + return sched_getcpu(); +#elif defined(ABSL_HAVE_PTHREAD_CPU_NUMBER_NP) + size_t cpu_num; + if (pthread_cpu_number_np(&cpu_num) == 0) { + return static_cast<int>(cpu_num); + } + return -1; +#else + return -1; +#endif +} + #ifndef ABSL_HAVE_SIGACTION static void AbslFailureSignalHandler(int signo) { void* ucontext = nullptr; @@ -360,10 +392,7 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) { // Increase the chance that the CPU we report was the same CPU on which the // signal was received by doing this as early as possible, i.e. after // verifying that this is not a recursive signal handler invocation. - int my_cpu = -1; -#ifdef ABSL_HAVE_SCHED_GETCPU - my_cpu = sched_getcpu(); -#endif + int my_cpu = GetCpuNumber(); #ifdef ABSL_HAVE_ALARM // Set an alarm to abort the program in case this code hangs or deadlocks. diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.h b/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.h index 19c4952e2f..1fac29c52b 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.h +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.h @@ -35,7 +35,7 @@ #if defined(__ELF__) && !defined(__OpenBSD__) && !defined(__QNX__) && \ !defined(__native_client__) && !defined(__asmjs__) && \ !defined(__wasm__) && !defined(__HAIKU__) && !defined(__sun) && \ - !defined(__VXWORKS__) && !defined(__hexagon__) + !defined(__VXWORKS__) && !defined(__hexagon__) && !defined(__XTENSA__) #define ABSL_HAVE_ELF_MEM_IMAGE 1 #endif diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h b/contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h index f41b64c39d..f5ba5575d1 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h @@ -24,7 +24,7 @@ // Use this feature test macro to detect its availability. #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION #error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly -#elif !defined(__APPLE__) && !defined(_WIN32) && \ +#elif !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) && \ (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \ defined(__aarch64__) || defined(__riscv)) #define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1 diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc index b123479b1a..4490c4e13c 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc @@ -178,6 +178,20 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc, return new_frame_pointer; } +// When PAC-RET (-mbranch-protection=pac-ret) is enabled, return addresses +// stored on the stack will be signed, which means that pointer bits outside of +// the VA range are potentially set. Since the stacktrace code is expected to +// return normal code pointers, this function clears those bits. +inline void* ClearPacBits(void* ptr) { + register void* x30 __asm__("x30") = ptr; + // The normal instruction for clearing PAC bits is XPACI, but for + // compatibility with ARM platforms that do not support pointer + // authentication, we use the hint space instruction XPACLRI instead. Hint + // space instructions behave as NOPs on unsupported platforms. + asm("xpaclri" : "+r"(x30)); + return x30; +} + template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> // We count on the bottom frame being this one. See the comment // at prev_return_address @@ -219,7 +233,7 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, if (skip_count > 0) { skip_count--; } else { - result[n] = prev_return_address; + result[n] = ClearPacBits(prev_return_address); if (IS_STACK_FRAMES) { sizes[n] = static_cast<int>( ComputeStackFrameSize(prev_frame_pointer, frame_pointer)); diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_config.h b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_config.h index 3929b1b734..88949fe974 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_config.h +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_config.h @@ -42,6 +42,13 @@ #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_emscripten-inl.inc" +#elif defined(__ANDROID__) && __ANDROID_API__ >= 33 + +// Use the generic implementation for Android 33+ (Android T+). This is the +// first version of Android for which <execinfo.h> implements backtrace(). +#define ABSL_STACKTRACE_INL_HEADER \ + "absl/debugging/internal/stacktrace_generic-inl.inc" + #elif defined(__linux__) && !defined(__ANDROID__) #if defined(NO_FRAME_POINTER) && \ diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc index 20183fa321..3f9e12407a 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc @@ -36,15 +36,16 @@ #include "absl/base/attributes.h" #include "absl/debugging/stacktrace.h" -static const uintptr_t kUnknownFrameSize = 0; +static constexpr ptrdiff_t kUnknownFrameSize = 0; // Compute the size of a stack frame in [low..high). We assume that low < high. // Return size of kUnknownFrameSize. template <typename T> -static inline uintptr_t ComputeStackFrameSize(const T *low, const T *high) { +static inline ptrdiff_t ComputeStackFrameSize(const T *low, const T *high) { const char *low_char_ptr = reinterpret_cast<const char *>(low); const char *high_char_ptr = reinterpret_cast<const char *>(high); - return low < high ? high_char_ptr - low_char_ptr : kUnknownFrameSize; + return low < high ? static_cast<ptrdiff_t>(high_char_ptr - low_char_ptr) + : kUnknownFrameSize; } // Given a pointer to a stack frame, locate and return the calling stackframe, @@ -93,8 +94,8 @@ static void ** NextStackFrame(void **old_frame_pointer, const void *uc, // Check frame size. In strict mode, we assume frames to be under 100,000 // bytes. In non-strict mode, we relax the limit to 1MB. - const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000; - const uintptr_t frame_size = + const ptrdiff_t max_size = STRICT_UNWINDING ? 100000 : 1000000; + const ptrdiff_t frame_size = ComputeStackFrameSize(old_frame_pointer, new_frame_pointer); if (frame_size == kUnknownFrameSize) { if (STRICT_UNWINDING) @@ -151,7 +152,9 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count, } else { result[n] = return_address; if (IS_STACK_FRAMES) { - sizes[n] = ComputeStackFrameSize(frame_pointer, next_frame_pointer); + // NextStackFrame() has already checked that frame size fits to int + sizes[n] = static_cast<int>(ComputeStackFrameSize(frame_pointer, + next_frame_pointer)); } n++; } diff --git a/contrib/restricted/abseil-cpp/absl/debugging/leak_check.cc b/contrib/restricted/abseil-cpp/absl/debugging/leak_check.cc index fdb8798b81..1370bcc455 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/leak_check.cc +++ b/contrib/restricted/abseil-cpp/absl/debugging/leak_check.cc @@ -28,7 +28,7 @@ #include <sanitizer/lsan_interface.h> #if ABSL_HAVE_ATTRIBUTE_WEAK -extern "C" ABSL_ATTRIBUTE_WEAK int __lsan_is_turned_off(); +extern "C" ABSL_ATTRIBUTE_WEAK int __lsan_is_turned_off() { return 0; } #endif namespace absl { @@ -37,13 +37,13 @@ bool HaveLeakSanitizer() { return true; } #if ABSL_HAVE_ATTRIBUTE_WEAK bool LeakCheckerIsActive() { - return !(&__lsan_is_turned_off && __lsan_is_turned_off()); + return __lsan_is_turned_off() == 0; } #else bool LeakCheckerIsActive() { return true; } #endif -bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check(); } +bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check() != 0; } void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); } void RegisterLivePointers(const void* ptr, size_t size) { __lsan_register_root_region(ptr, size); diff --git a/contrib/restricted/abseil-cpp/absl/debugging/symbolize.cc b/contrib/restricted/abseil-cpp/absl/debugging/symbolize.cc index 638d3954ae..344436f9d1 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/symbolize.cc +++ b/contrib/restricted/abseil-cpp/absl/debugging/symbolize.cc @@ -12,12 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #include "absl/debugging/symbolize.h" #ifdef _WIN32 #include <winapifamily.h> -#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \ - WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) // UWP doesn't have access to win32 APIs. #define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32 #endif diff --git a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc index ae75cd4153..a98ca81d17 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc +++ b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc @@ -52,6 +52,7 @@ #include <elf.h> #include <fcntl.h> #include <link.h> // For ElfW() macro. +#include <sys/resource.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -376,6 +377,46 @@ class Symbolizer { SymbolCacheLine symbol_cache_[SYMBOL_CACHE_LINES]; }; +// Protect against client code closing low-valued file descriptors it doesn't +// actually own. +int OpenReadOnlyWithHighFD(const char *fname) { + static int high_fd = [] { + struct rlimit rlim{}; + const int rc = getrlimit(RLIMIT_NOFILE, &rlim); + if (rc == 0 && rlim.rlim_cur >= 2000) { + const int max_fd = static_cast<int>(rlim.rlim_cur); + + // This will return 2000 on reasonably-configured systems. + return std::min<int>(2000, max_fd - 1000); + } + ABSL_RAW_LOG(WARNING, "Unable to get high fd: rc=%d, limit=%ld", // + rc, static_cast<long>(rlim.rlim_cur)); + return -1; + }(); + constexpr int kOpenFlags = O_RDONLY | O_CLOEXEC; + if (high_fd >= 1000) { + const int fd = open(fname, kOpenFlags); + if (fd != -1 && fd < high_fd) { + // Try to relocate fd to high range. + static_assert(kOpenFlags & O_CLOEXEC, + "F_DUPFD_CLOEXEC assumes O_CLOEXEC"); + const int fd2 = fcntl(fd, F_DUPFD_CLOEXEC, high_fd); + if (fd2 != -1) { + // Successfully obtained high fd. Use it. + close(fd); + return fd2; + } else { + ABSL_RAW_LOG(WARNING, "Unable to dup fd=%d above %d, errno=%d", fd, + high_fd, errno); + } + } + // Either open failed and fd==-1, or fd is already above high_fd, or fcntl + // failed and fd is valid (but low). + return fd; + } + return open(fname, kOpenFlags); +} + static std::atomic<Symbolizer *> g_cached_symbolizer; } // namespace @@ -541,11 +582,9 @@ static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType( (buf_bytes > num_bytes_left) ? num_bytes_left : buf_bytes; const off_t offset = sh_offset + static_cast<off_t>(i * sizeof(buf[0])); const ssize_t len = file->ReadFromOffset(buf, num_bytes_to_read, offset); - if (len < 0) { - ABSL_RAW_LOG( - WARNING, - "Reading %zu bytes from offset %ju returned %zd which is negative.", - num_bytes_to_read, static_cast<intmax_t>(offset), len); + if (len <= 0) { + ABSL_RAW_LOG(WARNING, "Reading %zu bytes from offset %ju returned %zd.", + num_bytes_to_read, static_cast<intmax_t>(offset), len); return false; } if (static_cast<size_t>(len) % sizeof(buf[0]) != 0) { @@ -1066,7 +1105,7 @@ static ABSL_ATTRIBUTE_NOINLINE bool ReadAddrMap( snprintf(maps_path, sizeof(maps_path), "/proc/self/task/%d/maps", getpid()); int maps_fd; - NO_INTR(maps_fd = open(maps_path, O_RDONLY)); + NO_INTR(maps_fd = OpenReadOnlyWithHighFD(maps_path)); FileDescriptor wrapped_maps_fd(maps_fd); if (wrapped_maps_fd.get() < 0) { ABSL_RAW_LOG(WARNING, "%s: errno=%d", maps_path, errno); @@ -1340,7 +1379,7 @@ static void MaybeOpenFdFromSelfExe(ObjFile *obj) { if (memcmp(obj->start_addr, ELFMAG, SELFMAG) != 0) { return; } - int fd = open("/proc/self/exe", O_RDONLY); + int fd = OpenReadOnlyWithHighFD("/proc/self/exe"); if (fd == -1) { return; } @@ -1364,7 +1403,7 @@ static void MaybeOpenFdFromSelfExe(ObjFile *obj) { static bool MaybeInitializeObjFile(ObjFile *obj) { if (obj->fd < 0) { - obj->fd = open(obj->filename, O_RDONLY); + obj->fd = OpenReadOnlyWithHighFD(obj->filename); if (obj->fd < 0) { // Getting /proc/self/exe here means that we were hinted. @@ -1372,7 +1411,7 @@ static bool MaybeInitializeObjFile(ObjFile *obj) { // /proc/self/exe may be inaccessible (due to setuid, etc.), so try // accessing the binary via argv0. if (argv0_value != nullptr) { - obj->fd = open(argv0_value, O_RDONLY); + obj->fd = OpenReadOnlyWithHighFD(argv0_value); } } else { MaybeOpenFdFromSelfExe(obj); diff --git a/contrib/restricted/abseil-cpp/absl/debugging/ya.make b/contrib/restricted/abseil-cpp/absl/debugging/ya.make index 3c3aa2d8bc..cff58f5fc8 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/ya.make +++ b/contrib/restricted/abseil-cpp/absl/debugging/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.cc b/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.cc index 9f3b4a5a28..4140230651 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.cc @@ -24,6 +24,7 @@ namespace absl { ABSL_NAMESPACE_BEGIN +absl::string_view CommandLineFlag::TypeName() const { return ""; } bool CommandLineFlag::IsRetired() const { return false; } bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) { return ParseFrom(value, flags_internal::SET_FLAGS_VALUE, diff --git a/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.h b/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.h index 26ec0e7d84..a9ffd02084 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.h +++ b/contrib/restricted/abseil-cpp/absl/flags/commandlineflag.h @@ -200,6 +200,13 @@ class CommandLineFlag { // Checks that flags default value can be converted to string and back to the // flag's value type. virtual void CheckDefaultValueParsingRoundtrip() const = 0; + + // absl::CommandLineFlag::TypeName() + // + // Returns string representation of the type of this flag + // (the way it is spelled in the ABSL_FLAG macro). + // The default implementation returns the empty string. + virtual absl::string_view TypeName() const; }; #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop diff --git a/contrib/restricted/abseil-cpp/absl/flags/flag.h b/contrib/restricted/abseil-cpp/absl/flags/flag.h index a8e0e93299..19d0ef992f 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/flag.h +++ b/contrib/restricted/abseil-cpp/absl/flags/flag.h @@ -204,12 +204,14 @@ ABSL_NAMESPACE_END #if ABSL_FLAGS_STRIP_NAMES #define ABSL_FLAG_IMPL_FLAGNAME(txt) "" +#define ABSL_FLAG_IMPL_TYPENAME(txt) "" #define ABSL_FLAG_IMPL_FILENAME() "" #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \ nullptr) #else #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt +#define ABSL_FLAG_IMPL_TYPENAME(txt) txt #define ABSL_FLAG_IMPL_FILENAME() __FILE__ #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \ absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \ @@ -261,16 +263,17 @@ ABSL_NAMESPACE_END // Note: Name of registrar object is not arbitrary. It is used to "grab" // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility // of defining two flags with names foo and nofoo. -#define ABSL_FLAG_IMPL(Type, name, default_value, help) \ - extern ::absl::Flag<Type> FLAGS_##name; \ - namespace absl /* block flags in namespaces */ {} \ - ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ - ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help) \ - ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{ \ - ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(), \ - ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \ - extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name; \ - absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name = \ +#define ABSL_FLAG_IMPL(Type, name, default_value, help) \ + extern ::absl::Flag<Type> FLAGS_##name; \ + namespace absl /* block flags in namespaces */ {} \ + ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ + ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help) \ + ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{ \ + ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_TYPENAME(#Type), \ + ABSL_FLAG_IMPL_FILENAME(), ABSL_FLAG_IMPL_HELP_ARG(name), \ + ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \ + extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name; \ + absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name = \ ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) // ABSL_RETIRED_FLAG @@ -290,8 +293,7 @@ ABSL_NAMESPACE_END // arguments unchanged (unless of course you actually want to retire the flag // type at this time as well). // -// `default_value` is only used as a double check on the type. `explanation` is -// unused. +// `default_value` and `explanation` are unused. // TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of // retired flags are cleaned up. #define ABSL_RETIRED_FLAG(type, name, default_value, explanation) \ diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc index 981f19fdb8..ccd26670cf 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc @@ -34,7 +34,9 @@ #include "absl/base/config.h" #include "absl/base/const_init.h" #include "absl/base/dynamic_annotations.h" +#include "absl/base/no_destructor.h" #include "absl/base/optimization.h" +#include "absl/base/thread_annotations.h" #include "absl/flags/config.h" #include "absl/flags/internal/commandlineflag.h" #include "absl/flags/usage_config.h" @@ -85,11 +87,15 @@ class MutexRelock { // we move the memory to the freelist where it lives indefinitely, so it can // still be safely accessed. This also prevents leak checkers from complaining // about the leaked memory that can no longer be accessed through any pointer. -ABSL_CONST_INIT absl::Mutex s_freelist_guard(absl::kConstInit); -ABSL_CONST_INIT std::vector<void*>* s_freelist = nullptr; +absl::Mutex* FreelistMutex() { + static absl::NoDestructor<absl::Mutex> mutex; + return mutex.get(); +} +ABSL_CONST_INIT std::vector<void*>* s_freelist ABSL_GUARDED_BY(FreelistMutex()) + ABSL_PT_GUARDED_BY(FreelistMutex()) = nullptr; void AddToFreelist(void* p) { - absl::MutexLock l(&s_freelist_guard); + absl::MutexLock l(FreelistMutex()); if (!s_freelist) { s_freelist = new std::vector<void*>; } @@ -101,7 +107,7 @@ void AddToFreelist(void* p) { /////////////////////////////////////////////////////////////////////////////// uint64_t NumLeakedFlagValues() { - absl::MutexLock l(&s_freelist_guard); + absl::MutexLock l(FreelistMutex()); return s_freelist == nullptr ? 0u : s_freelist->size(); } @@ -336,6 +342,8 @@ void FlagImpl::StoreValue(const void* src, ValueSource source) { absl::string_view FlagImpl::Name() const { return name_; } +absl::string_view FlagImpl::TypeName() const { return type_name_; } + std::string FlagImpl::Filename() const { return flags_internal::GetUsageConfig().normalize_filename(filename_); } diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h index a0be31d93a..a6e7986f96 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h @@ -373,9 +373,13 @@ class MaskedPointer { static constexpr int RequiredAlignment() { return 4; } + constexpr MaskedPointer() : ptr_(nullptr) {} constexpr explicit MaskedPointer(ptr_t rhs) : ptr_(rhs) {} MaskedPointer(ptr_t rhs, bool is_candidate); + MaskedPointer(const MaskedPointer& rhs) = default; + MaskedPointer& operator=(const MaskedPointer& rhs) = default; + void* Ptr() const { return reinterpret_cast<void*>(reinterpret_cast<mask_t>(ptr_) & kPtrValueMask); @@ -578,10 +582,12 @@ class FlagState; #endif class FlagImpl final : public CommandLineFlag { public: - constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op, - FlagHelpArg help, FlagValueStorageKind value_kind, + constexpr FlagImpl(const char* name, const char* type_name, + const char* filename, FlagOpFn op, FlagHelpArg help, + FlagValueStorageKind value_kind, FlagDefaultArg default_arg) : name_(name), + type_name_(type_name), filename_(filename), op_(op), help_(help.source), @@ -694,6 +700,7 @@ class FlagImpl final : public CommandLineFlag { // CommandLineFlag interface implementation absl::string_view Name() const override; + absl::string_view TypeName() const override; std::string Filename() const override; std::string Help() const override; FlagFastTypeId TypeId() const override; @@ -727,6 +734,10 @@ class FlagImpl final : public CommandLineFlag { // Flags name passed to ABSL_FLAG as second arg. const char* const name_; + + // Flags type passed to ABSL_FLAG as first arg. + const char* const type_name_; + // The file name where ABSL_FLAG resides. const char* const filename_; // Type-specific operations vtable. @@ -785,9 +796,9 @@ class FlagImpl final : public CommandLineFlag { template <typename T> class Flag { public: - constexpr Flag(const char* name, const char* filename, FlagHelpArg help, - const FlagDefaultArg default_arg) - : impl_(name, filename, &FlagOps<T>, help, + constexpr Flag(const char* name, const char* type_name, const char* filename, + FlagHelpArg help, const FlagDefaultArg default_arg) + : impl_(name, type_name, filename, &FlagOps<T>, help, flags_internal::StorageKind<T>(), default_arg), value_() {} diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.cc b/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.cc index a7eb58b6d4..610d1ffdf7 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.cc @@ -59,6 +59,10 @@ bool PrivateHandleAccessor::ParseFrom(CommandLineFlag& flag, return flag.ParseFrom(value, set_mode, source, error); } +absl::string_view PrivateHandleAccessor::TypeName(const CommandLineFlag& flag) { + return flag.TypeName(); +} + } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.h b/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.h index c64435cd61..bf4154c5a5 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.h +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/private_handle_accessor.h @@ -52,6 +52,9 @@ class PrivateHandleAccessor { static bool ParseFrom(CommandLineFlag& flag, absl::string_view value, flags_internal::FlagSettingMode set_mode, flags_internal::ValueSource source, std::string& error); + + // Access to CommandLineFlag::TypeName. + static absl::string_view TypeName(const CommandLineFlag& flag); }; } // namespace flags_internal diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/program_name.cc b/contrib/restricted/abseil-cpp/absl/flags/internal/program_name.cc index 51d698da8b..fb06643df5 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/program_name.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/program_name.cc @@ -19,7 +19,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/base/const_init.h" +#include "absl/base/no_destructor.h" #include "absl/base/thread_annotations.h" #include "absl/flags/internal/path_util.h" #include "absl/strings/string_view.h" @@ -29,30 +29,31 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { -ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit); -ABSL_CONST_INIT static std::string* program_name - ABSL_GUARDED_BY(program_name_guard) = nullptr; +static absl::Mutex* ProgramNameMutex() { + static absl::NoDestructor<absl::Mutex> mutex; + return mutex.get(); +} +ABSL_CONST_INIT static std::string* program_name ABSL_GUARDED_BY( + ProgramNameMutex()) ABSL_PT_GUARDED_BY(ProgramNameMutex()) = nullptr; std::string ProgramInvocationName() { - absl::MutexLock l(&program_name_guard); - + absl::MutexLock l(ProgramNameMutex()); return program_name ? *program_name : "UNKNOWN"; } std::string ShortProgramInvocationName() { - absl::MutexLock l(&program_name_guard); - + absl::MutexLock l(ProgramNameMutex()); return program_name ? std::string(flags_internal::Basename(*program_name)) : "UNKNOWN"; } void SetProgramInvocationName(absl::string_view prog_name_str) { - absl::MutexLock l(&program_name_guard); - - if (!program_name) + absl::MutexLock l(ProgramNameMutex()); + if (!program_name) { program_name = new std::string(prog_name_str); - else + } else { program_name->assign(prog_name_str.data(), prog_name_str.size()); + } } } // namespace flags_internal diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc b/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc index 8b169bcdc2..fc68b03db2 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc @@ -29,7 +29,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/base/const_init.h" +#include "absl/base/no_destructor.h" #include "absl/base/thread_annotations.h" #include "absl/flags/commandlineflag.h" #include "absl/flags/flag.h" @@ -434,45 +434,48 @@ HelpMode HandleUsageFlags(std::ostream& out, namespace { -ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit); -ABSL_CONST_INIT std::string* match_substr - ABSL_GUARDED_BY(help_attributes_guard) = nullptr; -ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) = +absl::Mutex* HelpAttributesMutex() { + static absl::NoDestructor<absl::Mutex> mutex; + return mutex.get(); +} +ABSL_CONST_INIT std::string* match_substr ABSL_GUARDED_BY(HelpAttributesMutex()) + ABSL_PT_GUARDED_BY(HelpAttributesMutex()) = nullptr; +ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(HelpAttributesMutex()) = HelpMode::kNone; -ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) = +ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(HelpAttributesMutex()) = HelpFormat::kHumanReadable; } // namespace std::string GetFlagsHelpMatchSubstr() { - absl::MutexLock l(&help_attributes_guard); + absl::MutexLock l(HelpAttributesMutex()); if (match_substr == nullptr) return ""; return *match_substr; } void SetFlagsHelpMatchSubstr(absl::string_view substr) { - absl::MutexLock l(&help_attributes_guard); + absl::MutexLock l(HelpAttributesMutex()); if (match_substr == nullptr) match_substr = new std::string; match_substr->assign(substr.data(), substr.size()); } HelpMode GetFlagsHelpMode() { - absl::MutexLock l(&help_attributes_guard); + absl::MutexLock l(HelpAttributesMutex()); return help_mode; } void SetFlagsHelpMode(HelpMode mode) { - absl::MutexLock l(&help_attributes_guard); + absl::MutexLock l(HelpAttributesMutex()); help_mode = mode; } HelpFormat GetFlagsHelpFormat() { - absl::MutexLock l(&help_attributes_guard); + absl::MutexLock l(HelpAttributesMutex()); return help_format; } void SetFlagsHelpFormat(HelpFormat format) { - absl::MutexLock l(&help_attributes_guard); + absl::MutexLock l(HelpAttributesMutex()); help_format = format; } diff --git a/contrib/restricted/abseil-cpp/absl/flags/parse.cc b/contrib/restricted/abseil-cpp/absl/flags/parse.cc index 526b61d1d1..8be2016fd6 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/parse.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/parse.cc @@ -35,7 +35,7 @@ #include "absl/algorithm/container.h" #include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/base/const_init.h" +#include "absl/base/no_destructor.h" #include "absl/base/thread_annotations.h" #include "absl/flags/commandlineflag.h" #include "absl/flags/config.h" @@ -64,14 +64,17 @@ ABSL_NAMESPACE_BEGIN namespace flags_internal { namespace { -ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit); +absl::Mutex* ProcessingChecksMutex() { + static absl::NoDestructor<absl::Mutex> mutex; + return mutex.get(); +} ABSL_CONST_INIT bool flagfile_needs_processing - ABSL_GUARDED_BY(processing_checks_guard) = false; + ABSL_GUARDED_BY(ProcessingChecksMutex()) = false; ABSL_CONST_INIT bool fromenv_needs_processing - ABSL_GUARDED_BY(processing_checks_guard) = false; + ABSL_GUARDED_BY(ProcessingChecksMutex()) = false; ABSL_CONST_INIT bool tryfromenv_needs_processing - ABSL_GUARDED_BY(processing_checks_guard) = false; + ABSL_GUARDED_BY(ProcessingChecksMutex()) = false; ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit); ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags @@ -106,7 +109,7 @@ ABSL_FLAG(std::vector<std::string>, flagfile, {}, .OnUpdate([]() { if (absl::GetFlag(FLAGS_flagfile).empty()) return; - absl::MutexLock l(&absl::flags_internal::processing_checks_guard); + absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex()); // Setting this flag twice before it is handled most likely an internal // error and should be reviewed by developers. @@ -122,7 +125,7 @@ ABSL_FLAG(std::vector<std::string>, fromenv, {}, .OnUpdate([]() { if (absl::GetFlag(FLAGS_fromenv).empty()) return; - absl::MutexLock l(&absl::flags_internal::processing_checks_guard); + absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex()); // Setting this flag twice before it is handled most likely an internal // error and should be reviewed by developers. @@ -138,7 +141,7 @@ ABSL_FLAG(std::vector<std::string>, tryfromenv, {}, .OnUpdate([]() { if (absl::GetFlag(FLAGS_tryfromenv).empty()) return; - absl::MutexLock l(&absl::flags_internal::processing_checks_guard); + absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex()); // Setting this flag twice before it is handled most likely an internal // error and should be reviewed by developers. @@ -415,7 +418,7 @@ bool HandleGeneratorFlags(std::vector<ArgsList>& input_args, std::vector<std::string>& flagfile_value) { bool success = true; - absl::MutexLock l(&flags_internal::processing_checks_guard); + absl::MutexLock l(flags_internal::ProcessingChecksMutex()); // flagfile could have been set either on a command line or // programmatically before invoking ParseCommandLine. Note that we do not @@ -478,7 +481,7 @@ void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) { // going to be {"f1", "f2"} if (!flagfile_value.empty()) { absl::SetFlag(&FLAGS_flagfile, flagfile_value); - absl::MutexLock l(&flags_internal::processing_checks_guard); + absl::MutexLock l(flags_internal::ProcessingChecksMutex()); flags_internal::flagfile_needs_processing = false; } @@ -490,7 +493,7 @@ void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) { absl::SetFlag(&FLAGS_tryfromenv, {}); } - absl::MutexLock l(&flags_internal::processing_checks_guard); + absl::MutexLock l(flags_internal::ProcessingChecksMutex()); flags_internal::fromenv_needs_processing = false; flags_internal::tryfromenv_needs_processing = false; } diff --git a/contrib/restricted/abseil-cpp/absl/flags/usage_config.cc b/contrib/restricted/abseil-cpp/absl/flags/usage_config.cc index 5d7426db31..5922c5e20f 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/usage_config.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/usage_config.cc @@ -22,6 +22,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/const_init.h" +#include "absl/base/no_destructor.h" #include "absl/base/thread_annotations.h" #include "absl/flags/internal/path_util.h" #include "absl/flags/internal/program_name.h" @@ -104,14 +105,18 @@ std::string NormalizeFilename(absl::string_view filename) { // -------------------------------------------------------------------- -ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit); +absl::Mutex* CustomUsageConfigMutex() { + static absl::NoDestructor<absl::Mutex> mutex; + return mutex.get(); +} ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config - ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr; + ABSL_GUARDED_BY(CustomUsageConfigMutex()) + ABSL_PT_GUARDED_BY(CustomUsageConfigMutex()) = nullptr; } // namespace FlagsUsageConfig GetUsageConfig() { - absl::MutexLock l(&custom_usage_config_guard); + absl::MutexLock l(CustomUsageConfigMutex()); if (custom_usage_config) return *custom_usage_config; @@ -136,7 +141,7 @@ void ReportUsageError(absl::string_view msg, bool is_fatal) { } // namespace flags_internal void SetFlagsUsageConfig(FlagsUsageConfig usage_config) { - absl::MutexLock l(&flags_internal::custom_usage_config_guard); + absl::MutexLock l(flags_internal::CustomUsageConfigMutex()); if (!usage_config.contains_helpshort_flags) usage_config.contains_helpshort_flags = diff --git a/contrib/restricted/abseil-cpp/absl/flags/ya.make b/contrib/restricted/abseil-cpp/absl/flags/ya.make index 6cdd7fa292..309a6f39d9 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/ya.make +++ b/contrib/restricted/abseil-cpp/absl/flags/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/functional/ya.make b/contrib/restricted/abseil-cpp/absl/functional/ya.make index 4e3328995c..2deef3b2a7 100644 --- a/contrib/restricted/abseil-cpp/absl/functional/ya.make +++ b/contrib/restricted/abseil-cpp/absl/functional/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240722.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20250127.0.tar.gz) NO_RUNTIME() diff --git a/contrib/restricted/abseil-cpp/absl/hash/hash.h b/contrib/restricted/abseil-cpp/absl/hash/hash.h index 470cca4837..479b17b7b1 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/hash.h +++ b/contrib/restricted/abseil-cpp/absl/hash/hash.h @@ -78,11 +78,16 @@ #ifndef ABSL_HASH_HASH_H_ #define ABSL_HASH_HASH_H_ +#include <cstddef> +#include <cstdint> #include <tuple> +#include <type_traits> #include <utility> +#include "absl/base/config.h" #include "absl/functional/function_ref.h" #include "absl/hash/internal/hash.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -319,8 +324,12 @@ class HashState : public hash_internal::HashStateBase<HashState> { // Create a new `HashState` instance that wraps `state`. All calls to // `combine()` and `combine_contiguous()` on the new instance will be // redirected to the original `state` object. The `state` object must outlive - // the `HashState` instance. - template <typename T> + // the `HashState` instance. `T` must be a subclass of `HashStateBase<T>` - + // users should not define their own HashState types. + template < + typename T, + absl::enable_if_t< + std::is_base_of<hash_internal::HashStateBase<T>, T>::value, int> = 0> static HashState Create(T* state) { HashState s; s.Init(state); @@ -353,6 +362,7 @@ class HashState : public hash_internal::HashStateBase<HashState> { HashState() = default; friend class HashState::HashStateBase; + friend struct hash_internal::CombineRaw; template <typename T> static void CombineContiguousImpl(void* p, const unsigned char* first, @@ -361,10 +371,22 @@ class HashState : public hash_internal::HashStateBase<HashState> { state = T::combine_contiguous(std::move(state), first, size); } + static HashState combine_raw(HashState hash_state, uint64_t value) { + hash_state.combine_raw_(hash_state.state_, value); + return hash_state; + } + + template <typename T> + static void CombineRawImpl(void* p, uint64_t value) { + T& state = *static_cast<T*>(p); + state = hash_internal::CombineRaw()(std::move(state), value); + } + template <typename T> void Init(T* state) { state_ = state; combine_contiguous_ = &CombineContiguousImpl<T>; + combine_raw_ = &CombineRawImpl<T>; run_combine_unordered_ = &RunCombineUnorderedImpl<T>; } @@ -403,6 +425,7 @@ class HashState : public hash_internal::HashStateBase<HashState> { void Init(HashState* state) { state_ = state->state_; combine_contiguous_ = state->combine_contiguous_; + combine_raw_ = state->combine_raw_; run_combine_unordered_ = state->run_combine_unordered_; } @@ -413,6 +436,7 @@ class HashState : public hash_internal::HashStateBase<HashState> { void* state_; void (*combine_contiguous_)(void*, const unsigned char*, size_t); + void (*combine_raw_)(void*, uint64_t); HashState (*run_combine_unordered_)( HashState state, absl::FunctionRef<void(HashState, absl::FunctionRef<void(HashState&)>)>); diff --git a/contrib/restricted/abseil-cpp/absl/hash/hash_testing.h b/contrib/restricted/abseil-cpp/absl/hash/hash_testing.h index 1e1c574149..673366deef 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/hash_testing.h +++ b/contrib/restricted/abseil-cpp/absl/hash/hash_testing.h @@ -244,7 +244,8 @@ VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) { if (v.expand() != expected) { return testing::AssertionFailure() << "Values " << c[0].ToString() << " and " << v.ToString() - << " evaluate as equal but have an unequal hash expansion."; + << " evaluate as equal but have unequal hash expansions (" + << expected << " vs. " << v.expand() << ")."; } } @@ -256,17 +257,18 @@ VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) { case SpyHashState::CompareResult::kEqual: return testing::AssertionFailure() << "Values " << c[0].ToString() << " and " << c2[0].ToString() - << " evaluate as unequal but have an equal hash expansion."; + << " evaluate as unequal but have an equal hash expansion:" + << c2_hash << "."; case SpyHashState::CompareResult::kBSuffixA: return testing::AssertionFailure() - << "Hash expansion of " << c2[0].ToString() + << "Hash expansion of " << c2[0].ToString() << ";" << c2_hash << " is a suffix of the hash expansion of " << c[0].ToString() - << "."; + << ";" << expected << "."; case SpyHashState::CompareResult::kASuffixB: return testing::AssertionFailure() - << "Hash expansion of " << c[0].ToString() - << " is a suffix of the hash expansion of " << c2[0].ToString() - << "."; + << "Hash expansion of " << c[0].ToString() << ";" + << expected << " is a suffix of the hash expansion of " + << c2[0].ToString() << ";" << c2_hash << "."; case SpyHashState::CompareResult::kUnequal: break; } diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.cc b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.cc index 93906ef872..e0a8ea9974 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.cc +++ b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.cc @@ -14,6 +14,14 @@ #include "absl/hash/internal/hash.h" +#include <cstddef> +#include <cstdint> +#include <type_traits> + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/hash/internal/low_level_hash.h" + namespace absl { ABSL_NAMESPACE_BEGIN namespace hash_internal { @@ -21,9 +29,10 @@ namespace hash_internal { uint64_t MixingHashState::CombineLargeContiguousImpl32( uint64_t state, const unsigned char* first, size_t len) { while (len >= PiecewiseChunkSize()) { - state = Mix(state, - hash_internal::CityHash32(reinterpret_cast<const char*>(first), - PiecewiseChunkSize())); + state = Mix( + state ^ hash_internal::CityHash32(reinterpret_cast<const char*>(first), + PiecewiseChunkSize()), + kMul); len -= PiecewiseChunkSize(); first += PiecewiseChunkSize(); } @@ -35,7 +44,7 @@ uint64_t MixingHashState::CombineLargeContiguousImpl32( uint64_t MixingHashState::CombineLargeContiguousImpl64( uint64_t state, const unsigned char* first, size_t len) { while (len >= PiecewiseChunkSize()) { - state = Mix(state, Hash64(first, PiecewiseChunkSize())); + state = Mix(state ^ Hash64(first, PiecewiseChunkSize()), kMul); len -= PiecewiseChunkSize(); first += PiecewiseChunkSize(); } @@ -46,22 +55,13 @@ uint64_t MixingHashState::CombineLargeContiguousImpl64( ABSL_CONST_INIT const void* const MixingHashState::kSeed = &kSeed; -// The salt array used by LowLevelHash. This array is NOT the mechanism used to -// make absl::Hash non-deterministic between program invocations. See `Seed()` -// for that mechanism. -// -// Any random values are fine. These values are just digits from the decimal -// part of pi. -// https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number -constexpr uint64_t kHashSalt[5] = { - uint64_t{0x243F6A8885A308D3}, uint64_t{0x13198A2E03707344}, - uint64_t{0xA4093822299F31D0}, uint64_t{0x082EFA98EC4E6C89}, - uint64_t{0x452821E638D01377}, -}; +#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL +constexpr uint64_t MixingHashState::kStaticRandomData[]; +#endif uint64_t MixingHashState::LowLevelHashImpl(const unsigned char* data, size_t len) { - return LowLevelHashLenGt16(data, len, Seed(), kHashSalt); + return LowLevelHashLenGt16(data, len, Seed(), &kStaticRandomData[0]); } } // namespace hash_internal diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h index 03bf183905..f4a0d7857c 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h +++ b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h @@ -36,8 +36,10 @@ #include <algorithm> #include <array> #include <bitset> +#include <cassert> #include <cmath> #include <cstddef> +#include <cstdint> #include <cstring> #include <deque> #include <forward_list> @@ -56,7 +58,10 @@ #include <utility> #include <vector> +#include "absl/base/attributes.h" +#include "absl/base/internal/endian.h" #include "absl/base/internal/unaligned_access.h" +#include "absl/base/optimization.h" #include "absl/base/port.h" #include "absl/container/fixed_array.h" #include "absl/hash/internal/city.h" @@ -69,8 +74,7 @@ #include "absl/types/variant.h" #include "absl/utility/utility.h" -#if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \ - !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) +#if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L #include <filesystem> // NOLINT #endif @@ -78,6 +82,10 @@ #include <string_view> #endif +#ifdef __ARM_ACLE +#include <arm_acle.h> +#endif + namespace absl { ABSL_NAMESPACE_BEGIN @@ -340,11 +348,47 @@ struct is_uniquely_represented< template <> struct is_uniquely_represented<bool> : std::false_type {}; +#ifdef ABSL_HAVE_INTRINSIC_INT128 +// Specialize the trait for GNU extension types. +template <> +struct is_uniquely_represented<__int128> : std::true_type {}; +template <> +struct is_uniquely_represented<unsigned __int128> : std::true_type {}; +#endif // ABSL_HAVE_INTRINSIC_INT128 + +template <typename T> +struct FitsIn64Bits : std::integral_constant<bool, sizeof(T) <= 8> {}; + +struct CombineRaw { + template <typename H> + H operator()(H state, uint64_t value) const { + return H::combine_raw(std::move(state), value); + } +}; + // hash_bytes() // // Convenience function that combines `hash_state` with the byte representation // of `value`. -template <typename H, typename T> +template <typename H, typename T, + absl::enable_if_t<FitsIn64Bits<T>::value, int> = 0> +H hash_bytes(H hash_state, const T& value) { + const unsigned char* start = reinterpret_cast<const unsigned char*>(&value); + uint64_t v; + if (sizeof(T) == 1) { + v = *start; + } else if (sizeof(T) == 2) { + v = absl::base_internal::UnalignedLoad16(start); + } else if (sizeof(T) == 4) { + v = absl::base_internal::UnalignedLoad32(start); + } else { + assert(sizeof(T) == 8); + v = absl::base_internal::UnalignedLoad64(start); + } + return CombineRaw()(std::move(hash_state), v); +} +template <typename H, typename T, + absl::enable_if_t<!FitsIn64Bits<T>::value, int> = 0> H hash_bytes(H hash_state, const T& value) { const unsigned char* start = reinterpret_cast<const unsigned char*>(&value); return H::combine_contiguous(std::move(hash_state), start, sizeof(value)); @@ -446,9 +490,9 @@ std::enable_if_t<std::is_pointer<T>::value, H> AbslHashValue(H hash_state, T ptr) { auto v = reinterpret_cast<uintptr_t>(ptr); // Due to alignment, pointers tend to have low bits as zero, and the next few - // bits follow a pattern since they are also multiples of some base value. - // Mixing the pointer twice helps prevent stuck low bits for certain alignment - // values. + // bits follow a pattern since they are also multiples of some base value. The + // byte swap in WeakMix helps ensure we still have good entropy in low bits. + // Mix pointers twice to ensure we have good entropy in low bits. return H::combine(std::move(hash_state), v, v); } @@ -597,7 +641,6 @@ H AbslHashValue(H hash_state, std::basic_string_view<Char> str) { #endif // ABSL_HAVE_STD_STRING_VIEW #if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \ - !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) && \ (!defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || \ __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000) && \ (!defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \ @@ -929,6 +972,7 @@ struct HashSelect { static State combine_contiguous(State hash_state, const unsigned char*, size_t); using State::HashStateBase::combine_contiguous; + static State combine_raw(State state, uint64_t value); }; struct UniquelyRepresentedProbe { @@ -1011,13 +1055,21 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> { using uint128 = absl::uint128; #endif // ABSL_HAVE_INTRINSIC_INT128 + // Random data taken from the hexadecimal digits of Pi's fractional component. + // https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number + ABSL_CACHELINE_ALIGNED static constexpr uint64_t kStaticRandomData[] = { + 0x243f'6a88'85a3'08d3, 0x1319'8a2e'0370'7344, 0xa409'3822'299f'31d0, + 0x082e'fa98'ec4e'6c89, 0x4528'21e6'38d0'1377, + }; + static constexpr uint64_t kMul = sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51} - : uint64_t{0x9ddfea08eb382d69}; + : uint64_t{0xdcb22ca68cb134ed}; template <typename T> using IntegralFastPath = - conjunction<std::is_integral<T>, is_uniquely_represented<T>>; + conjunction<std::is_integral<T>, is_uniquely_represented<T>, + FitsIn64Bits<T>>; public: // Move only @@ -1047,7 +1099,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> { template <typename T, absl::enable_if_t<IntegralFastPath<T>::value, int> = 0> static size_t hash(T value) { return static_cast<size_t>( - Mix(Seed(), static_cast<std::make_unsigned_t<T>>(value))); + WeakMix(Seed() ^ static_cast<std::make_unsigned_t<T>>(value))); } // Overload of MixingHashState::hash() @@ -1085,6 +1137,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> { // Allow the HashState type-erasure implementation to invoke // RunCombinedUnordered() directly. friend class absl::HashState; + friend struct CombineRaw; // Workaround for MSVC bug. // We make the type copyable to fix the calling convention, even though we @@ -1094,6 +1147,14 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> { explicit MixingHashState(uint64_t state) : state_(state) {} + // Combines a raw value from e.g. integrals/floats/pointers/etc. This allows + // us to be consistent with IntegralFastPath when combining raw types, but + // optimize Read1To3 and Read4To8 differently for the string case. + static MixingHashState combine_raw(MixingHashState hash_state, + uint64_t value) { + return MixingHashState(WeakMix(hash_state.state_ ^ value)); + } + // Implementation of the base case for combine_contiguous where we actually // mix the bytes into the state. // Dispatch to different implementations of the combine_contiguous depending @@ -1107,6 +1168,49 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> { std::integral_constant<int, 8> /* sizeof_size_t */); + ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t CombineSmallContiguousImpl( + uint64_t state, const unsigned char* first, size_t len) { + ABSL_ASSUME(len <= 8); + uint64_t v; + if (len >= 4) { + v = Read4To8(first, len); + } else if (len > 0) { + v = Read1To3(first, len); + } else { + // Empty ranges have no effect. + return state; + } + return WeakMix(state ^ v); + } + + ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t CombineContiguousImpl9to16( + uint64_t state, const unsigned char* first, size_t len) { + ABSL_ASSUME(len >= 9); + ABSL_ASSUME(len <= 16); + // Note: any time one half of the mix function becomes zero it will fail to + // incorporate any bits from the other half. However, there is exactly 1 in + // 2^64 values for each side that achieve this, and only when the size is + // exactly 16 -- for smaller sizes there is an overlapping byte that makes + // this impossible unless the seed is *also* incredibly unlucky. + auto p = Read9To16(first, len); + return Mix(state ^ p.first, kMul ^ p.second); + } + + ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t CombineContiguousImpl17to32( + uint64_t state, const unsigned char* first, size_t len) { + ABSL_ASSUME(len >= 17); + ABSL_ASSUME(len <= 32); + // Do two mixes of overlapping 16-byte ranges in parallel to minimize + // latency. + const uint64_t m0 = + Mix(Read8(first) ^ kStaticRandomData[1], Read8(first + 8) ^ state); + + const unsigned char* tail_16b_ptr = first + (len - 16); + const uint64_t m1 = Mix(Read8(tail_16b_ptr) ^ kStaticRandomData[3], + Read8(tail_16b_ptr + 8) ^ state); + return m0 ^ m1; + } + // Slow dispatch path for calls to CombineContiguousImpl with a size argument // larger than PiecewiseChunkSize(). Has the same effect as calling // CombineContiguousImpl() repeatedly with the chunk stride size. @@ -1122,8 +1226,8 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> { // are in .second. static std::pair<uint64_t, uint64_t> Read9To16(const unsigned char* p, size_t len) { - uint64_t low_mem = absl::base_internal::UnalignedLoad64(p); - uint64_t high_mem = absl::base_internal::UnalignedLoad64(p + len - 8); + uint64_t low_mem = Read8(p); + uint64_t high_mem = Read8(p + len - 8); #ifdef ABSL_IS_LITTLE_ENDIAN uint64_t most_significant = high_mem; uint64_t least_significant = low_mem; @@ -1134,55 +1238,81 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> { return {least_significant, most_significant}; } + // Reads 8 bytes from p. + static uint64_t Read8(const unsigned char* p) { + // Suppress erroneous array bounds errors on GCC. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif + return absl::base_internal::UnalignedLoad64(p); +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + } + // Reads 4 to 8 bytes from p. Zero pads to fill uint64_t. + // TODO(b/384509507): consider optimizing this by not requiring the output to + // be equivalent to an integer load for 4/8 bytes. Currently, we rely on this + // behavior for the HashConsistentAcrossIntTypes test case. Ditto for + // Read1To3. static uint64_t Read4To8(const unsigned char* p, size_t len) { - uint32_t low_mem = absl::base_internal::UnalignedLoad32(p); - uint32_t high_mem = absl::base_internal::UnalignedLoad32(p + len - 4); -#ifdef ABSL_IS_LITTLE_ENDIAN - uint32_t most_significant = high_mem; - uint32_t least_significant = low_mem; -#else - uint32_t most_significant = low_mem; - uint32_t least_significant = high_mem; -#endif - return (static_cast<uint64_t>(most_significant) << (len - 4) * 8) | - least_significant; + // If `len < 8`, we duplicate bytes in the middle. + // E.g.: + // `ABCD` will be read as `ABCDABCD`. + // `ABCDE` will be read as `ABCDBCDE`. + // `ABCDEF` will be read as `ABCDCDEF`. + // `ABCDEFG` will be read as `ABCDDEFG`. + // We also do not care about endianness. On big-endian platforms, bytes will + // be shuffled (it's fine). We always shift low memory by 32, because that + // can be pipelined earlier. Reading high memory requires computing + // `p + len - 4`. + uint64_t most_significant = + static_cast<uint64_t>(absl::base_internal::UnalignedLoad32(p)) << 32; + uint64_t least_significant = + absl::base_internal::UnalignedLoad32(p + len - 4); + return most_significant | least_significant; } // Reads 1 to 3 bytes from p. Zero pads to fill uint32_t. static uint32_t Read1To3(const unsigned char* p, size_t len) { - // The trick used by this implementation is to avoid branches if possible. - unsigned char mem0 = p[0]; - unsigned char mem1 = p[len / 2]; - unsigned char mem2 = p[len - 1]; -#ifdef ABSL_IS_LITTLE_ENDIAN - unsigned char significant2 = mem2; - unsigned char significant1 = mem1; - unsigned char significant0 = mem0; -#else - unsigned char significant2 = mem0; - unsigned char significant1 = len == 2 ? mem0 : mem1; - unsigned char significant0 = mem2; -#endif - return static_cast<uint32_t>(significant0 | // - (significant1 << (len / 2 * 8)) | // - (significant2 << ((len - 1) * 8))); + // The trick used by this implementation is to avoid branches. + // We always read three bytes by duplicating. + // E.g., + // `A` is read as `AAA`. + // `AB` is read as `ABB`. + // `ABC` is read as `ABC`. + // We always shift `p[0]` so that it can be pipelined better. + // Other bytes require extra computation to find indices. + uint32_t mem0 = (static_cast<uint32_t>(p[0]) << 16) | p[len - 1]; + uint32_t mem1 = static_cast<uint32_t>(p[len / 2]) << 8; + return mem0 | mem1; } - ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t state, uint64_t v) { + ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t lhs, uint64_t rhs) { // Though the 128-bit product on AArch64 needs two instructions, it is // still a good balance between speed and hash quality. using MultType = absl::conditional_t<sizeof(size_t) == 4, uint64_t, uint128>; - // We do the addition in 64-bit space to make sure the 128-bit - // multiplication is fast. If we were to do it as MultType the compiler has - // to assume that the high word is non-zero and needs to perform 2 - // multiplications instead of one. - MultType m = state + v; - m *= kMul; + MultType m = lhs; + m *= rhs; return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2))); } + // Slightly lower latency than Mix, but with lower quality. The byte swap + // helps ensure that low bits still have high quality. + ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t WeakMix(uint64_t n) { + // WeakMix doesn't work well on 32-bit platforms so just use Mix. + if (sizeof(size_t) < 8) return Mix(n, kMul); +#ifdef __ARM_ACLE + // gbswap_64 compiles to `rev` on ARM, but `rbit` is better because it + // reverses bits rather than reversing bytes. + return __rbitll(n * kMul); +#else + return absl::gbswap_64(n * kMul); +#endif + } + // An extern to avoid bloat on a direct call to LowLevelHash() with fixed // values for both the seed and salt parameters. static uint64_t LowLevelHashImpl(const unsigned char* data, size_t len); @@ -1234,21 +1364,15 @@ inline uint64_t MixingHashState::CombineContiguousImpl( std::integral_constant<int, 4> /* sizeof_size_t */) { // For large values we use CityHash, for small ones we just use a // multiplicative hash. - uint64_t v; - if (len > 8) { - if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) { - return CombineLargeContiguousImpl32(state, first, len); - } - v = hash_internal::CityHash32(reinterpret_cast<const char*>(first), len); - } else if (len >= 4) { - v = Read4To8(first, len); - } else if (len > 0) { - v = Read1To3(first, len); - } else { - // Empty ranges have no effect. - return state; + if (len <= 8) { + return CombineSmallContiguousImpl(state, first, len); } - return Mix(state, v); + if (ABSL_PREDICT_TRUE(len <= PiecewiseChunkSize())) { + return Mix(state ^ hash_internal::CityHash32( + reinterpret_cast<const char*>(first), len), + kMul); + } + return CombineLargeContiguousImpl32(state, first, len); } // Overload of MixingHashState::CombineContiguousImpl() @@ -1257,38 +1381,19 @@ inline uint64_t MixingHashState::CombineContiguousImpl( std::integral_constant<int, 8> /* sizeof_size_t */) { // For large values we use LowLevelHash or CityHash depending on the platform, // for small ones we just use a multiplicative hash. - uint64_t v; - if (len > 16) { - if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) { - return CombineLargeContiguousImpl64(state, first, len); - } - v = Hash64(first, len); - } else if (len > 8) { - // This hash function was constructed by the ML-driven algorithm discovery - // using reinforcement learning. We fed the agent lots of inputs from - // microbenchmarks, SMHasher, low hamming distance from generated inputs and - // picked up the one that was good on micro and macrobenchmarks. - auto p = Read9To16(first, len); - uint64_t lo = p.first; - uint64_t hi = p.second; - // Rotation by 53 was found to be most often useful when discovering these - // hashing algorithms with ML techniques. - lo = absl::rotr(lo, 53); - state += kMul; - lo += state; - state ^= hi; - uint128 m = state; - m *= lo; - return static_cast<uint64_t>(m ^ (m >> 64)); - } else if (len >= 4) { - v = Read4To8(first, len); - } else if (len > 0) { - v = Read1To3(first, len); - } else { - // Empty ranges have no effect. - return state; + if (len <= 8) { + return CombineSmallContiguousImpl(state, first, len); + } + if (len <= 16) { + return CombineContiguousImpl9to16(state, first, len); + } + if (len <= 32) { + return CombineContiguousImpl17to32(state, first, len); + } + if (ABSL_PREDICT_TRUE(len <= PiecewiseChunkSize())) { + return Mix(state ^ Hash64(first, len), kMul); } - return Mix(state, v); + return CombineLargeContiguousImpl64(state, first, len); } struct AggregateBarrier {}; diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc b/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc index 6dc71cf7cd..ec02d7e7c5 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc +++ b/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc @@ -33,8 +33,6 @@ static uint64_t Mix(uint64_t v0, uint64_t v1) { uint64_t LowLevelHashLenGt16(const void* data, size_t len, uint64_t seed, const uint64_t salt[5]) { - // Prefetch the cacheline that data resides in. - PrefetchToLocalCache(data); const uint8_t* ptr = static_cast<const uint8_t*>(data); uint64_t starting_length = static_cast<uint64_t>(len); const uint8_t* last_16_ptr = ptr + starting_length - 16; @@ -42,8 +40,8 @@ uint64_t LowLevelHashLenGt16(const void* data, size_t len, uint64_t seed, if (len > 64) { // If we have more than 64 bytes, we're going to handle chunks of 64 - // bytes at a time. We're going to build up two separate hash states - // which we will then hash together. + // bytes at a time. We're going to build up four separate hash states + // which we will then hash together. This avoids short dependency chains. uint64_t duplicated_state0 = current_state; uint64_t duplicated_state1 = current_state; uint64_t duplicated_state2 = current_state; diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h b/contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h index 357c301c4a..92490b1a21 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h +++ b/contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h @@ -16,6 +16,7 @@ #define ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ #include <algorithm> +#include <cstdint> #include <ostream> #include <string> #include <vector> @@ -196,6 +197,7 @@ class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> { private: template <typename U> friend class SpyHashStateImpl; + friend struct CombineRaw; struct UnorderedCombinerCallback { std::vector<std::string> element_hash_representations; @@ -213,6 +215,12 @@ class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> { } }; + // Combines raw data from e.g. integrals/floats/pointers/etc. + static SpyHashStateImpl combine_raw(SpyHashStateImpl state, uint64_t value) { + const unsigned char* data = reinterpret_cast<const unsigned char*>(&value); + return SpyHashStateImpl::combine_contiguous(std::move(state), data, 8); + } + // This is true if SpyHashStateImpl<T> has been passed to a call of // AbslHashValue with the wrong type. This detects that the user called // AbslHashValue directly (because the hash state type does not match). diff --git a/contrib/restricted/abseil-cpp/absl/hash/ya.make b/contrib/restricted/abseil-cpp/absl/hash/ya.make index aeef6cea71..4281424c58 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/ya.make +++ b/contrib/restricted/abseil-cpp/absl/hash/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/log/absl_vlog_is_on.h b/contrib/restricted/abseil-cpp/absl/log/absl_vlog_is_on.h index 6bf6c41339..e4ec86db52 100644 --- a/contrib/restricted/abseil-cpp/absl/log/absl_vlog_is_on.h +++ b/contrib/restricted/abseil-cpp/absl/log/absl_vlog_is_on.h @@ -40,6 +40,8 @@ // last . and everything after it) is stripped from each filename prior to // matching, as is the special suffix "-inl". // +// Example: --vmodule=module_a=1,module_b=2 +// // Files are matched against globs in `--vmodule` in order, and the first match // determines the verbosity level. // diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc index 23c4a3b205..cec94218ec 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc +++ b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc @@ -14,10 +14,15 @@ #include "absl/log/internal/check_op.h" -#include <string.h> - +#include <cstring> #include <ostream> +#include <string> +#include <utility> +#include "absl/base/config.h" +#include "absl/base/nullability.h" +#include "absl/debugging/leak_check.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #ifdef _MSC_VER @@ -26,18 +31,13 @@ #include <strings.h> // for strcasecmp, but msvc does not have this header #endif -#include <sstream> -#include <string> - -#include "absl/base/config.h" -#include "absl/strings/str_cat.h" - namespace absl { ABSL_NAMESPACE_BEGIN namespace log_internal { #define ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(x) \ - template std::string* MakeCheckOpString(x, x, const char*) + template absl::Nonnull<const char*> MakeCheckOpString( \ + x, x, absl::Nonnull<const char*>) ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(bool); ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(int64_t); ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(uint64_t); @@ -53,7 +53,8 @@ ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const unsigned char*); ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const void*); #undef ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING -CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext) { +CheckOpMessageBuilder::CheckOpMessageBuilder( + absl::Nonnull<const char*> exprtext) { stream_ << exprtext << " ("; } @@ -62,9 +63,10 @@ std::ostream& CheckOpMessageBuilder::ForVar2() { return stream_; } -std::string* CheckOpMessageBuilder::NewString() { +absl::Nonnull<const char*> CheckOpMessageBuilder::NewString() { stream_ << ")"; - return new std::string(stream_.str()); + // There's no need to free this string since the process is crashing. + return absl::IgnoreLeak(new std::string(std::move(stream_).str()))->c_str(); } void MakeCheckOpValueString(std::ostream& os, const char v) { @@ -100,16 +102,19 @@ void MakeCheckOpValueString(std::ostream& os, const void* p) { } // Helper functions for string comparisons. -#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \ - std::string* Check##func##expected##Impl(const char* s1, const char* s2, \ - const char* exprtext) { \ - bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \ - if (equal == expected) { \ - return nullptr; \ - } else { \ - return new std::string( \ - absl::StrCat(exprtext, " (", s1, " vs. ", s2, ")")); \ - } \ +#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \ + absl::Nullable<const char*> Check##func##expected##Impl( \ + absl::Nullable<const char*> s1, absl::Nullable<const char*> s2, \ + absl::Nonnull<const char*> exprtext) { \ + bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \ + if (equal == expected) { \ + return nullptr; \ + } else { \ + /* There's no need to free this string since the process is crashing. */ \ + return absl::IgnoreLeak(new std::string(absl::StrCat(exprtext, " (", s1, \ + " vs. ", s2, ")"))) \ + ->c_str(); \ + } \ } DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true) DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false) diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h index 215922079c..d56aa3130e 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h @@ -32,7 +32,9 @@ #include <utility> #include "absl/base/attributes.h" +#include "absl/base/casts.h" #include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/log/internal/nullguard.h" #include "absl/log/internal/nullstream.h" @@ -62,7 +64,7 @@ #endif #define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \ - while (::std::string* absl_log_internal_check_op_result \ + while (absl::Nullable<const char*> absl_log_internal_check_op_result \ ABSL_LOG_INTERNAL_ATTRIBUTE_UNUSED_IF_STRIP_LOG = \ ::absl::log_internal::name##Impl( \ ::absl::log_internal::GetReferenceableValue(val1), \ @@ -70,37 +72,44 @@ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL( \ val1_text " " #op " " val2_text))) \ ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true) \ - ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_op_result).InternalStream() -#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2, \ - val2_text) \ - while (::std::string* absl_log_internal_qcheck_op_result = \ - ::absl::log_internal::name##Impl( \ - ::absl::log_internal::GetReferenceableValue(val1), \ - ::absl::log_internal::GetReferenceableValue(val2), \ - ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL( \ - val1_text " " #op " " val2_text))) \ - ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \ - ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_op_result).InternalStream() + ABSL_LOG_INTERNAL_CHECK(absl::implicit_cast<absl::Nonnull<const char*>>( \ + absl_log_internal_check_op_result)) \ + .InternalStream() +#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2, \ + val2_text) \ + while (absl::Nullable<const char*> absl_log_internal_qcheck_op_result = \ + ::absl::log_internal::name##Impl( \ + ::absl::log_internal::GetReferenceableValue(val1), \ + ::absl::log_internal::GetReferenceableValue(val2), \ + ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL( \ + val1_text " " #op " " val2_text))) \ + ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \ + ABSL_LOG_INTERNAL_QCHECK(absl::implicit_cast<absl::Nonnull<const char*>>( \ + absl_log_internal_qcheck_op_result)) \ + .InternalStream() #define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2, \ s2_text) \ - while (::std::string* absl_log_internal_check_strop_result = \ + while (absl::Nullable<const char*> absl_log_internal_check_strop_result = \ ::absl::log_internal::Check##func##expected##Impl( \ (s1), (s2), \ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \ " " s2_text))) \ ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true) \ - ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_strop_result) \ + ABSL_LOG_INTERNAL_CHECK(absl::implicit_cast<absl::Nonnull<const char*>>( \ + absl_log_internal_check_strop_result)) \ .InternalStream() #define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2, \ s2_text) \ - while (::std::string* absl_log_internal_qcheck_strop_result = \ + while (absl::Nullable<const char*> absl_log_internal_qcheck_strop_result = \ ::absl::log_internal::Check##func##expected##Impl( \ (s1), (s2), \ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \ " " s2_text))) \ ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \ - ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_strop_result) \ + ABSL_LOG_INTERNAL_QCHECK(absl::implicit_cast<absl::Nonnull<const char*>>( \ + absl_log_internal_qcheck_strop_result)) \ .InternalStream() + // This one is tricky: // * We must evaluate `val` exactly once, yet we need to do two things with it: // evaluate `.ok()` and (sometimes) `.ToString()`. @@ -125,37 +134,41 @@ // string literal and abort without doing any streaming. We don't need to // strip the call to stringify the non-ok `Status` as long as we don't log it; // dropping the `Status`'s message text is out of scope. -#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text) \ - for (::std::pair<const ::absl::Status*, ::std::string*> \ - absl_log_internal_check_ok_goo; \ - absl_log_internal_check_ok_goo.first = \ - ::absl::log_internal::AsStatus(val), \ - absl_log_internal_check_ok_goo.second = \ - ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \ - ? nullptr \ - : ::absl::status_internal::MakeCheckFailString( \ - absl_log_internal_check_ok_goo.first, \ - ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \ - " is OK")), \ - !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \ - ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true) \ - ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_ok_goo.second) \ +#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text) \ + for (::std::pair<absl::Nonnull<const ::absl::Status*>, \ + absl::Nullable<const char*>> \ + absl_log_internal_check_ok_goo; \ + absl_log_internal_check_ok_goo.first = \ + ::absl::log_internal::AsStatus(val), \ + absl_log_internal_check_ok_goo.second = \ + ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \ + ? nullptr \ + : ::absl::status_internal::MakeCheckFailString( \ + absl_log_internal_check_ok_goo.first, \ + ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \ + " is OK")), \ + !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \ + ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true) \ + ABSL_LOG_INTERNAL_CHECK(absl::implicit_cast<absl::Nonnull<const char*>>( \ + absl_log_internal_check_ok_goo.second)) \ .InternalStream() -#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text) \ - for (::std::pair<const ::absl::Status*, ::std::string*> \ - absl_log_internal_qcheck_ok_goo; \ - absl_log_internal_qcheck_ok_goo.first = \ - ::absl::log_internal::AsStatus(val), \ - absl_log_internal_qcheck_ok_goo.second = \ - ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok()) \ - ? nullptr \ - : ::absl::status_internal::MakeCheckFailString( \ - absl_log_internal_qcheck_ok_goo.first, \ - ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \ - " is OK")), \ - !ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());) \ - ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \ - ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_ok_goo.second) \ +#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text) \ + for (::std::pair<absl::Nonnull<const ::absl::Status*>, \ + absl::Nullable<const char*>> \ + absl_log_internal_qcheck_ok_goo; \ + absl_log_internal_qcheck_ok_goo.first = \ + ::absl::log_internal::AsStatus(val), \ + absl_log_internal_qcheck_ok_goo.second = \ + ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok()) \ + ? nullptr \ + : ::absl::status_internal::MakeCheckFailString( \ + absl_log_internal_qcheck_ok_goo.first, \ + ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \ + " is OK")), \ + !ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());) \ + ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \ + ABSL_LOG_INTERNAL_QCHECK(absl::implicit_cast<absl::Nonnull<const char*>>( \ + absl_log_internal_qcheck_ok_goo.second)) \ .InternalStream() namespace absl { @@ -166,8 +179,9 @@ template <typename T> class StatusOr; namespace status_internal { -ABSL_ATTRIBUTE_PURE_FUNCTION std::string* MakeCheckFailString( - const absl::Status* status, const char* prefix); +ABSL_ATTRIBUTE_PURE_FUNCTION absl::Nonnull<const char*> MakeCheckFailString( + absl::Nonnull<const absl::Status*> status, + absl::Nonnull<const char*> prefix); } // namespace status_internal namespace log_internal { @@ -175,9 +189,11 @@ namespace log_internal { // Convert a Status or a StatusOr to its underlying status value. // // (This implementation does not require a dep on absl::Status to work.) -inline const absl::Status* AsStatus(const absl::Status& s) { return &s; } +inline absl::Nonnull<const absl::Status*> AsStatus(const absl::Status& s) { + return &s; +} template <typename T> -const absl::Status* AsStatus(const absl::StatusOr<T>& s) { +absl::Nonnull<const absl::Status*> AsStatus(const absl::StatusOr<T>& s) { return &s.status(); } @@ -186,14 +202,14 @@ const absl::Status* AsStatus(const absl::StatusOr<T>& s) { class CheckOpMessageBuilder final { public: // Inserts `exprtext` and ` (` to the stream. - explicit CheckOpMessageBuilder(const char* exprtext); + explicit CheckOpMessageBuilder(absl::Nonnull<const char*> exprtext); ~CheckOpMessageBuilder() = default; // For inserting the first variable. std::ostream& ForVar1() { return stream_; } // For inserting the second variable (adds an intermediate ` vs. `). std::ostream& ForVar2(); // Get the result (inserts the closing `)`). - std::string* NewString(); + absl::Nonnull<const char*> NewString(); private: std::ostringstream stream_; @@ -336,11 +352,12 @@ using CheckOpStreamType = decltype(detect_specialization::Detect<T>(0)); // Build the error message string. Specify no inlining for code size. template <typename T1, typename T2> -ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* MakeCheckOpString( - T1 v1, T2 v2, const char* exprtext) ABSL_ATTRIBUTE_NOINLINE; +ABSL_ATTRIBUTE_RETURNS_NONNULL absl::Nonnull<const char*> MakeCheckOpString( + T1 v1, T2 v2, absl::Nonnull<const char*> exprtext) ABSL_ATTRIBUTE_NOINLINE; template <typename T1, typename T2> -std::string* MakeCheckOpString(T1 v1, T2 v2, const char* exprtext) { +absl::Nonnull<const char*> MakeCheckOpString( + T1 v1, T2 v2, absl::Nonnull<const char*> exprtext) { CheckOpMessageBuilder comb(exprtext); MakeCheckOpValueString(comb.ForVar1(), v1); MakeCheckOpValueString(comb.ForVar2(), v2); @@ -350,7 +367,8 @@ std::string* MakeCheckOpString(T1 v1, T2 v2, const char* exprtext) { // Add a few commonly used instantiations as extern to reduce size of objects // files. #define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \ - extern template std::string* MakeCheckOpString(x, x, const char*) + extern template absl::Nonnull<const char*> MakeCheckOpString( \ + x, x, absl::Nonnull<const char*>) ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool); ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t); ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t); @@ -374,7 +392,7 @@ ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*); ((::absl::LogSeverity::kFatal >= \ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL)) \ ? MakeCheckOpString<U1, U2>(v1, v2, exprtext) \ - : new std::string()) + : "") #else #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \ MakeCheckOpString<U1, U2>(v1, v2, exprtext) @@ -386,8 +404,8 @@ ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*); // type. #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op) \ template <typename T1, typename T2> \ - inline constexpr ::std::string* name##Impl(const T1& v1, const T2& v2, \ - const char* exprtext) { \ + inline constexpr absl::Nullable<const char*> name##Impl( \ + const T1& v1, const T2& v2, absl::Nonnull<const char*> exprtext) { \ using U1 = CheckOpStreamType<T1>; \ using U2 = CheckOpStreamType<T2>; \ return ABSL_PREDICT_TRUE(v1 op v2) \ @@ -395,8 +413,8 @@ ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*); : ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, U1(v1), \ U2(v2), exprtext); \ } \ - inline constexpr ::std::string* name##Impl(int v1, int v2, \ - const char* exprtext) { \ + inline constexpr absl::Nullable<const char*> name##Impl( \ + int v1, int v2, absl::Nonnull<const char*> exprtext) { \ return name##Impl<int, int>(v1, v2, exprtext); \ } @@ -409,14 +427,18 @@ ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >) #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL -std::string* CheckstrcmptrueImpl(const char* s1, const char* s2, - const char* exprtext); -std::string* CheckstrcmpfalseImpl(const char* s1, const char* s2, - const char* exprtext); -std::string* CheckstrcasecmptrueImpl(const char* s1, const char* s2, - const char* exprtext); -std::string* CheckstrcasecmpfalseImpl(const char* s1, const char* s2, - const char* exprtext); +absl::Nullable<const char*> CheckstrcmptrueImpl( + absl::Nullable<const char*> s1, absl::Nullable<const char*> s2, + absl::Nonnull<const char*> exprtext); +absl::Nullable<const char*> CheckstrcmpfalseImpl( + absl::Nullable<const char*> s1, absl::Nullable<const char*> s2, + absl::Nonnull<const char*> exprtext); +absl::Nullable<const char*> CheckstrcasecmptrueImpl( + absl::Nullable<const char*> s1, absl::Nullable<const char*> s2, + absl::Nonnull<const char*> exprtext); +absl::Nullable<const char*> CheckstrcasecmpfalseImpl( + absl::Nullable<const char*> s1, absl::Nullable<const char*> s2, + absl::Nonnull<const char*> exprtext); // `CHECK_EQ` and friends want to pass their arguments by reference, however // this winds up exposing lots of cases where people have defined and @@ -424,6 +446,8 @@ std::string* CheckstrcasecmpfalseImpl(const char* s1, const char* s2, // file), meaning they are not referenceable. This function avoids that problem // for integers (the most common cases) by overloading for every primitive // integer type, even the ones we discourage, and returning them by value. +// NOLINTBEGIN(runtime/int) +// NOLINTBEGIN(google-runtime-int) template <typename T> inline constexpr const T& GetReferenceableValue(const T& t) { return t; @@ -433,27 +457,25 @@ inline constexpr unsigned char GetReferenceableValue(unsigned char t) { return t; } inline constexpr signed char GetReferenceableValue(signed char t) { return t; } -inline constexpr short GetReferenceableValue(short t) { return t; } // NOLINT -inline constexpr unsigned short GetReferenceableValue( // NOLINT - unsigned short t) { // NOLINT +inline constexpr short GetReferenceableValue(short t) { return t; } +inline constexpr unsigned short GetReferenceableValue(unsigned short t) { return t; } inline constexpr int GetReferenceableValue(int t) { return t; } inline constexpr unsigned int GetReferenceableValue(unsigned int t) { return t; } -inline constexpr long GetReferenceableValue(long t) { return t; } // NOLINT -inline constexpr unsigned long GetReferenceableValue( // NOLINT - unsigned long t) { // NOLINT - return t; -} -inline constexpr long long GetReferenceableValue(long long t) { // NOLINT +inline constexpr long GetReferenceableValue(long t) { return t; } +inline constexpr unsigned long GetReferenceableValue(unsigned long t) { return t; } -inline constexpr unsigned long long GetReferenceableValue( // NOLINT - unsigned long long t) { // NOLINT +inline constexpr long long GetReferenceableValue(long long t) { return t; } +inline constexpr unsigned long long GetReferenceableValue( + unsigned long long t) { return t; } +// NOLINTEND(google-runtime-int) +// NOLINTEND(runtime/int) } // namespace log_internal ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc index 4e9b08af64..9e7722dac0 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc +++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc @@ -39,6 +39,7 @@ #include "absl/base/internal/strerror.h" #include "absl/base/internal/sysinfo.h" #include "absl/base/log_severity.h" +#include "absl/base/nullability.h" #include "absl/container/inlined_vector.h" #include "absl/debugging/internal/examine_stack.h" #include "absl/log/globals.h" @@ -47,6 +48,7 @@ #include "absl/log/internal/log_format.h" #include "absl/log/internal/log_sink_set.h" #include "absl/log/internal/proto.h" +#include "absl/log/internal/structured_proto.h" #include "absl/log/log_entry.h" #include "absl/log/log_sink.h" #include "absl/log/log_sink_registry.h" @@ -145,8 +147,8 @@ void WriteToStream(const char* data, void* os) { } // namespace struct LogMessage::LogMessageData final { - LogMessageData(const char* file, int line, absl::LogSeverity severity, - absl::Time timestamp); + LogMessageData(absl::Nonnull<const char*> file, int line, + absl::LogSeverity severity, absl::Time timestamp); LogMessageData(const LogMessageData&) = delete; LogMessageData& operator=(const LogMessageData&) = delete; @@ -161,7 +163,7 @@ struct LogMessage::LogMessageData final { bool is_perror; // Extra `LogSink`s to log to, in addition to `global_sinks`. - absl::InlinedVector<absl::LogSink*, 16> extra_sinks; + absl::InlinedVector<absl::Nonnull<absl::LogSink*>, 16> extra_sinks; // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded // non-sink targets (e.g. stderr, log files). bool extra_sinks_only; @@ -197,8 +199,8 @@ struct LogMessage::LogMessageData final { void FinalizeEncodingAndFormat(); }; -LogMessage::LogMessageData::LogMessageData(const char* file, int line, - absl::LogSeverity severity, +LogMessage::LogMessageData::LogMessageData(absl::Nonnull<const char*> file, + int line, absl::LogSeverity severity, absl::Time timestamp) : extra_sinks_only(false), manipulated(nullptr) { // Legacy defaults for LOG's ostream: @@ -268,7 +270,8 @@ void LogMessage::LogMessageData::FinalizeEncodingAndFormat() { absl::MakeSpan(string_buf).subspan(0, chars_written); } -LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity) +LogMessage::LogMessage(absl::Nonnull<const char*> file, int line, + absl::LogSeverity severity) : data_(absl::make_unique<LogMessageData>(file, line, severity, absl::Now())) { data_->first_fatal = false; @@ -281,11 +284,11 @@ LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity) LogBacktraceIfNeeded(); } -LogMessage::LogMessage(const char* file, int line, InfoTag) +LogMessage::LogMessage(absl::Nonnull<const char*> file, int line, InfoTag) : LogMessage(file, line, absl::LogSeverity::kInfo) {} -LogMessage::LogMessage(const char* file, int line, WarningTag) +LogMessage::LogMessage(absl::Nonnull<const char*> file, int line, WarningTag) : LogMessage(file, line, absl::LogSeverity::kWarning) {} -LogMessage::LogMessage(const char* file, int line, ErrorTag) +LogMessage::LogMessage(absl::Nonnull<const char*> file, int line, ErrorTag) : LogMessage(file, line, absl::LogSeverity::kError) {} LogMessage::~LogMessage() { @@ -348,13 +351,13 @@ LogMessage& LogMessage::WithPerror() { return *this; } -LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) { +LogMessage& LogMessage::ToSinkAlso(absl::Nonnull<absl::LogSink*> sink) { ABSL_INTERNAL_CHECK(sink, "null LogSink*"); data_->extra_sinks.push_back(sink); return *this; } -LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) { +LogMessage& LogMessage::ToSinkOnly(absl::Nonnull<absl::LogSink*> sink) { ABSL_INTERNAL_CHECK(sink, "null LogSink*"); data_->extra_sinks.clear(); data_->extra_sinks.push_back(sink); @@ -418,23 +421,26 @@ LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) { data_->manipulated << m; return *this; } +// NOLINTBEGIN(runtime/int) +// NOLINTBEGIN(google-runtime-int) template LogMessage& LogMessage::operator<<(const char& v); template LogMessage& LogMessage::operator<<(const signed char& v); template LogMessage& LogMessage::operator<<(const unsigned char& v); -template LogMessage& LogMessage::operator<<(const short& v); // NOLINT -template LogMessage& LogMessage::operator<<(const unsigned short& v); // NOLINT +template LogMessage& LogMessage::operator<<(const short& v); +template LogMessage& LogMessage::operator<<(const unsigned short& v); template LogMessage& LogMessage::operator<<(const int& v); template LogMessage& LogMessage::operator<<(const unsigned int& v); -template LogMessage& LogMessage::operator<<(const long& v); // NOLINT -template LogMessage& LogMessage::operator<<(const unsigned long& v); // NOLINT -template LogMessage& LogMessage::operator<<(const long long& v); // NOLINT -template LogMessage& LogMessage::operator<<( - const unsigned long long& v); // NOLINT +template LogMessage& LogMessage::operator<<(const long& v); +template LogMessage& LogMessage::operator<<(const unsigned long& v); +template LogMessage& LogMessage::operator<<(const long long& v); +template LogMessage& LogMessage::operator<<(const unsigned long long& v); template LogMessage& LogMessage::operator<<(void* const& v); template LogMessage& LogMessage::operator<<(const void* const& v); template LogMessage& LogMessage::operator<<(const float& v); template LogMessage& LogMessage::operator<<(const double& v); template LogMessage& LogMessage::operator<<(const bool& v); +// NOLINTEND(google-runtime-int) +// NOLINTEND(runtime/int) void LogMessage::Flush() { if (data_->entry.log_severity() < absl::MinLogLevel()) return; @@ -575,16 +581,17 @@ void LogMessage::LogBacktraceIfNeeded() { template <LogMessage::StringType str_type> void LogMessage::CopyToEncodedBuffer(absl::string_view str) { auto encoded_remaining_copy = data_->encoded_remaining(); + constexpr uint8_t tag_value = str_type == StringType::kLiteral + ? ValueTag::kStringLiteral + : ValueTag::kString; auto start = EncodeMessageStart( - EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(), + EventTag::kValue, + BufferSizeFor(tag_value, WireType::kLengthDelimited) + str.size(), &encoded_remaining_copy); // If the `logging.proto.Event.value` field header did not fit, // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and // `EncodeStringTruncate` will fail too. - if (EncodeStringTruncate(str_type == StringType::kLiteral - ? ValueTag::kStringLiteral - : ValueTag::kString, - str, &encoded_remaining_copy)) { + if (EncodeStringTruncate(tag_value, str, &encoded_remaining_copy)) { // The string may have been truncated, but the field header fit. EncodeMessageLength(start, &encoded_remaining_copy); data_->encoded_remaining() = encoded_remaining_copy; @@ -601,13 +608,14 @@ template void LogMessage::CopyToEncodedBuffer< template <LogMessage::StringType str_type> void LogMessage::CopyToEncodedBuffer(char ch, size_t num) { auto encoded_remaining_copy = data_->encoded_remaining(); + constexpr uint8_t tag_value = str_type == StringType::kLiteral + ? ValueTag::kStringLiteral + : ValueTag::kString; auto value_start = EncodeMessageStart( - EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num, + EventTag::kValue, + BufferSizeFor(tag_value, WireType::kLengthDelimited) + num, &encoded_remaining_copy); - auto str_start = EncodeMessageStart(str_type == StringType::kLiteral - ? ValueTag::kStringLiteral - : ValueTag::kString, - num, &encoded_remaining_copy); + auto str_start = EncodeMessageStart(tag_value, num, &encoded_remaining_copy); if (str_start.data()) { // The field headers fit. log_internal::AppendTruncated(ch, num, encoded_remaining_copy); @@ -625,6 +633,47 @@ template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>( template void LogMessage::CopyToEncodedBuffer< LogMessage::StringType::kNotLiteral>(char ch, size_t num); +template void LogMessage::CopyToEncodedBufferWithStructuredProtoField< + LogMessage::StringType::kLiteral>(StructuredProtoField field, + absl::string_view str); +template void LogMessage::CopyToEncodedBufferWithStructuredProtoField< + LogMessage::StringType::kNotLiteral>(StructuredProtoField field, + absl::string_view str); + +template <LogMessage::StringType str_type> +void LogMessage::CopyToEncodedBufferWithStructuredProtoField( + StructuredProtoField field, absl::string_view str) { + auto encoded_remaining_copy = data_->encoded_remaining(); + size_t encoded_field_size = BufferSizeForStructuredProtoField(field); + constexpr uint8_t tag_value = str_type == StringType::kLiteral + ? ValueTag::kStringLiteral + : ValueTag::kString; + auto start = EncodeMessageStart( + EventTag::kValue, + encoded_field_size + + BufferSizeFor(tag_value, WireType::kLengthDelimited) + str.size(), + &encoded_remaining_copy); + + // Write the encoded proto field. + if (!EncodeStructuredProtoField(field, encoded_remaining_copy)) { + // The header / field will not fit; zero `encoded_remaining()` so we + // don't write anything else later. + data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size()); + return; + } + + // Write the string, truncating if necessary. + if (!EncodeStringTruncate(ValueTag::kString, str, &encoded_remaining_copy)) { + // The length of the string itself did not fit; zero `encoded_remaining()` + // so the value is not encoded at all. + data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size()); + return; + } + + EncodeMessageLength(start, &encoded_remaining_copy); + data_->encoded_remaining() = encoded_remaining_copy; +} + // We intentionally don't return from these destructors. Disable MSVC's warning // about the destructor never returning as we do so intentionally here. #if defined(_MSC_VER) && !defined(__clang__) @@ -632,11 +681,11 @@ template void LogMessage::CopyToEncodedBuffer< #pragma warning(disable : 4722) #endif -LogMessageFatal::LogMessageFatal(const char* file, int line) +LogMessageFatal::LogMessageFatal(absl::Nonnull<const char*> file, int line) : LogMessage(file, line, absl::LogSeverity::kFatal) {} -LogMessageFatal::LogMessageFatal(const char* file, int line, - absl::string_view failure_msg) +LogMessageFatal::LogMessageFatal(absl::Nonnull<const char*> file, int line, + absl::Nonnull<const char*> failure_msg) : LogMessage(file, line, absl::LogSeverity::kFatal) { *this << "Check failed: " << failure_msg << " "; } @@ -646,7 +695,8 @@ LogMessageFatal::~LogMessageFatal() { FailWithoutStackTrace(); } -LogMessageDebugFatal::LogMessageDebugFatal(const char* file, int line) +LogMessageDebugFatal::LogMessageDebugFatal(absl::Nonnull<const char*> file, + int line) : LogMessage(file, line, absl::LogSeverity::kFatal) {} LogMessageDebugFatal::~LogMessageDebugFatal() { @@ -654,8 +704,8 @@ LogMessageDebugFatal::~LogMessageDebugFatal() { FailWithoutStackTrace(); } -LogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal(const char* file, - int line) +LogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal( + absl::Nonnull<const char*> file, int line) : LogMessage(file, line, absl::LogSeverity::kFatal) { SetFailQuietly(); } @@ -665,15 +715,17 @@ LogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() { FailQuietly(); } -LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line) +LogMessageQuietlyFatal::LogMessageQuietlyFatal(absl::Nonnull<const char*> file, + int line) : LogMessage(file, line, absl::LogSeverity::kFatal) { SetFailQuietly(); } -LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line, - absl::string_view failure_msg) +LogMessageQuietlyFatal::LogMessageQuietlyFatal( + absl::Nonnull<const char*> file, int line, + absl::Nonnull<const char*> failure_msg) : LogMessageQuietlyFatal(file, line) { - *this << "Check failed: " << failure_msg << " "; + *this << "Check failed: " << failure_msg << " "; } LogMessageQuietlyFatal::~LogMessageQuietlyFatal() { diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h index 0c067da9ad..7d0e403e3a 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h @@ -27,17 +27,21 @@ #ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_ #define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_ +#include <cstddef> #include <ios> #include <memory> #include <ostream> #include <streambuf> #include <string> +#include <type_traits> #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/errno_saver.h" #include "absl/base/log_severity.h" +#include "absl/base/nullability.h" #include "absl/log/internal/nullguard.h" +#include "absl/log/internal/structured_proto.h" #include "absl/log/log_entry.h" #include "absl/log/log_sink.h" #include "absl/strings/has_absl_stringify.h" @@ -49,6 +53,8 @@ ABSL_NAMESPACE_BEGIN namespace log_internal { constexpr int kLogMessageBufferSize = 15000; +enum class StructuredStringType; + class LogMessage { public: struct InfoTag {}; @@ -56,15 +62,15 @@ class LogMessage { struct ErrorTag {}; // Used for `LOG`. - LogMessage(const char* file, int line, + LogMessage(absl::Nonnull<const char*> file, int line, absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD; // These constructors are slightly smaller/faster to call; the severity is // curried into the function pointer. - LogMessage(const char* file, int line, + LogMessage(absl::Nonnull<const char*> file, int line, InfoTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE; - LogMessage(const char* file, int line, + LogMessage(absl::Nonnull<const char*> file, int line, WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE; - LogMessage(const char* file, int line, + LogMessage(absl::Nonnull<const char*> file, int line, ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE; LogMessage(const LogMessage&) = delete; LogMessage& operator=(const LogMessage&) = delete; @@ -95,59 +101,67 @@ class LogMessage { // of `errno`. LogMessage& WithPerror(); // Sends this message to `*sink` in addition to whatever other sinks it would - // otherwise have been sent to. `sink` must not be null. - LogMessage& ToSinkAlso(absl::LogSink* sink); - // Sends this message to `*sink` and no others. `sink` must not be null. - LogMessage& ToSinkOnly(absl::LogSink* sink); + // otherwise have been sent to. + LogMessage& ToSinkAlso(absl::Nonnull<absl::LogSink*> sink); + // Sends this message to `*sink` and no others. + LogMessage& ToSinkOnly(absl::Nonnull<absl::LogSink*> sink); // Don't call this method from outside this library. LogMessage& InternalStream() { return *this; } // By-value overloads for small, common types let us overlook common failures // to define globals and static data members (i.e. in a .cc file). - // clang-format off - // The CUDA toolchain cannot handle these <<<'s: + // NOLINTBEGIN(runtime/int) + // NOLINTBEGIN(google-runtime-int) + // clang-format off: The CUDA toolchain cannot handle these <<<'s LogMessage& operator<<(char v) { return operator<< <char>(v); } LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); } LogMessage& operator<<(unsigned char v) { return operator<< <unsigned char>(v); } - LogMessage& operator<<(signed short v) { // NOLINT - return operator<< <signed short>(v); // NOLINT + LogMessage& operator<<(signed short v) { + return operator<< <signed short>(v); } LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); } - LogMessage& operator<<(signed long v) { // NOLINT - return operator<< <signed long>(v); // NOLINT + LogMessage& operator<<(signed long v) { + return operator<< <signed long>(v); } - LogMessage& operator<<(signed long long v) { // NOLINT - return operator<< <signed long long>(v); // NOLINT + LogMessage& operator<<(signed long long v) { + return operator<< <signed long long>(v); } - LogMessage& operator<<(unsigned short v) { // NOLINT - return operator<< <unsigned short>(v); // NOLINT + LogMessage& operator<<(unsigned short v) { + return operator<< <unsigned short>(v); } LogMessage& operator<<(unsigned int v) { return operator<< <unsigned int>(v); } - LogMessage& operator<<(unsigned long v) { // NOLINT - return operator<< <unsigned long>(v); // NOLINT + LogMessage& operator<<(unsigned long v) { + return operator<< <unsigned long>(v); + } + LogMessage& operator<<(unsigned long long v) { + return operator<< <unsigned long long>(v); } - LogMessage& operator<<(unsigned long long v) { // NOLINT - return operator<< <unsigned long long>(v); // NOLINT + LogMessage& operator<<(absl::Nullable<void*> v) { + return operator<< <void*>(v); + } + LogMessage& operator<<(absl::Nullable<const void*> v) { + return operator<< <const void*>(v); } - LogMessage& operator<<(void* v) { return operator<< <void*>(v); } - LogMessage& operator<<(const void* v) { return operator<< <const void*>(v); } LogMessage& operator<<(float v) { return operator<< <float>(v); } LogMessage& operator<<(double v) { return operator<< <double>(v); } LogMessage& operator<<(bool v) { return operator<< <bool>(v); } // clang-format on + // NOLINTEND(google-runtime-int) + // NOLINTEND(runtime/int) // These overloads are more efficient since no `ostream` is involved. LogMessage& operator<<(const std::string& v); LogMessage& operator<<(absl::string_view v); // Handle stream manipulators e.g. std::endl. - LogMessage& operator<<(std::ostream& (*m)(std::ostream& os)); - LogMessage& operator<<(std::ios_base& (*m)(std::ios_base& os)); + LogMessage& operator<<(absl::Nonnull<std::ostream& (*)(std::ostream & os)> m); + LogMessage& operator<<( + absl::Nonnull<std::ios_base& (*)(std::ios_base & os)> m); // Literal strings. This allows us to record C string literals as literals in // the logging.proto.Value. @@ -206,6 +220,10 @@ class LogMessage { struct LogMessageData; // Opaque type containing message state friend class AsLiteralImpl; friend class StringifySink; + template <StructuredStringType str_type> + friend class AsStructuredStringTypeImpl; + template <typename T> + friend class AsStructuredValueImpl; // This streambuf writes directly into the structured logging buffer so that // arbitrary types can be encoded as string data (using @@ -236,6 +254,13 @@ class LogMessage { template <StringType str_type> void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE; + // Copies `field` to the encoded buffer, then appends `str` after it + // (truncating `str` if necessary to fit). + template <StringType str_type> + void CopyToEncodedBufferWithStructuredProtoField(StructuredProtoField field, + absl::string_view str) + ABSL_ATTRIBUTE_NOINLINE; + // Returns `true` if the message is fatal or enabled debug-fatal. bool IsFatal() const; @@ -255,7 +280,7 @@ class LogMessage { // We keep the data in a separate struct so that each instance of `LogMessage` // uses less stack space. - std::unique_ptr<LogMessageData> data_; + absl::Nonnull<std::unique_ptr<LogMessageData>> data_; }; // Helper class so that `AbslStringify()` can modify the LogMessage. @@ -273,7 +298,8 @@ class StringifySink final { } // For types that implement `AbslStringify` using `absl::Format()`. - friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) { + friend void AbslFormatFlush(absl::Nonnull<StringifySink*> sink, + absl::string_view v) { sink->Append(v); } @@ -315,27 +341,28 @@ LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) { // We instantiate these specializations in the library's TU to save space in // other TUs. Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be // emitting a function call either way. +// NOLINTBEGIN(runtime/int) +// NOLINTBEGIN(google-runtime-int) extern template LogMessage& LogMessage::operator<<(const char& v); extern template LogMessage& LogMessage::operator<<(const signed char& v); extern template LogMessage& LogMessage::operator<<(const unsigned char& v); -extern template LogMessage& LogMessage::operator<<(const short& v); // NOLINT -extern template LogMessage& LogMessage::operator<<( - const unsigned short& v); // NOLINT +extern template LogMessage& LogMessage::operator<<(const short& v); +extern template LogMessage& LogMessage::operator<<(const unsigned short& v); extern template LogMessage& LogMessage::operator<<(const int& v); +extern template LogMessage& LogMessage::operator<<(const unsigned int& v); +extern template LogMessage& LogMessage::operator<<(const long& v); +extern template LogMessage& LogMessage::operator<<(const unsigned long& v); +extern template LogMessage& LogMessage::operator<<(const long long& v); +extern template LogMessage& LogMessage::operator<<(const unsigned long long& v); extern template LogMessage& LogMessage::operator<<( - const unsigned int& v); // NOLINT -extern template LogMessage& LogMessage::operator<<(const long& v); // NOLINT -extern template LogMessage& LogMessage::operator<<( - const unsigned long& v); // NOLINT -extern template LogMessage& LogMessage::operator<<( - const long long& v); // NOLINT + absl::Nullable<void*> const& v); extern template LogMessage& LogMessage::operator<<( - const unsigned long long& v); // NOLINT -extern template LogMessage& LogMessage::operator<<(void* const& v); -extern template LogMessage& LogMessage::operator<<(const void* const& v); + absl::Nullable<const void*> const& v); extern template LogMessage& LogMessage::operator<<(const float& v); extern template LogMessage& LogMessage::operator<<(const double& v); extern template LogMessage& LogMessage::operator<<(const bool& v); +// NOLINTEND(google-runtime-int) +// NOLINTEND(runtime/int) extern template void LogMessage::CopyToEncodedBuffer< LogMessage::StringType::kLiteral>(absl::string_view str); @@ -351,9 +378,10 @@ extern template void LogMessage::CopyToEncodedBuffer< // message. class LogMessageFatal final : public LogMessage { public: - LogMessageFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD; - LogMessageFatal(const char* file, int line, - absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD; + LogMessageFatal(absl::Nonnull<const char*> file, + int line) ABSL_ATTRIBUTE_COLD; + LogMessageFatal(absl::Nonnull<const char*> file, int line, + absl::Nonnull<const char*> failure_msg) ABSL_ATTRIBUTE_COLD; [[noreturn]] ~LogMessageFatal(); }; @@ -362,7 +390,8 @@ class LogMessageFatal final : public LogMessage { // for DLOG(FATAL) variants. class LogMessageDebugFatal final : public LogMessage { public: - LogMessageDebugFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD; + LogMessageDebugFatal(absl::Nonnull<const char*> file, + int line) ABSL_ATTRIBUTE_COLD; ~LogMessageDebugFatal(); }; @@ -371,16 +400,19 @@ class LogMessageQuietlyDebugFatal final : public LogMessage { // DLOG(QFATAL) calls this instead of LogMessageQuietlyFatal to make sure the // destructor is not [[noreturn]] even if this is always FATAL as this is only // invoked when DLOG() is enabled. - LogMessageQuietlyDebugFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD; + LogMessageQuietlyDebugFatal(absl::Nonnull<const char*> file, + int line) ABSL_ATTRIBUTE_COLD; ~LogMessageQuietlyDebugFatal(); }; // Used for LOG(QFATAL) to make sure it's properly understood as [[noreturn]]. class LogMessageQuietlyFatal final : public LogMessage { public: - LogMessageQuietlyFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD; - LogMessageQuietlyFatal(const char* file, int line, - absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD; + LogMessageQuietlyFatal(absl::Nonnull<const char*> file, + int line) ABSL_ATTRIBUTE_COLD; + LogMessageQuietlyFatal(absl::Nonnull<const char*> file, int line, + absl::Nonnull<const char*> failure_msg) + ABSL_ATTRIBUTE_COLD; [[noreturn]] ~LogMessageQuietlyFatal(); }; diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc b/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc index eb699ae8e7..3513b15053 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc +++ b/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc @@ -35,9 +35,6 @@ void EncodeRawVarint(uint64_t value, size_t size, absl::Span<char> *buf) { } buf->remove_prefix(size); } -constexpr uint64_t MakeTagType(uint64_t tag, WireType type) { - return tag << 3 | static_cast<uint64_t>(type); -} } // namespace bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf) { diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/proto.h b/contrib/restricted/abseil-cpp/absl/log/internal/proto.h index c8d14acc47..20a9f3a80b 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/proto.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/proto.h @@ -199,23 +199,33 @@ constexpr uint64_t MaxVarintForSize(size_t size) { return size >= 10 ? (std::numeric_limits<uint64_t>::max)() : (static_cast<uint64_t>(1) << size * 7) - 1; } +constexpr uint64_t MakeTagType(uint64_t tag, WireType type) { + return tag << 3 | static_cast<uint64_t>(type); +} // `BufferSizeFor` returns a number of bytes guaranteed to be sufficient to -// store encoded fields of the specified WireTypes regardless of tag numbers and -// data values. This only makes sense for `WireType::kLengthDelimited` if you -// add in the length of the contents yourself, e.g. for string and bytes fields -// by adding the lengths of any encoded strings to the return value or for -// submessage fields by enumerating the fields you may encode into their -// contents. -constexpr size_t BufferSizeFor() { return 0; } -template <typename... T> -constexpr size_t BufferSizeFor(WireType type, T... tail) { - // tag_type + data + ... - return MaxVarintSize() + - (type == WireType::kVarint ? MaxVarintSize() : // - type == WireType::k64Bit ? 8 : // - type == WireType::k32Bit ? 4 : MaxVarintSize()) + // - BufferSizeFor(tail...); +// store encoded fields as `(tag, WireType)`, regardless of data values. This +// only makes sense for `WireType::kLengthDelimited` if you add in the length of +// the contents yourself, e.g. for string and bytes fields by adding the lengths +// of any encoded strings to the return value or for submessage fields by +// enumerating the fields you may encode into their contents. +constexpr size_t BufferSizeFor(uint64_t tag, WireType type) { + size_t buffer_size = VarintSize(MakeTagType(tag, type)); + switch (type) { + case WireType::kVarint: + buffer_size += MaxVarintSize(); + break; + case WireType::k64Bit: + buffer_size += size_t{8}; + break; + case WireType::kLengthDelimited: + buffer_size += MaxVarintSize(); + break; + case WireType::k32Bit: + buffer_size += size_t{4}; + break; + } + return buffer_size; } // absl::Span<const char> represents a view into the un-processed space in a diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/structured.h b/contrib/restricted/abseil-cpp/absl/log/internal/structured.h index 5223dbc310..50783dffd2 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/structured.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/structured.h @@ -20,9 +20,14 @@ #define ABSL_LOG_INTERNAL_STRUCTURED_H_ #include <ostream> +#include <string> +#include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/functional/any_invocable.h" #include "absl/log/internal/log_message.h" +#include "absl/log/internal/structured_proto.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" namespace absl { @@ -31,14 +36,16 @@ namespace log_internal { class ABSL_MUST_USE_RESULT AsLiteralImpl final { public: - explicit AsLiteralImpl(absl::string_view str) : str_(str) {} + explicit AsLiteralImpl(absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND) + : str_(str) {} AsLiteralImpl(const AsLiteralImpl&) = default; AsLiteralImpl& operator=(const AsLiteralImpl&) = default; private: absl::string_view str_; - friend std::ostream& operator<<(std::ostream& os, AsLiteralImpl as_literal) { + friend std::ostream& operator<<(std::ostream& os, + AsLiteralImpl&& as_literal) { return os << as_literal.str_; } void AddToMessage(log_internal::LogMessage& m) { @@ -51,6 +58,105 @@ class ABSL_MUST_USE_RESULT AsLiteralImpl final { } }; +enum class StructuredStringType { + kLiteral, + kNotLiteral, +}; + +// Structured log data for a string and associated structured proto field, +// both of which must outlive this object. +template <StructuredStringType str_type> +class ABSL_MUST_USE_RESULT AsStructuredStringTypeImpl final { + public: + constexpr AsStructuredStringTypeImpl( + absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND, + StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND) + : str_(str), field_(field) {} + + private: + absl::string_view str_; + StructuredProtoField field_; + + friend std::ostream& operator<<(std::ostream& os, + const AsStructuredStringTypeImpl& impl) { + return os << impl.str_; + } + void AddToMessage(LogMessage& m) const { + if (str_type == StructuredStringType::kLiteral) { + return m.CopyToEncodedBufferWithStructuredProtoField< + log_internal::LogMessage::StringType::kLiteral>(field_, str_); + } else { + return m.CopyToEncodedBufferWithStructuredProtoField< + log_internal::LogMessage::StringType::kNotLiteral>(field_, str_); + } + } + friend LogMessage& operator<<(LogMessage& m, + const AsStructuredStringTypeImpl& impl) { + impl.AddToMessage(m); + return m; + } +}; + +using AsStructuredLiteralImpl = + AsStructuredStringTypeImpl<StructuredStringType::kLiteral>; +using AsStructuredNotLiteralImpl = + AsStructuredStringTypeImpl<StructuredStringType::kNotLiteral>; + +// Structured log data for a stringifyable type T and associated structured +// proto field, both of which must outlive this object. +template <typename T> +class ABSL_MUST_USE_RESULT AsStructuredValueImpl final { + public: + using ValueFormatter = absl::AnyInvocable<std::string(T) const>; + + constexpr AsStructuredValueImpl( + T value ABSL_ATTRIBUTE_LIFETIME_BOUND, + StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND, + ValueFormatter value_formatter = + [](T value) { return absl::StrCat(value); }) + : value_(value), + field_(field), + value_formatter_(std::move(value_formatter)) {} + + private: + T value_; + StructuredProtoField field_; + ValueFormatter value_formatter_; + + friend std::ostream& operator<<(std::ostream& os, + const AsStructuredValueImpl& impl) { + return os << impl.value_formatter_(impl.value_); + } + void AddToMessage(LogMessage& m) const { + m.CopyToEncodedBufferWithStructuredProtoField< + log_internal::LogMessage::StringType::kNotLiteral>( + field_, value_formatter_(value_)); + } + friend LogMessage& operator<<(LogMessage& m, + const AsStructuredValueImpl& impl) { + impl.AddToMessage(m); + return m; + } +}; + +#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION + +// Template deduction guide so `AsStructuredValueImpl(42, data)` works +// without specifying the template type. +template <typename T> +AsStructuredValueImpl(T value, StructuredProtoField field) + -> AsStructuredValueImpl<T>; + +// Template deduction guide so `AsStructuredValueImpl(42, data, formatter)` +// works without specifying the template type. +template <typename T> +AsStructuredValueImpl( + T value, StructuredProtoField field, + typename AsStructuredValueImpl<T>::ValueFormatter value_formatter) + -> AsStructuredValueImpl<T>; + +#endif // ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION + } // namespace log_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/structured_proto.cc b/contrib/restricted/abseil-cpp/absl/log/internal/structured_proto.cc new file mode 100644 index 0000000000..e3829e4b5d --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/log/internal/structured_proto.cc @@ -0,0 +1,115 @@ +// +// Copyright 2024 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/log/internal/structured_proto.h" + +#include <cstdint> + +#include "absl/base/config.h" +#include "absl/log/internal/proto.h" +#include "absl/types/span.h" +#include "absl/types/variant.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { + +namespace { + +// Handles protobuf-encoding a type contained inside +// `StructuredProtoField::Varint`. +struct VarintEncoderVisitor final { + template <typename T> + bool operator()(T value) const { + return EncodeVarint(field_number, value, &buf); + } + + uint64_t field_number; + absl::Span<char>& buf; +}; + +// Handles protobuf-encoding a type contained inside +// `StructuredProtoField::I64`. +struct I64EncoderVisitor final { + bool operator()(uint64_t value) const { + return Encode64Bit(field_number, value, &buf); + } + + bool operator()(int64_t value) const { + return Encode64Bit(field_number, value, &buf); + } + + bool operator()(double value) const { + return EncodeDouble(field_number, value, &buf); + } + + uint64_t field_number; + absl::Span<char>& buf; +}; + +// Handles protobuf-encoding a type contained inside +// `StructuredProtoField::I32`. +struct I32EncoderVisitor final { + bool operator()(uint32_t value) const { + return Encode32Bit(field_number, value, &buf); + } + + bool operator()(int32_t value) const { + return Encode32Bit(field_number, value, &buf); + } + + bool operator()(float value) const { + return EncodeFloat(field_number, value, &buf); + } + + uint64_t field_number; + absl::Span<char>& buf; +}; + +// Handles protobuf-encoding a type contained inside `StructuredProtoField`. +struct EncoderVisitor final { + bool operator()(StructuredProtoField::Varint varint) { + return absl::visit(VarintEncoderVisitor{field_number, buf}, varint); + } + + bool operator()(StructuredProtoField::I64 i64) { + return absl::visit(I64EncoderVisitor{field_number, buf}, i64); + } + + bool operator()(StructuredProtoField::LengthDelimited length_delimited) { + // No need for a visitor, since `StructuredProtoField::LengthDelimited` is + // just `absl::Span<const char>`. + return EncodeBytes(field_number, length_delimited, &buf); + } + + bool operator()(StructuredProtoField::I32 i32) { + return absl::visit(I32EncoderVisitor{field_number, buf}, i32); + } + + uint64_t field_number; + absl::Span<char>& buf; +}; + +} // namespace + +bool EncodeStructuredProtoField(StructuredProtoField field, + absl::Span<char>& buf) { + return absl::visit(EncoderVisitor{field.field_number, buf}, field.value); +} + +} // namespace log_internal + +ABSL_NAMESPACE_END +} // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/structured_proto.h b/contrib/restricted/abseil-cpp/absl/log/internal/structured_proto.h new file mode 100644 index 0000000000..3ebc4beb55 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/log/internal/structured_proto.h @@ -0,0 +1,107 @@ +// 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. +// +// ----------------------------------------------------------------------------- +// File: log/internal/structured_proto.h +// ----------------------------------------------------------------------------- + +#ifndef ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_ +#define ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_ + +#include <cstddef> +#include <cstdint> + +#include "absl/base/config.h" +#include "absl/log/internal/proto.h" +#include "absl/types/span.h" +#include "absl/types/variant.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { + +// Sum type holding a single valid protobuf field suitable for encoding. +struct StructuredProtoField final { + // Numeric type encoded with varint encoding: + // https://protobuf.dev/programming-guides/encoding/#varints + using Varint = absl::variant<uint64_t, int64_t, uint32_t, int32_t, bool>; + + // Fixed-length 64-bit integer encoding: + // https://protobuf.dev/programming-guides/encoding/#non-varints + using I64 = absl::variant<uint64_t, int64_t, double>; + + // Length-delimited record type (string, sub-message): + // https://protobuf.dev/programming-guides/encoding/#length-types + using LengthDelimited = absl::Span<const char>; + + // Fixed-length 32-bit integer encoding: + // https://protobuf.dev/programming-guides/encoding/#non-varints + using I32 = absl::variant<uint32_t, int32_t, float>; + + // Valid record type: + // https://protobuf.dev/programming-guides/encoding/#structure + using Value = absl::variant<Varint, I64, LengthDelimited, I32>; + + // Field number for the protobuf value. + uint64_t field_number; + + // Value to encode. + Value value; +}; + +// Estimates the number of bytes needed to encode `field` using +// protobuf encoding. +// +// The returned value might be larger than the actual number of bytes needed. +inline size_t BufferSizeForStructuredProtoField(StructuredProtoField field) { + // Visitor to estimate the number of bytes of one of the types contained + // inside `StructuredProtoField`. + struct BufferSizeVisitor final { + size_t operator()(StructuredProtoField::Varint /*unused*/) { + return BufferSizeFor(field_number, WireType::kVarint); + } + + size_t operator()(StructuredProtoField::I64 /*unused*/) { + return BufferSizeFor(field_number, WireType::k64Bit); + } + + size_t operator()(StructuredProtoField::LengthDelimited length_delimited) { + return BufferSizeFor(field_number, WireType::kLengthDelimited) + + length_delimited.size(); + } + + size_t operator()(StructuredProtoField::I32 /*unused*/) { + return BufferSizeFor(field_number, WireType::k32Bit); + } + + uint64_t field_number; + }; + + return absl::visit(BufferSizeVisitor{field.field_number}, field.value); +} + +// Encodes `field` into `buf` using protobuf encoding. +// +// On success, returns `true` and advances `buf` to the end of +// the bytes consumed. +// +// On failure (if `buf` was too small), returns `false`. +bool EncodeStructuredProtoField(StructuredProtoField field, + absl::Span<char>& buf); + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_ diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.cc b/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.cc index b578850041..f7c61bed52 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.cc +++ b/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.cc @@ -207,7 +207,14 @@ int PrependVModuleLocked(absl::string_view module_pattern, int log_level) get_vmodule_info().erase( std::remove_if(++iter, get_vmodule_info().end(), [module_pattern](const VModuleInfo& info) { - return FNMatch(info.module_pattern, module_pattern); + // Remove the previous pattern if it is less generic than + // the new one. For example, if the new pattern + // `module_pattern` is "foo*" and the previous pattern + // `info.module_pattern` is "foo", we should remove the + // previous pattern. Because the new pattern "foo*" will + // match all the files that the previous pattern "foo" + // matches. + return FNMatch(module_pattern, info.module_pattern); }), get_vmodule_info().cend()); return old_log_level.value_or(global_v); diff --git a/contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h b/contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h index bf76cceeae..3aa3bf6795 100644 --- a/contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h +++ b/contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h @@ -22,6 +22,7 @@ #define ABSL_LOG_LOG_SINK_REGISTRY_H_ #include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/log/internal/log_sink_set.h" #include "absl/log/log_sink.h" @@ -43,8 +44,10 @@ ABSL_NAMESPACE_BEGIN // sink instead which writes them to `stderr`. // // Do not call these inside `absl::LogSink::Send`. -inline void AddLogSink(absl::LogSink* sink) { log_internal::AddLogSink(sink); } -inline void RemoveLogSink(absl::LogSink* sink) { +inline void AddLogSink(absl::Nonnull<absl::LogSink*> sink) { + log_internal::AddLogSink(sink); +} +inline void RemoveLogSink(absl::Nonnull<absl::LogSink*> sink) { log_internal::RemoveLogSink(sink); } diff --git a/contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h b/contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h index 399e604deb..a383066741 100644 --- a/contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h +++ b/contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h @@ -40,8 +40,8 @@ enum class MockLogDefault { kIgnoreUnexpected, kDisallowUnexpected }; // ScopedMockLog // -// ScopedMockLog is a LogSink that intercepts LOG() messages issued during its -// lifespan. +// ScopedMockLog is a LogSink that intercepts LOG() messages issued by all +// threads when active. // // Using this together with GoogleTest, it's easy to test how a piece of code // calls LOG(). The typical usage, noting the distinction between diff --git a/contrib/restricted/abseil-cpp/absl/log/structured.h b/contrib/restricted/abseil-cpp/absl/log/structured.h index 9ad69fbdcd..89d241e4f5 100644 --- a/contrib/restricted/abseil-cpp/absl/log/structured.h +++ b/contrib/restricted/abseil-cpp/absl/log/structured.h @@ -32,6 +32,7 @@ #include <ostream> +#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/log/internal/structured.h" #include "absl/strings/string_view.h" @@ -60,7 +61,11 @@ ABSL_NAMESPACE_BEGIN // int line) { // LOG(LEVEL(severity)).AtLocation(file, line) << absl::LogAsLiteral(str); // } -inline log_internal::AsLiteralImpl LogAsLiteral(absl::string_view s) { +// +// `LogAsLiteral` should only be used as a streaming operand and not, for +// example, as a local variable initializer. +inline log_internal::AsLiteralImpl LogAsLiteral( + absl::string_view s ABSL_ATTRIBUTE_LIFETIME_BOUND) { return log_internal::AsLiteralImpl(s); } diff --git a/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h b/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h index f7539df4ea..c33fcc173d 100644 --- a/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h +++ b/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h @@ -40,6 +40,8 @@ // last . and everything after it) is stripped from each filename prior to // matching, as is the special suffix "-inl". // +// Example: --vmodule=module_a=1,module_b=2 +// // Files are matched against globs in `--vmodule` in order, and the first match // determines the verbosity level. // diff --git a/contrib/restricted/abseil-cpp/absl/log/ya.make b/contrib/restricted/abseil-cpp/absl/log/ya.make index 743000eb5e..6e721ca636 100644 --- a/contrib/restricted/abseil-cpp/absl/log/ya.make +++ b/contrib/restricted/abseil-cpp/absl/log/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base @@ -48,6 +48,7 @@ SRCS( internal/log_sink_set.cc internal/nullguard.cc internal/proto.cc + internal/structured_proto.cc internal/vlog_config.cc log_entry.cc log_sink.cc diff --git a/contrib/restricted/abseil-cpp/absl/memory/ya.make b/contrib/restricted/abseil-cpp/absl/memory/ya.make index 7125e13df7..b8267ff47e 100644 --- a/contrib/restricted/abseil-cpp/absl/memory/ya.make +++ b/contrib/restricted/abseil-cpp/absl/memory/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240722.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20250127.0.tar.gz) PEERDIR( contrib/restricted/abseil-cpp/absl/meta diff --git a/contrib/restricted/abseil-cpp/absl/meta/type_traits.h b/contrib/restricted/abseil-cpp/absl/meta/type_traits.h index ded55820a3..02da0674a8 100644 --- a/contrib/restricted/abseil-cpp/absl/meta/type_traits.h +++ b/contrib/restricted/abseil-cpp/absl/meta/type_traits.h @@ -503,10 +503,11 @@ using swap_internal::Swap; // remove the condition. // // Clang on all platforms fails to detect that a type with a user-provided -// move-assignment operator is not trivially relocatable. So in fact we -// opt out of Clang altogether, for now. +// move-assignment operator is not trivially relocatable so we also check for +// is_trivially_move_assignable for Clang. // -// TODO(b/325479096): Remove the opt-out once Clang's behavior is fixed. +// TODO(b/325479096): Remove the Clang is_trivially_move_assignable version once +// Clang's behavior is fixed. // // According to https://github.com/abseil/abseil-cpp/issues/1479, this does not // work with NVCC either. @@ -516,6 +517,15 @@ using swap_internal::Swap; template <class T> struct is_trivially_relocatable : std::integral_constant<bool, __is_trivially_relocatable(T)> {}; +#elif ABSL_HAVE_BUILTIN(__is_trivially_relocatable) && defined(__clang__) && \ + !(defined(_WIN32) || defined(_WIN64)) && !defined(__APPLE__) && \ + !defined(__NVCC__) +template <class T> +struct is_trivially_relocatable + : std::integral_constant< + bool, std::is_trivially_copyable<T>::value || + (__is_trivially_relocatable(T) && + std::is_trivially_move_assignable<T>::value)> {}; #else // Otherwise we use a fallback that detects only those types we can feasibly // detect. Any type that is trivially copyable is by definition trivially @@ -648,9 +658,9 @@ struct IsView<std::span<T>> : std::true_type {}; // Until then, we consider an assignment from an "owner" (such as std::string) // to a "view" (such as std::string_view) to be a lifetime-bound assignment. template <typename T, typename U> -using IsLifetimeBoundAssignment = - std::integral_constant<bool, IsView<absl::remove_cvref_t<T>>::value && - IsOwner<absl::remove_cvref_t<U>>::value>; +using IsLifetimeBoundAssignment = absl::conjunction< + std::integral_constant<bool, !std::is_lvalue_reference<U>::value>, + IsOwner<absl::remove_cvref_t<U>>, IsView<absl::remove_cvref_t<T>>>; } // namespace type_traits_internal diff --git a/contrib/restricted/abseil-cpp/absl/meta/ya.make b/contrib/restricted/abseil-cpp/absl/meta/ya.make index 8b2d3b836b..0260771d82 100644 --- a/contrib/restricted/abseil-cpp/absl/meta/ya.make +++ b/contrib/restricted/abseil-cpp/absl/meta/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240722.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20250127.0.tar.gz) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/numeric/int128.h b/contrib/restricted/abseil-cpp/absl/numeric/int128.h index 5a067d17b3..ae736b2846 100644 --- a/contrib/restricted/abseil-cpp/absl/numeric/int128.h +++ b/contrib/restricted/abseil-cpp/absl/numeric/int128.h @@ -216,7 +216,11 @@ class // Support for absl::Hash. template <typename H> friend H AbslHashValue(H h, uint128 v) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return H::combine(std::move(h), static_cast<unsigned __int128>(v)); +#else return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v)); +#endif } // Support for absl::StrCat() etc. @@ -458,7 +462,11 @@ class int128 { // Support for absl::Hash. template <typename H> friend H AbslHashValue(H h, int128 v) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return H::combine(std::move(h), v.v_); +#else return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); +#endif } // Support for absl::StrCat() etc. @@ -781,16 +789,20 @@ constexpr uint128::operator unsigned __int128() const { // Conversion operators to floating point types. inline uint128::operator float() const { - return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64); + // Note: This method might return Inf. + constexpr float pow_2_64 = 18446744073709551616.0f; + return static_cast<float>(lo_) + static_cast<float>(hi_) * pow_2_64; } inline uint128::operator double() const { - return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64); + constexpr double pow_2_64 = 18446744073709551616.0; + return static_cast<double>(lo_) + static_cast<double>(hi_) * pow_2_64; } inline uint128::operator long double() const { + constexpr long double pow_2_64 = 18446744073709551616.0L; return static_cast<long double>(lo_) + - std::ldexp(static_cast<long double>(hi_), 64); + static_cast<long double>(hi_) * pow_2_64; } // Comparison operators. diff --git a/contrib/restricted/abseil-cpp/absl/numeric/int128_have_intrinsic.inc b/contrib/restricted/abseil-cpp/absl/numeric/int128_have_intrinsic.inc index 51e4b9d485..216115a412 100644 --- a/contrib/restricted/abseil-cpp/absl/numeric/int128_have_intrinsic.inc +++ b/contrib/restricted/abseil-cpp/absl/numeric/int128_have_intrinsic.inc @@ -170,27 +170,29 @@ inline int128::operator float() const { // complement overwhelms the precision of the mantissa. // // Also check to make sure we don't negate Int128Min() + constexpr float pow_2_64 = 18446744073709551616.0f; return v_ < 0 && *this != Int128Min() ? -static_cast<float>(-*this) : static_cast<float>(Int128Low64(*this)) + - std::ldexp(static_cast<float>(Int128High64(*this)), 64); + static_cast<float>(Int128High64(*this)) * pow_2_64; } inline int128::operator double() const { // See comment in int128::operator float() above. + constexpr double pow_2_64 = 18446744073709551616.0; return v_ < 0 && *this != Int128Min() ? -static_cast<double>(-*this) : static_cast<double>(Int128Low64(*this)) + - std::ldexp(static_cast<double>(Int128High64(*this)), 64); + static_cast<double>(Int128High64(*this)) * pow_2_64; } inline int128::operator long double() const { // See comment in int128::operator float() above. + constexpr long double pow_2_64 = 18446744073709551616.0L; return v_ < 0 && *this != Int128Min() ? -static_cast<long double>(-*this) : static_cast<long double>(Int128Low64(*this)) + - std::ldexp(static_cast<long double>(Int128High64(*this)), - 64); + static_cast<long double>(Int128High64(*this)) * pow_2_64; } #endif // Clang on PowerPC diff --git a/contrib/restricted/abseil-cpp/absl/numeric/int128_no_intrinsic.inc b/contrib/restricted/abseil-cpp/absl/numeric/int128_no_intrinsic.inc index 195b7452ea..a7cdceabfa 100644 --- a/contrib/restricted/abseil-cpp/absl/numeric/int128_no_intrinsic.inc +++ b/contrib/restricted/abseil-cpp/absl/numeric/int128_no_intrinsic.inc @@ -139,26 +139,29 @@ inline int128::operator float() const { // complement overwhelms the precision of the mantissa. // // Also check to make sure we don't negate Int128Min() + constexpr float pow_2_64 = 18446744073709551616.0f; return hi_ < 0 && *this != Int128Min() ? -static_cast<float>(-*this) : static_cast<float>(lo_) + - std::ldexp(static_cast<float>(hi_), 64); + static_cast<float>(hi_) * pow_2_64; } inline int128::operator double() const { // See comment in int128::operator float() above. + constexpr double pow_2_64 = 18446744073709551616.0; return hi_ < 0 && *this != Int128Min() ? -static_cast<double>(-*this) : static_cast<double>(lo_) + - std::ldexp(static_cast<double>(hi_), 64); + static_cast<double>(hi_) * pow_2_64; } inline int128::operator long double() const { // See comment in int128::operator float() above. + constexpr long double pow_2_64 = 18446744073709551616.0L; return hi_ < 0 && *this != Int128Min() ? -static_cast<long double>(-*this) : static_cast<long double>(lo_) + - std::ldexp(static_cast<long double>(hi_), 64); + static_cast<long double>(hi_) * pow_2_64; } // Comparison operators. diff --git a/contrib/restricted/abseil-cpp/absl/numeric/ya.make b/contrib/restricted/abseil-cpp/absl/numeric/ya.make index ff64443a48..4abce215fe 100644 --- a/contrib/restricted/abseil-cpp/absl/numeric/ya.make +++ b/contrib/restricted/abseil-cpp/absl/numeric/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) ADDINCL( GLOBAL contrib/restricted/abseil-cpp diff --git a/contrib/restricted/abseil-cpp/absl/profiling/ya.make b/contrib/restricted/abseil-cpp/absl/profiling/ya.make index e5a60c5c9d..8ce0b25df3 100644 --- a/contrib/restricted/abseil-cpp/absl/profiling/ya.make +++ b/contrib/restricted/abseil-cpp/absl/profiling/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) ADDINCL( GLOBAL contrib/restricted/abseil-cpp diff --git a/contrib/restricted/abseil-cpp/absl/random/bernoulli_distribution.h b/contrib/restricted/abseil-cpp/absl/random/bernoulli_distribution.h index d81b6ae6b1..10c24e6221 100644 --- a/contrib/restricted/abseil-cpp/absl/random/bernoulli_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/bernoulli_distribution.h @@ -15,10 +15,12 @@ #ifndef ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_ #define ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_ +#include <cassert> #include <cstdint> #include <istream> -#include <limits> +#include <ostream> +#include "absl/base/config.h" #include "absl/base/optimization.h" #include "absl/random/internal/fast_uniform_bits.h" #include "absl/random/internal/iostream_state_saver.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/beta_distribution.h b/contrib/restricted/abseil-cpp/absl/random/beta_distribution.h index 432c51612a..a3623453b3 100644 --- a/contrib/restricted/abseil-cpp/absl/random/beta_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/beta_distribution.h @@ -17,14 +17,16 @@ #include <cassert> #include <cmath> +#include <cstdint> #include <istream> #include <limits> #include <ostream> #include <type_traits> +#include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/meta/type_traits.h" #include "absl/random/internal/fast_uniform_bits.h" -#include "absl/random/internal/fastmath.h" #include "absl/random/internal/generate_real.h" #include "absl/random/internal/iostream_state_saver.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h b/contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h index ac26d9d4ab..40e7b60739 100644 --- a/contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h +++ b/contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h @@ -24,13 +24,14 @@ #ifndef ABSL_RANDOM_BIT_GEN_REF_H_ #define ABSL_RANDOM_BIT_GEN_REF_H_ +#include <cstdint> #include <limits> #include <type_traits> #include <utility> #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/fast_type_id.h" -#include "absl/base/macros.h" #include "absl/meta/type_traits.h" #include "absl/random/internal/distribution_caller.h" #include "absl/random/internal/fast_uniform_bits.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.cc b/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.cc index 081accee52..247faa84fb 100644 --- a/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.cc +++ b/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.cc @@ -14,6 +14,16 @@ #include "absl/random/discrete_distribution.h" +#include <cassert> +#include <cmath> +#include <cstddef> +#include <iterator> +#include <numeric> +#include <utility> +#include <vector> + +#include "absl/base/config.h" + namespace absl { ABSL_NAMESPACE_BEGIN namespace random_internal { diff --git a/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.h b/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.h index 171aa11a1e..f579a64a8d 100644 --- a/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/discrete_distribution.h @@ -16,14 +16,16 @@ #define ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_ #include <cassert> -#include <cmath> +#include <cstddef> +#include <initializer_list> #include <istream> #include <limits> -#include <numeric> +#include <ostream> #include <type_traits> #include <utility> #include <vector> +#include "absl/base/config.h" #include "absl/random/bernoulli_distribution.h" #include "absl/random/internal/iostream_state_saver.h" #include "absl/random/uniform_int_distribution.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h b/contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h index b5caf8a1e1..4af2fb482b 100644 --- a/contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h @@ -21,6 +21,7 @@ #include <limits> #include <type_traits> +#include "absl/base/config.h" #include "absl/meta/type_traits.h" #include "absl/random/internal/fast_uniform_bits.h" #include "absl/random/internal/generate_real.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/gaussian_distribution.h b/contrib/restricted/abseil-cpp/absl/random/gaussian_distribution.h index 4b07a5c0af..ce84d4a56b 100644 --- a/contrib/restricted/abseil-cpp/absl/random/gaussian_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/gaussian_distribution.h @@ -26,6 +26,7 @@ #include <cstdint> #include <istream> #include <limits> +#include <ostream> #include <type_traits> #include "absl/base/config.h" @@ -57,7 +58,7 @@ class ABSL_DLL gaussian_distribution_base { bool neg); // Constants used for the gaussian distribution. - static constexpr double kR = 3.442619855899; // Start of the tail. + static constexpr double kR = 3.442619855899; // Start of the tail. static constexpr double kRInv = 0.29047645161474317; // ~= (1.0 / kR) . static constexpr double kV = 9.91256303526217e-3; static constexpr uint64_t kMask = 0x07f; diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/chi_square.cc b/contrib/restricted/abseil-cpp/absl/random/internal/chi_square.cc index fbe0173299..4cfc4d7c52 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/chi_square.cc +++ b/contrib/restricted/abseil-cpp/absl/random/internal/chi_square.cc @@ -25,9 +25,7 @@ namespace { #if defined(__EMSCRIPTEN__) // Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found. -inline double fma(double x, double y, double z) { - return (x * y) + z; -} +inline double fma(double x, double y, double z) { return (x * y) + z; } #endif // Use Horner's method to evaluate a polynomial. @@ -105,9 +103,8 @@ double normal_survival(double z) { // p-value, usually using bisection. Also known by the name CRITCHI. double ChiSquareValue(int dof, double p) { static constexpr double kChiEpsilon = - 0.000001; // Accuracy of the approximation. - static constexpr double kChiMax = - 99999.0; // Maximum chi-squared value. + 0.000001; // Accuracy of the approximation. + static constexpr double kChiMax = 99999.0; // Maximum chi-squared value. const double p_value = 1.0 - p; if (dof < 1 || p_value > 1.0) { diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h b/contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h index 0f162a4e29..2534ca951d 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h @@ -17,11 +17,13 @@ #ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_ #define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_ -#include <utility> +#include <tuple> #include <type_traits> +#include <utility> #include "absl/base/config.h" #include "absl/base/internal/fast_type_id.h" +#include "absl/meta/type_traits.h" #include "absl/utility/utility.h" namespace absl { diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/distribution_test_util.h b/contrib/restricted/abseil-cpp/absl/random/internal/distribution_test_util.h index 6d94cf6c97..1189340e3a 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/distribution_test_util.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/distribution_test_util.h @@ -16,9 +16,9 @@ #define ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_ #include <cstddef> -#include <iostream> -#include <vector> +#include <ostream> +#include "absl/base/config.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" @@ -96,7 +96,7 @@ double BetaIncomplete(double x, double p, double q); // https://www.jstor.org/stable/2346798 // https://www.jstor.org/stable/2346887 // -// BetaIncompleteInv(p, q, beta, alhpa) +// BetaIncompleteInv(p, q, beta, alpha) // `p` is beta parameter p, `q` is beta parameter q. // `alpha` is the value of the lower tail area. // diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/iostream_state_saver.h b/contrib/restricted/abseil-cpp/absl/random/internal/iostream_state_saver.h index e6e242ee1e..0f56bcb834 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/iostream_state_saver.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/iostream_state_saver.h @@ -16,10 +16,14 @@ #define ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_ #include <cmath> -#include <iostream> +#include <cstdint> +#include <ios> +#include <istream> #include <limits> +#include <ostream> #include <type_traits> +#include "absl/base/config.h" #include "absl/meta/type_traits.h" #include "absl/numeric/int128.h" @@ -95,7 +99,6 @@ typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value, null_state_saver<T>> make_ostream_state_saver(T& is, // NOLINT(runtime/references) std::ios_base::fmtflags flags = std::ios_base::dec) { - std::cerr << "null_state_saver"; using result_type = null_state_saver<T>; return result_type(is, flags); } diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h b/contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h index cfaeeeef1a..a09f035dc3 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h @@ -51,10 +51,8 @@ struct MockSingleOverload<DistrT, ValidatorT, Ret(MockingBitGen&, Args...)> { auto gmock_Call(MockURBG& gen, const ::testing::Matcher<Args>&... matchers) -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT()) .gmock_Call(matchers...)) { - static_assert( - std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value || - std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value, - "Mocking requires an absl::MockingBitGen"); + static_assert(std::is_base_of<MockingBitGen, MockURBG>::value, + "Mocking requires an absl::MockingBitGen"); return MockHelpers::MockFor<KeyT>(gen, ValidatorT()) .gmock_Call(matchers...); } @@ -74,10 +72,8 @@ struct MockSingleOverload<DistrT, ValidatorT, const ::testing::Matcher<Args>&... matchers) -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT()) .gmock_Call(matcher, matchers...)) { - static_assert( - std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value || - std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value, - "Mocking requires an absl::MockingBitGen"); + static_assert(std::is_base_of<MockingBitGen, MockURBG>::value, + "Mocking requires an absl::MockingBitGen"); return MockHelpers::MockFor<KeyT>(gen, ValidatorT()) .gmock_Call(matcher, matchers...); } diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/platform.h b/contrib/restricted/abseil-cpp/absl/random/internal/platform.h index d779f481dd..bd2993e181 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/platform.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/platform.h @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + #ifndef ABSL_RANDOM_INTERNAL_PLATFORM_H_ #define ABSL_RANDOM_INTERNAL_PLATFORM_H_ @@ -134,7 +136,14 @@ // accelerated Randen implementation. #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 -#if defined(ABSL_ARCH_X86_64) +// iOS does not support dispatch, even on x86, since applications +// should be bundled as fat binaries, with a different build tailored for +// each specific supported platform/architecture. +#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \ + (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR) +#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH +#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 +#elif defined(ABSL_ARCH_X86_64) // Dispatch is available on x86_64 #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1 @@ -142,8 +151,8 @@ // Or when running linux PPC #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1 -#elif defined(__linux__) && defined(ABSL_ARCH_AARCH64) -// Or when running linux AArch64 +#elif (defined(__linux__) || defined(__APPLE__)) && defined(ABSL_ARCH_AARCH64) +// Or when running linux or macOS AArch64 #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1 #elif defined(__linux__) && defined(ABSL_ARCH_ARM) && (__ARM_ARCH >= 8) @@ -159,13 +168,4 @@ #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 #endif -// iOS does not support dispatch, even on x86, since applications -// should be bundled as fat binaries, with a different build tailored for -// each specific supported platform/architecture. -#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \ - (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR) -#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH -#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 -#endif - #endif // ABSL_RANDOM_INTERNAL_PLATFORM_H_ diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/randen_detect.cc b/contrib/restricted/abseil-cpp/absl/random/internal/randen_detect.cc index bdeab877b9..828db4790a 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/randen_detect.cc +++ b/contrib/restricted/abseil-cpp/absl/random/internal/randen_detect.cc @@ -19,10 +19,21 @@ #include "absl/random/internal/randen_detect.h" +#if defined(__APPLE__) && defined(__aarch64__) +#if defined(__has_include) +#if __has_include(<arm/cpu_capabilities_public.h>) +#include <arm/cpu_capabilities_public.h> +#endif +#endif +#include <sys/sysctl.h> +#include <sys/types.h> +#endif + #include <cstdint> #include <cstring> #include "absl/random/internal/platform.h" +#include "absl/types/optional.h" // IWYU pragma: keep #if !defined(__UCLIBC__) && defined(__GLIBC__) && \ (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16)) @@ -102,6 +113,19 @@ static uint32_t GetAuxval(uint32_t hwcap_type) { #endif +#if defined(__APPLE__) && defined(ABSL_ARCH_AARCH64) +template <typename T> +static absl::optional<T> ReadSysctlByName(const char* name) { + T val; + size_t val_size = sizeof(T); + int ret = sysctlbyname(name, &val, &val_size, nullptr, 0); + if (ret == -1) { + return std::nullopt; + } + return val; +} +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace random_internal { @@ -129,7 +153,9 @@ namespace random_internal { // cpu capabilities, and should allow us to enable crypto in the android // builds where it is supported. // -// 3. Use the default for the compiler architecture. +// 3. When __APPLE__ is defined on AARCH64, use sysctlbyname(). +// +// 4. Use the default for the compiler architecture. // bool CPUSupportsRandenHwAes() { @@ -178,8 +204,36 @@ bool CPUSupportsRandenHwAes() { return ((hwcap & kNEON) != 0) && ((hwcap & kAES) != 0); #endif +#elif defined(__APPLE__) && defined(ABSL_ARCH_AARCH64) + // 3. Use sysctlbyname. + + // Newer XNU kernels support querying all capabilities in a single + // sysctlbyname. +#if defined(CAP_BIT_AdvSIMD) && defined(CAP_BIT_FEAT_AES) + static const absl::optional<uint64_t> caps = + ReadSysctlByName<uint64_t>("hw.optional.arm.caps"); + if (caps.has_value()) { + constexpr uint64_t kNeonAndAesCaps = + (uint64_t{1} << CAP_BIT_AdvSIMD) | (uint64_t{1} << CAP_BIT_FEAT_AES); + return (*caps & kNeonAndAesCaps) == kNeonAndAesCaps; + } +#endif + + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#overview + static const absl::optional<int> adv_simd = + ReadSysctlByName<int>("hw.optional.AdvSIMD"); + if (adv_simd.value_or(0) == 0) { + return false; + } + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855 + static const absl::optional<int> feat_aes = + ReadSysctlByName<int>("hw.optional.arm.FEAT_AES"); + if (feat_aes.value_or(0) == 0) { + return false; + } + return true; #else // ABSL_INTERNAL_USE_GETAUXVAL - // 3. By default, assume that the compiler default. + // 4. By default, assume that the compiler default. return ABSL_HAVE_ACCELERATED_AES ? true : false; #endif @@ -215,9 +269,6 @@ bool CPUSupportsRandenHwAes() { // __asm __volatile("mrs %0, id_aa64isar0_el1" :"=&r" (val)); // // * Use a CPUID-style heuristic database. - // - // * On Apple (__APPLE__), AES is available on Arm v8. - // https://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios } #if defined(__clang__) diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h b/contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h index fe2d9f6c15..925e1bbab5 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h @@ -18,9 +18,10 @@ #include <algorithm> #include <cinttypes> #include <cstdlib> -#include <iostream> +#include <istream> #include <iterator> #include <limits> +#include <ostream> #include <type_traits> #include "absl/base/internal/endian.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h b/contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h index db737e13f3..d230073868 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h @@ -201,8 +201,8 @@ is_uniform_range_valid(FloatType a, FloatType b) { } template <typename IntType> -absl::enable_if_t<IsIntegral<IntType>::value, bool> -is_uniform_range_valid(IntType a, IntType b) { +absl::enable_if_t<IsIntegral<IntType>::value, bool> is_uniform_range_valid( + IntType a, IntType b) { return a <= b; } diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/wide_multiply.h b/contrib/restricted/abseil-cpp/absl/random/internal/wide_multiply.h index 891e3630b7..b1256813df 100644 --- a/contrib/restricted/abseil-cpp/absl/random/internal/wide_multiply.h +++ b/contrib/restricted/abseil-cpp/absl/random/internal/wide_multiply.h @@ -75,7 +75,6 @@ inline U256 MultiplyU128ToU256(uint128 a, uint128 b) { c00 + (c64a << 64) + (c64b << 64)}; } - template <> struct wide_multiply<uint128> { using input_type = uint128; diff --git a/contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h b/contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h index 4afff8f604..cbd5e0ca2b 100644 --- a/contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h @@ -21,11 +21,8 @@ #include <istream> #include <limits> #include <ostream> -#include <type_traits> -#include "absl/numeric/bits.h" -#include "absl/random/internal/fastmath.h" -#include "absl/random/internal/generate_real.h" +#include "absl/base/config.h" #include "absl/random/internal/iostream_state_saver.h" #include "absl/random/internal/traits.h" #include "absl/random/uniform_int_distribution.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/mock_distributions.h b/contrib/restricted/abseil-cpp/absl/random/mock_distributions.h index b379262cb6..1983547327 100644 --- a/contrib/restricted/abseil-cpp/absl/random/mock_distributions.h +++ b/contrib/restricted/abseil-cpp/absl/random/mock_distributions.h @@ -17,14 +17,14 @@ // ----------------------------------------------------------------------------- // // This file contains mock distribution functions for use alongside an -// `absl::MockingBitGen` object within the Googletest testing framework. Such +// `absl::MockingBitGen` object within the GoogleTest testing framework. Such // mocks are useful to provide deterministic values as return values within // (otherwise random) Abseil distribution functions. // // The return type of each function is a mock expectation object which // is used to set the match result. // -// More information about the Googletest testing framework is available at +// More information about the GoogleTest testing framework is available at // https://github.com/google/googletest // // EXPECT_CALL and ON_CALL need to be made within the same DLL component as diff --git a/contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h b/contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h index 041989de20..ba7ceae04a 100644 --- a/contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h +++ b/contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h @@ -17,12 +17,12 @@ // ----------------------------------------------------------------------------- // // This file includes an `absl::MockingBitGen` class to use as a mock within the -// Googletest testing framework. Such a mock is useful to provide deterministic +// GoogleTest testing framework. Such a mock is useful to provide deterministic // values as return values within (otherwise random) Abseil distribution // functions. Such determinism within a mock is useful within testing frameworks // to test otherwise indeterminate APIs. // -// More information about the Googletest testing framework is available at +// More information about the GoogleTest testing framework is available at // https://github.com/google/googletest #ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_ @@ -34,7 +34,6 @@ #include <utility> #include "gmock/gmock.h" -#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/fast_type_id.h" #include "absl/container/flat_hash_map.h" @@ -52,13 +51,53 @@ namespace random_internal { template <typename> struct DistributionCaller; class MockHelpers; +} // namespace random_internal -// Implements MockingBitGen with an option to turn on extra validation. -template <bool EnableValidation> -class MockingBitGenImpl { +// MockingBitGen +// +// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class +// which can act in place of an `absl::BitGen` URBG within tests using the +// GoogleTest testing framework. +// +// Usage: +// +// Use an `absl::MockingBitGen` along with a mock distribution object (within +// mock_distributions.h) inside Googletest constructs such as ON_CALL(), +// EXPECT_TRUE(), etc. to produce deterministic results conforming to the +// distribution's API contract. +// +// Example: +// +// // Mock a call to an `absl::Bernoulli` distribution using Googletest +// absl::MockingBitGen bitgen; +// +// ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5)) +// .WillByDefault(testing::Return(true)); +// EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5)); +// +// // Mock a call to an `absl::Uniform` distribution within Googletest +// absl::MockingBitGen bitgen; +// +// ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_)) +// .WillByDefault([] (int low, int high) { +// return low + (high - low) / 2; +// }); +// +// EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5); +// EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35); +// +// At this time, only mock distributions supplied within the Abseil random +// library are officially supported. +// +// EXPECT_CALL and ON_CALL need to be made within the same DLL component as +// the call to absl::Uniform and related methods, otherwise mocking will fail +// since the underlying implementation creates a type-specific pointer which +// will be distinct across different DLL boundaries. +// +class MockingBitGen { public: - MockingBitGenImpl() = default; - ~MockingBitGenImpl() = default; + MockingBitGen() = default; + ~MockingBitGen() = default; // URBG interface using result_type = absl::BitGen::result_type; @@ -138,25 +177,23 @@ class MockingBitGenImpl { typename ValidatorT> auto RegisterMock(SelfT&, base_internal::FastTypeIdType type, ValidatorT) -> decltype(GetMockFnType(std::declval<ResultT>(), - std::declval<ArgTupleT>()))& { - using ActualValidatorT = - std::conditional_t<EnableValidation, ValidatorT, NoOpValidator>; + std::declval<ArgTupleT>())) & { using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>())); using WrappedFnType = absl::conditional_t< - std::is_same<SelfT, ::testing::NiceMock<MockingBitGenImpl>>::value, + std::is_same<SelfT, ::testing::NiceMock<MockingBitGen>>::value, ::testing::NiceMock<MockFnType>, absl::conditional_t< - std::is_same<SelfT, ::testing::NaggyMock<MockingBitGenImpl>>::value, + std::is_same<SelfT, ::testing::NaggyMock<MockingBitGen>>::value, ::testing::NaggyMock<MockFnType>, absl::conditional_t< std::is_same<SelfT, - ::testing::StrictMock<MockingBitGenImpl>>::value, + ::testing::StrictMock<MockingBitGen>>::value, ::testing::StrictMock<MockFnType>, MockFnType>>>; using ImplT = - FunctionHolderImpl<WrappedFnType, ActualValidatorT, ResultT, ArgTupleT>; + FunctionHolderImpl<WrappedFnType, ValidatorT, ResultT, ArgTupleT>; auto& mock = mocks_[type]; if (!mock) { mock = absl::make_unique<ImplT>(); @@ -196,58 +233,6 @@ class MockingBitGenImpl { // InvokeMock }; -} // namespace random_internal - -// MockingBitGen -// -// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class -// which can act in place of an `absl::BitGen` URBG within tests using the -// Googletest testing framework. -// -// Usage: -// -// Use an `absl::MockingBitGen` along with a mock distribution object (within -// mock_distributions.h) inside Googletest constructs such as ON_CALL(), -// EXPECT_TRUE(), etc. to produce deterministic results conforming to the -// distribution's API contract. -// -// Example: -// -// // Mock a call to an `absl::Bernoulli` distribution using Googletest -// absl::MockingBitGen bitgen; -// -// ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5)) -// .WillByDefault(testing::Return(true)); -// EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5)); -// -// // Mock a call to an `absl::Uniform` distribution within Googletest -// absl::MockingBitGen bitgen; -// -// ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_)) -// .WillByDefault([] (int low, int high) { -// return low + (high - low) / 2; -// }); -// -// EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5); -// EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35); -// -// At this time, only mock distributions supplied within the Abseil random -// library are officially supported. -// -// EXPECT_CALL and ON_CALL need to be made within the same DLL component as -// the call to absl::Uniform and related methods, otherwise mocking will fail -// since the underlying implementation creates a type-specific pointer which -// will be distinct across different DLL boundaries. -// -using MockingBitGen = random_internal::MockingBitGenImpl<true>; - -// UnvalidatedMockingBitGen -// -// UnvalidatedMockingBitGen is a variant of MockingBitGen which does no extra -// validation. -using UnvalidatedMockingBitGen ABSL_DEPRECATED("Use MockingBitGen instead") = - random_internal::MockingBitGenImpl<false>; - ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h b/contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h index f4573082e1..ae2e095be3 100644 --- a/contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h @@ -17,11 +17,12 @@ #include <cassert> #include <cmath> +#include <cstdint> #include <istream> #include <limits> #include <ostream> -#include <type_traits> +#include "absl/base/config.h" #include "absl/random/internal/fast_uniform_bits.h" #include "absl/random/internal/fastmath.h" #include "absl/random/internal/generate_real.h" @@ -48,8 +49,8 @@ ABSL_NAMESPACE_BEGIN // the distribution results are limited to the max() value. // // The goals of this implementation are to provide good performance while still -// beig thread-safe: This limits the implementation to not using lgamma provided -// by <math.h>. +// being thread-safe: This limits the implementation to not using lgamma +// provided by <math.h>. // template <typename IntType = int> class poisson_distribution { diff --git a/contrib/restricted/abseil-cpp/absl/random/seed_gen_exception.cc b/contrib/restricted/abseil-cpp/absl/random/seed_gen_exception.cc index fdcb54a86c..6fb4ad3766 100644 --- a/contrib/restricted/abseil-cpp/absl/random/seed_gen_exception.cc +++ b/contrib/restricted/abseil-cpp/absl/random/seed_gen_exception.cc @@ -14,9 +14,8 @@ #include "absl/random/seed_gen_exception.h" -#include <iostream> - #include "absl/base/config.h" +#include "absl/base/internal/raw_logging.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -36,7 +35,7 @@ void ThrowSeedGenException() { #ifdef ABSL_HAVE_EXCEPTIONS throw absl::SeedGenException(); #else - std::cerr << kExceptionMessage << std::endl; + ABSL_RAW_LOG(FATAL, "%s", kExceptionMessage); std::terminate(); #endif } diff --git a/contrib/restricted/abseil-cpp/absl/random/seed_sequences.h b/contrib/restricted/abseil-cpp/absl/random/seed_sequences.h index 33970be581..dacc5b90c0 100644 --- a/contrib/restricted/abseil-cpp/absl/random/seed_sequences.h +++ b/contrib/restricted/abseil-cpp/absl/random/seed_sequences.h @@ -80,8 +80,7 @@ using SeedSeq = random_internal::SaltedSeedSeq<std::seed_seq>; // template <typename URBG> SeedSeq CreateSeedSeqFrom(URBG* urbg) { - SeedSeq::result_type - seed_material[random_internal::kEntropyBlocksNeeded]; + SeedSeq::result_type seed_material[random_internal::kEntropyBlocksNeeded]; if (!random_internal::ReadSeedMaterialFromURBG( urbg, absl::MakeSpan(seed_material))) { diff --git a/contrib/restricted/abseil-cpp/absl/random/uniform_int_distribution.h b/contrib/restricted/abseil-cpp/absl/random/uniform_int_distribution.h index fae80252e3..0dc7c62c3e 100644 --- a/contrib/restricted/abseil-cpp/absl/random/uniform_int_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/uniform_int_distribution.h @@ -31,8 +31,9 @@ #include <cassert> #include <istream> #include <limits> -#include <type_traits> +#include <ostream> +#include "absl/base/config.h" #include "absl/base/optimization.h" #include "absl/random/internal/fast_uniform_bits.h" #include "absl/random/internal/iostream_state_saver.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h b/contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h index 196833415e..8bef9469ae 100644 --- a/contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h @@ -37,8 +37,10 @@ #include <cstdint> #include <istream> #include <limits> +#include <ostream> #include <type_traits> +#include "absl/base/config.h" #include "absl/meta/type_traits.h" #include "absl/random/internal/fast_uniform_bits.h" #include "absl/random/internal/generate_real.h" diff --git a/contrib/restricted/abseil-cpp/absl/random/ya.make b/contrib/restricted/abseil-cpp/absl/random/ya.make index 1026a5d497..c5789234d1 100644 --- a/contrib/restricted/abseil-cpp/absl/random/ya.make +++ b/contrib/restricted/abseil-cpp/absl/random/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h b/contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h index 03497b1b26..21e3b709b0 100644 --- a/contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h +++ b/contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h @@ -22,6 +22,7 @@ #include <ostream> #include <type_traits> +#include "absl/base/config.h" #include "absl/random/internal/iostream_state_saver.h" #include "absl/random/internal/traits.h" #include "absl/random/uniform_real_distribution.h" @@ -57,8 +58,8 @@ class zipf_distribution { public: using distribution_type = zipf_distribution; - // Preconditions: k > 0, v > 0, q > 1 - // The precondidtions are validated when NDEBUG is not defined via + // Preconditions: k >= 0, v > 0, q > 1 + // The preconditions are validated when NDEBUG is not defined via // a pair of assert() directives. // If NDEBUG is defined and either or both of these parameters take invalid // values, the behavior of the class is undefined. @@ -152,7 +153,7 @@ zipf_distribution<IntType>::param_type::param_type( : k_(k), q_(q), v_(v), one_minus_q_(1 - q) { assert(q > 1); assert(v > 0); - assert(k > 0); + assert(k >= 0); one_minus_q_inv_ = 1 / one_minus_q_; // Setup for the ZRI algorithm (pg 17 of the paper). @@ -221,7 +222,7 @@ zipf_distribution<IntType>::operator()( const double v = uniform_double(g); const double u = p.hxm_ + v * p.hx0_minus_hxm_; const double x = p.hinv(u); - k = rint(x); // std::floor(x + 0.5); + k = rint(x); // std::floor(x + 0.5); if (k > static_cast<double>(p.k())) continue; // reject k > max_k if (k - x <= p.s_) break; const double h = p.h(k + 0.5); diff --git a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.cc b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.cc index a91567549e..99bf8faca3 100644 --- a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.cc +++ b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.cc @@ -28,6 +28,7 @@ #include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/base/nullability.h" +#include "absl/debugging/leak_check.h" #include "absl/debugging/stacktrace.h" #include "absl/debugging/symbolize.h" #include "absl/memory/memory.h" @@ -234,12 +235,15 @@ absl::StatusCode MapToLocalCode(int value) { } } -absl::Nonnull<std::string*> MakeCheckFailString( +absl::Nonnull<const char*> MakeCheckFailString( absl::Nonnull<const absl::Status*> status, absl::Nonnull<const char*> prefix) { - return new std::string( - absl::StrCat(prefix, " (", - status->ToString(StatusToStringMode::kWithEverything), ")")); + // There's no need to free this string since the process is crashing. + return absl::IgnoreLeak( + new std::string(absl::StrCat( + prefix, " (", + status->ToString(StatusToStringMode::kWithEverything), ")"))) + ->c_str(); } } // namespace status_internal diff --git a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h index c9f4383272..fe335b0b7c 100644 --- a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h +++ b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h @@ -120,7 +120,7 @@ absl::StatusCode MapToLocalCode(int value); // // This is an internal implementation detail for Abseil logging. ABSL_ATTRIBUTE_PURE_FUNCTION -absl::Nonnull<std::string*> MakeCheckFailString( +absl::Nonnull<const char*> MakeCheckFailString( absl::Nonnull<const absl::Status*> status, absl::Nonnull<const char*> prefix); diff --git a/contrib/restricted/abseil-cpp/absl/status/status.h b/contrib/restricted/abseil-cpp/absl/status/status.h index 6cfe49f2dd..02fd296485 100644 --- a/contrib/restricted/abseil-cpp/absl/status/status.h +++ b/contrib/restricted/abseil-cpp/absl/status/status.h @@ -649,7 +649,7 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI Status final { // Converts between StatusRep* and the external uintptr_t representation used // by rep_. See rep_ for details. - static uintptr_t PointerToRep(status_internal::StatusRep* r); + static uintptr_t PointerToRep(absl::Nonnull<status_internal::StatusRep*> r); static absl::Nonnull<const status_internal::StatusRep*> RepToPointer( uintptr_t r); diff --git a/contrib/restricted/abseil-cpp/absl/status/ya.make b/contrib/restricted/abseil-cpp/absl/status/ya.make index d7e0102e2d..0b2cd3499a 100644 --- a/contrib/restricted/abseil-cpp/absl/status/ya.make +++ b/contrib/restricted/abseil-cpp/absl/status/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc index 20a696a1f6..d15e4249ec 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc @@ -19,10 +19,8 @@ #include <cstring> #include <string> -#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/nullability.h" -#include "absl/base/optimization.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -177,10 +175,17 @@ constexpr bool AsciiInAZRange(unsigned char c) { return static_cast<signed char>(u) < threshold; } -// Force-inline so the compiler won't merge the short and long implementations. template <bool ToUpper> -ABSL_ATTRIBUTE_ALWAYS_INLINE inline constexpr void AsciiStrCaseFoldImpl( - absl::Nonnull<char*> p, size_t size) { +constexpr bool AsciiInAZRangeNaive(unsigned char c) { + constexpr unsigned char a = (ToUpper ? 'a' : 'A'); + constexpr unsigned char z = (ToUpper ? 'z' : 'Z'); + return a <= c && c <= z; +} + +template <bool ToUpper, bool Naive> +constexpr void AsciiStrCaseFoldImpl(absl::Nonnull<char*> dst, + absl::Nullable<const char*> src, + size_t size) { // The upper- and lowercase versions of ASCII characters differ by only 1 bit. // When we need to flip the case, we can xor with this bit to achieve the // desired result. Note that the choice of 'a' and 'A' here is arbitrary. We @@ -189,29 +194,37 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline constexpr void AsciiStrCaseFoldImpl( constexpr unsigned char kAsciiCaseBitFlip = 'a' ^ 'A'; for (size_t i = 0; i < size; ++i) { - unsigned char v = static_cast<unsigned char>(p[i]); - v ^= AsciiInAZRange<ToUpper>(v) ? kAsciiCaseBitFlip : 0; - p[i] = static_cast<char>(v); + unsigned char v = static_cast<unsigned char>(src[i]); + if ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 (Naive) { + v ^= AsciiInAZRangeNaive<ToUpper>(v) ? kAsciiCaseBitFlip : 0; + } else { + v ^= AsciiInAZRange<ToUpper>(v) ? kAsciiCaseBitFlip : 0; + } + dst[i] = static_cast<char>(v); } } -// The string size threshold for starting using the long string version. -constexpr size_t kCaseFoldThreshold = 16; - -// No-inline so the compiler won't merge the short and long implementations. -template <bool ToUpper> -ABSL_ATTRIBUTE_NOINLINE constexpr void AsciiStrCaseFoldLong( - absl::Nonnull<char*> p, size_t size) { - ABSL_ASSUME(size >= kCaseFoldThreshold); - AsciiStrCaseFoldImpl<ToUpper>(p, size); -} - // Splitting to short and long strings to allow vectorization decisions // to be made separately in the long and short cases. +// Using slightly different implementations so the compiler won't optimize them +// into the same code (the non-naive version is needed for SIMD, so for short +// strings it's not important). +// `src` may be null iff `size` is zero. template <bool ToUpper> -constexpr void AsciiStrCaseFold(absl::Nonnull<char*> p, size_t size) { - size < kCaseFoldThreshold ? AsciiStrCaseFoldImpl<ToUpper>(p, size) - : AsciiStrCaseFoldLong<ToUpper>(p, size); +constexpr void AsciiStrCaseFold(absl::Nonnull<char*> dst, + absl::Nullable<const char*> src, size_t size) { + size < 16 ? AsciiStrCaseFoldImpl<ToUpper, /*Naive=*/true>(dst, src, size) + : AsciiStrCaseFoldImpl<ToUpper, /*Naive=*/false>(dst, src, size); +} + +void AsciiStrToLower(absl::Nonnull<char*> dst, absl::Nullable<const char*> src, + size_t n) { + return AsciiStrCaseFold<false>(dst, src, n); +} + +void AsciiStrToUpper(absl::Nonnull<char*> dst, absl::Nullable<const char*> src, + size_t n) { + return AsciiStrCaseFold<true>(dst, src, n); } static constexpr size_t ValidateAsciiCasefold() { @@ -222,8 +235,8 @@ static constexpr size_t ValidateAsciiCasefold() { for (unsigned int i = 0; i < num_chars; ++i) { uppered[i] = lowered[i] = static_cast<char>(i); } - AsciiStrCaseFold<false>(&lowered[0], num_chars); - AsciiStrCaseFold<true>(&uppered[0], num_chars); + AsciiStrCaseFold<false>(&lowered[0], &lowered[0], num_chars); + AsciiStrCaseFold<true>(&uppered[0], &uppered[0], num_chars); for (size_t i = 0; i < num_chars; ++i) { const char ch = static_cast<char>(i), ch_upper = ('a' <= ch && ch <= 'z' ? 'A' + (ch - 'a') : ch), @@ -241,11 +254,13 @@ static_assert(ValidateAsciiCasefold() == 0, "error in case conversion"); } // namespace ascii_internal void AsciiStrToLower(absl::Nonnull<std::string*> s) { - return ascii_internal::AsciiStrCaseFold<false>(&(*s)[0], s->size()); + char* p = &(*s)[0]; + return ascii_internal::AsciiStrCaseFold<false>(p, p, s->size()); } void AsciiStrToUpper(absl::Nonnull<std::string*> s) { - return ascii_internal::AsciiStrCaseFold<true>(&(*s)[0], s->size()); + char* p = &(*s)[0]; + return ascii_internal::AsciiStrCaseFold<true>(p, p, s->size()); } void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str) { diff --git a/contrib/restricted/abseil-cpp/absl/strings/ascii.h b/contrib/restricted/abseil-cpp/absl/strings/ascii.h index c238f4de82..d9317eb113 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/ascii.h +++ b/contrib/restricted/abseil-cpp/absl/strings/ascii.h @@ -55,10 +55,12 @@ #include <algorithm> #include <cstddef> #include <string> +#include <utility> #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/nullability.h" +#include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/string_view.h" namespace absl { @@ -74,6 +76,12 @@ ABSL_DLL extern const char kToUpper[256]; // Declaration for the array of characters to lower-case characters. ABSL_DLL extern const char kToLower[256]; +void AsciiStrToLower(absl::Nonnull<char*> dst, absl::Nullable<const char*> src, + size_t n); + +void AsciiStrToUpper(absl::Nonnull<char*> dst, absl::Nullable<const char*> src, + size_t n); + } // namespace ascii_internal // ascii_isalpha() @@ -131,32 +139,42 @@ inline bool ascii_isxdigit(unsigned char c) { // // Determines whether the given character can be represented as a decimal // digit character (i.e. {0-9}). -inline bool ascii_isdigit(unsigned char c) { return c >= '0' && c <= '9'; } +inline constexpr bool ascii_isdigit(unsigned char c) { + return c >= '0' && c <= '9'; +} // ascii_isprint() // // Determines whether the given character is printable, including spaces. -inline bool ascii_isprint(unsigned char c) { return c >= 32 && c < 127; } +inline constexpr bool ascii_isprint(unsigned char c) { + return c >= 32 && c < 127; +} // ascii_isgraph() // // Determines whether the given character has a graphical representation. -inline bool ascii_isgraph(unsigned char c) { return c > 32 && c < 127; } +inline constexpr bool ascii_isgraph(unsigned char c) { + return c > 32 && c < 127; +} // ascii_isupper() // // Determines whether the given character is uppercase. -inline bool ascii_isupper(unsigned char c) { return c >= 'A' && c <= 'Z'; } +inline constexpr bool ascii_isupper(unsigned char c) { + return c >= 'A' && c <= 'Z'; +} // ascii_islower() // // Determines whether the given character is lowercase. -inline bool ascii_islower(unsigned char c) { return c >= 'a' && c <= 'z'; } +inline constexpr bool ascii_islower(unsigned char c) { + return c >= 'a' && c <= 'z'; +} // ascii_isascii() // // Determines whether the given character is ASCII. -inline bool ascii_isascii(unsigned char c) { return c < 128; } +inline constexpr bool ascii_isascii(unsigned char c) { return c < 128; } // ascii_tolower() // @@ -171,7 +189,18 @@ void AsciiStrToLower(absl::Nonnull<std::string*> s); // Creates a lowercase string from a given absl::string_view. ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(absl::string_view s) { - std::string result(s); + std::string result; + strings_internal::STLStringResizeUninitialized(&result, s.size()); + ascii_internal::AsciiStrToLower(&result[0], s.data(), s.size()); + return result; +} + +// Creates a lowercase string from a given std::string&&. +// +// (Template is used to lower priority of this overload.) +template <int&... DoNotSpecify> +ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(std::string&& s) { + std::string result = std::move(s); absl::AsciiStrToLower(&result); return result; } @@ -189,7 +218,18 @@ void AsciiStrToUpper(absl::Nonnull<std::string*> s); // Creates an uppercase string from a given absl::string_view. ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(absl::string_view s) { - std::string result(s); + std::string result; + strings_internal::STLStringResizeUninitialized(&result, s.size()); + ascii_internal::AsciiStrToUpper(&result[0], s.data(), s.size()); + return result; +} + +// Creates an uppercase string from a given std::string&&. +// +// (Template is used to lower priority of this overload.) +template <int&... DoNotSpecify> +ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(std::string&& s) { + std::string result = std::move(s); absl::AsciiStrToUpper(&result); return result; } diff --git a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc index 0c9227f849..66c12cc73d 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc @@ -359,16 +359,13 @@ template <typename FloatType> bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative, absl::Nonnull<FloatType*> value) { if (input.type == strings_internal::FloatType::kNan) { - // A bug in both clang < 7 and gcc would cause the compiler to optimize - // away the buffer we are building below. Declaring the buffer volatile - // avoids the issue, and has no measurable performance impact in - // microbenchmarks. + // A bug in gcc would cause the compiler to optimize away the buffer we are + // building below. Declaring the buffer volatile avoids the issue, and has + // no measurable performance impact in microbenchmarks. // - // https://bugs.llvm.org/show_bug.cgi?id=37778 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113 constexpr ptrdiff_t kNanBufferSize = 128; -#if (defined(__GNUC__) && !defined(__clang__)) || \ - (defined(__clang__) && __clang_major__ < 7) +#if (defined(__GNUC__) && !defined(__clang__)) volatile char n_char_sequence[kNanBufferSize]; #else char n_char_sequence[kNanBufferSize]; diff --git a/contrib/restricted/abseil-cpp/absl/strings/charset.h b/contrib/restricted/abseil-cpp/absl/strings/charset.h index ff4e81a41f..04ad459bc6 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/charset.h +++ b/contrib/restricted/abseil-cpp/absl/strings/charset.h @@ -46,15 +46,13 @@ #ifndef ABSL_STRINGS_CHARSET_H_ #define ABSL_STRINGS_CHARSET_H_ -#include <cstddef> #include <cstdint> -#include <cstring> -#include "absl/base/macros.h" -#include "absl/base/port.h" +#include "absl/base/config.h" #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN class CharSet { public: @@ -159,6 +157,7 @@ class CharSet { uint64_t m_[4]; }; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_CHARSET_H_ diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord.h b/contrib/restricted/abseil-cpp/absl/strings/cord.h index 69aa8ef41f..1f8aafb587 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/cord.h +++ b/contrib/restricted/abseil-cpp/absl/strings/cord.h @@ -61,6 +61,7 @@ #define ABSL_STRINGS_CORD_H_ #include <algorithm> +#include <cassert> #include <cstddef> #include <cstdint> #include <cstring> @@ -68,16 +69,14 @@ #include <iterator> #include <string> #include <type_traits> +#include <utility> #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/endian.h" -#include "absl/base/internal/per_thread_tls.h" #include "absl/base/macros.h" #include "absl/base/nullability.h" #include "absl/base/optimization.h" -#include "absl/base/port.h" -#include "absl/container/inlined_vector.h" #include "absl/crc/internal/crc_cord_state.h" #include "absl/functional/function_ref.h" #include "absl/meta/type_traits.h" @@ -88,12 +87,10 @@ #include "absl/strings/internal/cord_rep_btree.h" #include "absl/strings/internal/cord_rep_btree_reader.h" #include "absl/strings/internal/cord_rep_crc.h" -#include "absl/strings/internal/cordz_functions.h" +#include "absl/strings/internal/cord_rep_flat.h" #include "absl/strings/internal/cordz_info.h" -#include "absl/strings/internal/cordz_statistics.h" #include "absl/strings/internal/cordz_update_scope.h" #include "absl/strings/internal/cordz_update_tracker.h" -#include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/string_constant.h" #include "absl/strings/string_view.h" #include "absl/types/compare.h" @@ -641,7 +638,6 @@ class Cord { bool operator==(const CharIterator& other) const; bool operator!=(const CharIterator& other) const; reference operator*() const; - pointer operator->() const; friend Cord; @@ -979,15 +975,9 @@ class Cord { bool IsSame(const InlineRep& other) const { return data_ == other.data_; } + // Copies the inline contents into `dst`. Assumes the cord is not empty. void CopyTo(absl::Nonnull<std::string*> dst) const { - // memcpy is much faster when operating on a known size. On most supported - // platforms, the small string optimization is large enough that resizing - // to 15 bytes does not cause a memory allocation. - absl::strings_internal::STLStringResizeUninitialized(dst, kMaxInline); - data_.copy_max_inline_to(&(*dst)[0]); - // erase is faster than resize because the logic for memory allocation is - // not needed. - dst->erase(inline_size()); + data_.CopyInlineToString(dst); } // Copies the inline contents into `dst`. Assumes the cord is not empty. @@ -1659,10 +1649,6 @@ inline Cord::CharIterator::reference Cord::CharIterator::operator*() const { return *chunk_iterator_->data(); } -inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const { - return chunk_iterator_->data(); -} - inline Cord Cord::AdvanceAndRead(absl::Nonnull<CharIterator*> it, size_t n_bytes) { assert(it != nullptr); diff --git a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc index 4ffef94b63..b70c5041ae 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc @@ -15,6 +15,7 @@ #include "absl/strings/escaping.h" #include <algorithm> +#include <array> #include <cassert> #include <cstddef> #include <cstdint> @@ -24,6 +25,7 @@ #include <utility> #include "absl/base/config.h" +#include "absl/base/internal/endian.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/unaligned_access.h" #include "absl/base/nullability.h" @@ -368,7 +370,7 @@ std::string CEscapeInternal(absl::string_view src, bool use_hex, } /* clang-format off */ -constexpr unsigned char kCEscapedLen[256] = { +constexpr std::array<unsigned char, 256> kCEscapedLen = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", ' @@ -388,6 +390,40 @@ constexpr unsigned char kCEscapedLen[256] = { }; /* clang-format on */ +constexpr uint32_t MakeCEscapedLittleEndianUint32(size_t c) { + size_t char_len = kCEscapedLen[c]; + if (char_len == 1) { + return static_cast<uint32_t>(c); + } + if (char_len == 2) { + switch (c) { + case '\n': + return '\\' | (static_cast<uint32_t>('n') << 8); + case '\r': + return '\\' | (static_cast<uint32_t>('r') << 8); + case '\t': + return '\\' | (static_cast<uint32_t>('t') << 8); + case '\"': + return '\\' | (static_cast<uint32_t>('\"') << 8); + case '\'': + return '\\' | (static_cast<uint32_t>('\'') << 8); + case '\\': + return '\\' | (static_cast<uint32_t>('\\') << 8); + } + } + return static_cast<uint32_t>('\\' | (('0' + (c / 64)) << 8) | + (('0' + ((c % 64) / 8)) << 16) | + (('0' + (c % 8)) << 24)); +} + +template <size_t... indexes> +inline constexpr std::array<uint32_t, sizeof...(indexes)> +MakeCEscapedLittleEndianUint32Array(std::index_sequence<indexes...>) { + return {MakeCEscapedLittleEndianUint32(indexes)...}; +} +constexpr std::array<uint32_t, 256> kCEscapedLittleEndianUint32Array = + MakeCEscapedLittleEndianUint32Array(std::make_index_sequence<256>()); + // Calculates the length of the C-style escaped version of 'src'. // Assumes that non-printable characters are escaped using octal sequences, and // that UTF-8 bytes are not handled specially. @@ -421,59 +457,31 @@ void CEscapeAndAppendInternal(absl::string_view src, return; } + // We keep 3 slop bytes so that we can call `little_endian::Store32` + // invariably regardless of the length of the escaped character. + constexpr size_t slop_bytes = 3; size_t cur_dest_len = dest->size(); - ABSL_INTERNAL_CHECK( - cur_dest_len <= std::numeric_limits<size_t>::max() - escaped_len, - "std::string size overflow"); - strings_internal::STLStringResizeUninitialized(dest, - cur_dest_len + escaped_len); + size_t new_dest_len = cur_dest_len + escaped_len + slop_bytes; + ABSL_INTERNAL_CHECK(new_dest_len > cur_dest_len, "std::string size overflow"); + strings_internal::AppendUninitializedTraits<std::string>::Append( + dest, escaped_len + slop_bytes); char* append_ptr = &(*dest)[cur_dest_len]; for (char c : src) { - size_t char_len = kCEscapedLen[static_cast<unsigned char>(c)]; - if (char_len == 1) { - *append_ptr++ = c; - } else if (char_len == 2) { - switch (c) { - case '\n': - *append_ptr++ = '\\'; - *append_ptr++ = 'n'; - break; - case '\r': - *append_ptr++ = '\\'; - *append_ptr++ = 'r'; - break; - case '\t': - *append_ptr++ = '\\'; - *append_ptr++ = 't'; - break; - case '\"': - *append_ptr++ = '\\'; - *append_ptr++ = '\"'; - break; - case '\'': - *append_ptr++ = '\\'; - *append_ptr++ = '\''; - break; - case '\\': - *append_ptr++ = '\\'; - *append_ptr++ = '\\'; - break; - } - } else { - *append_ptr++ = '\\'; - *append_ptr++ = '0' + static_cast<unsigned char>(c) / 64; - *append_ptr++ = '0' + (static_cast<unsigned char>(c) % 64) / 8; - *append_ptr++ = '0' + static_cast<unsigned char>(c) % 8; - } + unsigned char uc = static_cast<unsigned char>(c); + size_t char_len = kCEscapedLen[uc]; + uint32_t little_endian_uint32 = kCEscapedLittleEndianUint32Array[uc]; + little_endian::Store32(append_ptr, little_endian_uint32); + append_ptr += char_len; } + dest->resize(new_dest_len - slop_bytes); } // Reverses the mapping in Base64EscapeInternal; see that method's // documentation for details of the mapping. bool Base64UnescapeInternal(absl::Nullable<const char*> src_param, size_t szsrc, absl::Nullable<char*> dest, size_t szdest, - absl::Nonnull<const signed char*> unbase64, + const std::array<signed char, 256>& unbase64, absl::Nonnull<size_t*> len) { static const char kPad64Equals = '='; static const char kPad64Dot = '.'; @@ -738,7 +746,7 @@ bool Base64UnescapeInternal(absl::Nullable<const char*> src_param, size_t szsrc, // where the value of "Base64[]" was replaced by one of k(WebSafe)Base64Chars // in the internal escaping.cc. /* clang-format off */ -constexpr signed char kUnBase64[] = { +constexpr std::array<signed char, 256> kUnBase64 = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -773,7 +781,7 @@ constexpr signed char kUnBase64[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -constexpr signed char kUnWebSafeBase64[] = { +constexpr std::array<signed char, 256> kUnWebSafeBase64 = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -812,7 +820,7 @@ constexpr signed char kUnWebSafeBase64[] = { template <typename String> bool Base64UnescapeInternal(absl::Nullable<const char*> src, size_t slen, absl::Nonnull<String*> dest, - absl::Nonnull<const signed char*> unbase64) { + const std::array<signed char, 256>& unbase64) { // Determine the size of the output string. Base64 encodes every 3 bytes into // 4 characters. Any leftover chars are added directly for good measure. const size_t dest_len = 3 * (slen / 4) + (slen % 4); @@ -837,7 +845,7 @@ bool Base64UnescapeInternal(absl::Nullable<const char*> src, size_t slen, } /* clang-format off */ -constexpr char kHexValueLenient[256] = { +constexpr std::array<char, 256> kHexValueLenient = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -856,7 +864,7 @@ constexpr char kHexValueLenient[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -constexpr signed char kHexValueStrict[256] = { +constexpr std::array<signed char, 256> kHexValueStrict = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h index cb29767663..2c7a336646 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.h @@ -17,7 +17,7 @@ #include <algorithm> #include <cstdint> -#include <iostream> +#include <ostream> #include <string> #include "absl/base/config.h" diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h index f0060f1015..b68ec2bbc5 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h @@ -19,16 +19,18 @@ #include <cassert> #include <cstddef> #include <cstdint> -#include <type_traits> +#include <cstring> +#include <string> #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/endian.h" #include "absl/base/internal/invoke.h" +#include "absl/base/macros.h" +#include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/container/internal/compressed_tuple.h" #include "absl/container/internal/container_memory.h" -#include "absl/meta/type_traits.h" #include "absl/strings/string_view.h" // We can only add poisoning if we can detect consteval executions. @@ -635,6 +637,19 @@ class InlineData { poison(); } + void CopyInlineToString(absl::Nonnull<std::string*> dst) const { + assert(!is_tree()); + // As Cord can store only 15 bytes it is smaller than std::string's + // small string optimization buffer size. Therefore we will always trigger + // the fast assign short path. + // + // Copying with a size equal to the maximum allows more efficient, wider + // stores to be used and no branching. + dst->assign(rep_.SanitizerSafeCopy().as_chars(), kMaxInline); + // After the copy we then change the size and put in a 0 byte. + dst->erase(inline_size()); + } + void copy_max_inline_to(char* dst) const { assert(!is_tree()); memcpy(dst, rep_.SanitizerSafeCopy().as_chars(), kMaxInline); @@ -713,35 +728,53 @@ class InlineData { GetOrNull(chars, 13), GetOrNull(chars, 14)} {} +#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER + // Break compiler optimization for cases when value is allocated on the + // stack. Compiler assumes that the the variable is fully accessible + // regardless of our poisoning. + // Missing report: https://github.com/llvm/llvm-project/issues/100640 + const Rep* self() const { + const Rep* volatile ptr = this; + return ptr; + } + Rep* self() { + Rep* volatile ptr = this; + return ptr; + } +#else + constexpr const Rep* self() const { return this; } + constexpr Rep* self() { return this; } +#endif + // Disable sanitizer as we must always be able to read `tag`. ABSL_CORD_INTERNAL_NO_SANITIZE int8_t tag() const { return reinterpret_cast<const int8_t*>(this)[0]; } - void set_tag(int8_t rhs) { reinterpret_cast<int8_t*>(this)[0] = rhs; } + void set_tag(int8_t rhs) { reinterpret_cast<int8_t*>(self())[0] = rhs; } - char* as_chars() { return data + 1; } - const char* as_chars() const { return data + 1; } + char* as_chars() { return self()->data + 1; } + const char* as_chars() const { return self()->data + 1; } - bool is_tree() const { return (tag() & 1) != 0; } + bool is_tree() const { return (self()->tag() & 1) != 0; } size_t inline_size() const { - ABSL_ASSERT(!is_tree()); - return static_cast<size_t>(tag()) >> 1; + ABSL_ASSERT(!self()->is_tree()); + return static_cast<size_t>(self()->tag()) >> 1; } void set_inline_size(size_t size) { ABSL_ASSERT(size <= kMaxInline); - set_tag(static_cast<int8_t>(size << 1)); + self()->set_tag(static_cast<int8_t>(size << 1)); } - CordRep* tree() const { return as_tree.rep; } - void set_tree(CordRep* rhs) { as_tree.rep = rhs; } + CordRep* tree() const { return self()->as_tree.rep; } + void set_tree(CordRep* rhs) { self()->as_tree.rep = rhs; } - cordz_info_t cordz_info() const { return as_tree.cordz_info; } - void set_cordz_info(cordz_info_t rhs) { as_tree.cordz_info = rhs; } + cordz_info_t cordz_info() const { return self()->as_tree.cordz_info; } + void set_cordz_info(cordz_info_t rhs) { self()->as_tree.cordz_info = rhs; } void make_tree(CordRep* tree) { - as_tree.rep = tree; - as_tree.cordz_info = kNullCordzInfo; + self()->as_tree.rep = tree; + self()->as_tree.cordz_info = kNullCordzInfo; } #ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc index 8edf520dcd..aa31998088 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc @@ -17,6 +17,7 @@ #include <string.h> #include <algorithm> +#include <array> #include <cassert> #include <cmath> #include <limits> @@ -159,7 +160,7 @@ class BinaryToDecimal { // See the current block of digits. absl::string_view CurrentDigits() const { - return absl::string_view(digits_ + kDigitsPerChunk - size_, size_); + return absl::string_view(&digits_[kDigitsPerChunk - size_], size_); } // Advance the current view of digits. @@ -234,7 +235,7 @@ class BinaryToDecimal { size_t decimal_start_; size_t decimal_end_; - char digits_[kDigitsPerChunk]; + std::array<char, kDigitsPerChunk> digits_; size_t size_ = 0; absl::Span<uint32_t> data_; diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h index 11ea96f2c1..ed1f117cda 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h @@ -253,6 +253,10 @@ using ShouldUseLifetimeBoundForPair = std::integral_constant< (std::is_same<First, absl::string_view>::value || std::is_same<Second, absl::string_view>::value)>; +template <typename StringType, typename ElementType, std::size_t Size> +using ShouldUseLifetimeBoundForArray = std::integral_constant< + bool, std::is_same<StringType, std::string>::value && + std::is_same<ElementType, absl::string_view>::value>; // This class implements the range that is returned by absl::StrSplit(). This // class has templated conversion operators that allow it to be implicitly @@ -344,7 +348,38 @@ class Splitter { return ConvertToPair<First, Second>(); } + // Returns an array with its elements set to the first few strings returned by + // the begin() iterator. If there is not a corresponding value the empty + // string is used. + template <typename ElementType, std::size_t Size, + std::enable_if_t<ShouldUseLifetimeBoundForArray< + StringType, ElementType, Size>::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::array<ElementType, Size>() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return ConvertToArray<ElementType, Size>(); + } + + template <typename ElementType, std::size_t Size, + std::enable_if_t<!ShouldUseLifetimeBoundForArray< + StringType, ElementType, Size>::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::array<ElementType, Size>() const { + return ConvertToArray<ElementType, Size>(); + } + private: + template <typename ElementType, std::size_t Size> + std::array<ElementType, Size> ConvertToArray() const { + std::array<ElementType, Size> a; + auto it = begin(); + for (std::size_t i = 0; i < Size && it != end(); ++i, ++it) { + a[i] = ElementType(*it); + } + return a; + } + template <typename First, typename Second> std::pair<First, Second> ConvertToPair() const { absl::string_view first, second; diff --git a/contrib/restricted/abseil-cpp/absl/strings/match.h b/contrib/restricted/abseil-cpp/absl/strings/match.h index 1eeafbbf67..ce4fe78473 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/match.h +++ b/contrib/restricted/abseil-cpp/absl/strings/match.h @@ -55,22 +55,32 @@ inline bool StrContains(absl::string_view haystack, char needle) noexcept { // StartsWith() // // Returns whether a given string `text` begins with `prefix`. -inline bool StartsWith(absl::string_view text, - absl::string_view prefix) noexcept { - return prefix.empty() || - (text.size() >= prefix.size() && - memcmp(text.data(), prefix.data(), prefix.size()) == 0); +inline constexpr bool StartsWith(absl::string_view text, + absl::string_view prefix) noexcept { + if (prefix.empty()) { + return true; + } + if (text.size() < prefix.size()) { + return false; + } + absl::string_view possible_match = text.substr(0, prefix.size()); + + return possible_match == prefix; } // EndsWith() // // Returns whether a given string `text` ends with `suffix`. -inline bool EndsWith(absl::string_view text, - absl::string_view suffix) noexcept { - return suffix.empty() || - (text.size() >= suffix.size() && - memcmp(text.data() + (text.size() - suffix.size()), suffix.data(), - suffix.size()) == 0); +inline constexpr bool EndsWith(absl::string_view text, + absl::string_view suffix) noexcept { + if (suffix.empty()) { + return true; + } + if (text.size() < suffix.size()) { + return false; + } + absl::string_view possible_match = text.substr(text.size() - suffix.size()); + return possible_match == suffix; } // StrContainsIgnoreCase() // diff --git a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc index b57d9e82e5..83ea80b474 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc @@ -18,6 +18,7 @@ #include "absl/strings/numbers.h" #include <algorithm> +#include <array> #include <cassert> #include <cfloat> // for DBL_DIG and FLT_DIG #include <cmath> // for HUGE_VAL @@ -674,7 +675,7 @@ namespace { // Represents integer values of digits. // Uses 36 to indicate an invalid character since we support // bases up to 36. -static const int8_t kAsciiToInt[256] = { +static constexpr std::array<int8_t, 256> kAsciiToInt = { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 16 36s. 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 1, 2, 3, 4, 5, diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h index b98adc0248..1a80662775 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h +++ b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h @@ -101,6 +101,7 @@ #include <vector> #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/nullability.h" #include "absl/base/port.h" #include "absl/meta/type_traits.h" @@ -110,6 +111,10 @@ #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" +#if defined(ABSL_HAVE_STD_STRING_VIEW) && !defined(ABSL_USES_STD_STRING_VIEW) +#include <string_view> +#endif + namespace absl { ABSL_NAMESPACE_BEGIN @@ -361,6 +366,12 @@ class AlphaNum { ABSL_ATTRIBUTE_LIFETIME_BOUND) : piece_(pc) {} +#if defined(ABSL_HAVE_STD_STRING_VIEW) && !defined(ABSL_USES_STD_STRING_VIEW) + AlphaNum(std::string_view pc // NOLINT(runtime/explicit) + ABSL_ATTRIBUTE_LIFETIME_BOUND) + : piece_(pc.data(), pc.size()) {} +#endif // !ABSL_USES_STD_STRING_VIEW + template <typename T, typename = typename std::enable_if< HasAbslStringify<T>::value>::type> AlphaNum( // NOLINT(runtime/explicit) diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_split.h b/contrib/restricted/abseil-cpp/absl/strings/str_split.h index ba176fca3c..7e8e31c3d8 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_split.h +++ b/contrib/restricted/abseil-cpp/absl/strings/str_split.h @@ -444,8 +444,10 @@ using EnableSplitIfString = // behavior works for: // // 1) All standard STL containers including `std::vector`, `std::list`, -// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap` +// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`. // 2) `std::pair` (which is not actually a container). See below. +// 3) `std::array`, which is a container but has different behavior due to its +// fixed size. See below. // // Example: // @@ -487,6 +489,21 @@ using EnableSplitIfString = // std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ','); // // p.first == "a", p.second == "b" // "c" is omitted. // +// +// Splitting to `std::array` is similar to splitting to `std::pair`, but for +// N elements instead of two; missing elements are filled with the empty string +// and extra elements are discarded. +// +// Examples: +// +// // Stores first two split strings as the elements in a std::array. +// std::array<std::string, 2> a = absl::StrSplit("a,b,c", ','); +// // a[0] == "a", a[1] == "b" // "c" is omitted. +// +// // The second element is empty. +// std::array<std::string, 2> a = absl::StrSplit("a,", ','); +// // a[0] == "a", a[1] == "" +// // The `StrSplit()` function can be used multiple times to perform more // complicated splitting logic, such as intelligently parsing key-value pairs. // diff --git a/contrib/restricted/abseil-cpp/absl/strings/string_view.h b/contrib/restricted/abseil-cpp/absl/strings/string_view.h index ff7600144a..b461478f14 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/string_view.h +++ b/contrib/restricted/abseil-cpp/absl/strings/string_view.h @@ -159,7 +159,7 @@ ABSL_NAMESPACE_BEGIN // // absl::string_view() == absl::string_view("", 0) // absl::string_view(nullptr, 0) == absl::string_view("abcdef"+6, 0) -class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view { +class ABSL_ATTRIBUTE_VIEW string_view { public: using traits_type = std::char_traits<char>; using value_type = char; @@ -200,13 +200,12 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view { absl::Nonnull<const char*> str) : ptr_(str), length_(str ? StrlenInternal(str) : 0) {} - // Implicit constructor of a `string_view` from a `const char*` and length. + // Constructor of a `string_view` from a `const char*` and length. constexpr string_view(absl::Nullable<const char*> data, size_type len) : ptr_(data), length_(CheckLengthInternal(len)) {} - // NOTE: Harmlessly omitted to work around gdb bug. - // constexpr string_view(const string_view&) noexcept = default; - // string_view& operator=(const string_view&) noexcept = default; + constexpr string_view(const string_view&) noexcept = default; + string_view& operator=(const string_view&) noexcept = default; // Iterators @@ -293,7 +292,8 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view { // Returns the ith element of the `string_view` using the array operator. // Note that this operator does not perform any bounds checking. constexpr const_reference operator[](size_type i) const { - return ABSL_HARDENING_ASSERT(i < size()), ptr_[i]; + ABSL_HARDENING_ASSERT(i < size()); + return ptr_[i]; } // string_view::at() @@ -302,25 +302,26 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view { // and an exception of type `std::out_of_range` will be thrown on invalid // access. constexpr const_reference at(size_type i) const { - return ABSL_PREDICT_TRUE(i < size()) - ? ptr_[i] - : ((void)base_internal::ThrowStdOutOfRange( - "absl::string_view::at"), - ptr_[i]); + if (ABSL_PREDICT_FALSE(i >= size())) { + base_internal::ThrowStdOutOfRange("absl::string_view::at"); + } + return ptr_[i]; } // string_view::front() // // Returns the first element of a `string_view`. constexpr const_reference front() const { - return ABSL_HARDENING_ASSERT(!empty()), ptr_[0]; + ABSL_HARDENING_ASSERT(!empty()); + return ptr_[0]; } // string_view::back() // // Returns the last element of a `string_view`. constexpr const_reference back() const { - return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1]; + ABSL_HARDENING_ASSERT(!empty()); + return ptr_[size() - 1]; } // string_view::data() @@ -394,11 +395,10 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view { // `pos > size`. // Use absl::ClippedSubstr if you need a truncating substr operation. constexpr string_view substr(size_type pos = 0, size_type n = npos) const { - return ABSL_PREDICT_FALSE(pos > length_) - ? (base_internal::ThrowStdOutOfRange( - "absl::string_view::substr"), - string_view()) - : string_view(ptr_ + pos, Min(n, length_ - pos)); + if (ABSL_PREDICT_FALSE(pos > length_)) { + base_internal::ThrowStdOutOfRange("absl::string_view::substr"); + } + return string_view(ptr_ + pos, Min(n, length_ - pos)); } // string_view::compare() @@ -667,7 +667,8 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view { (std::numeric_limits<difference_type>::max)(); static constexpr size_type CheckLengthInternal(size_type len) { - return ABSL_HARDENING_ASSERT(len <= kMaxSize), len; + ABSL_HARDENING_ASSERT(len <= kMaxSize); + return len; } static constexpr size_type StrlenInternal(absl::Nonnull<const char*> str) { diff --git a/contrib/restricted/abseil-cpp/absl/strings/strip.h b/contrib/restricted/abseil-cpp/absl/strings/strip.h index e3cda5bac3..8a55375169 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/strip.h +++ b/contrib/restricted/abseil-cpp/absl/strings/strip.h @@ -24,6 +24,7 @@ #include <cstddef> #include <string> +#include "absl/base/attributes.h" #include "absl/base/macros.h" #include "absl/base/nullability.h" #include "absl/strings/ascii.h" @@ -44,8 +45,8 @@ ABSL_NAMESPACE_BEGIN // absl::string_view input("abc"); // EXPECT_TRUE(absl::ConsumePrefix(&input, "a")); // EXPECT_EQ(input, "bc"); -inline bool ConsumePrefix(absl::Nonnull<absl::string_view*> str, - absl::string_view expected) { +inline constexpr bool ConsumePrefix(absl::Nonnull<absl::string_view*> str, + absl::string_view expected) { if (!absl::StartsWith(*str, expected)) return false; str->remove_prefix(expected.size()); return true; @@ -61,8 +62,8 @@ inline bool ConsumePrefix(absl::Nonnull<absl::string_view*> str, // absl::string_view input("abcdef"); // EXPECT_TRUE(absl::ConsumeSuffix(&input, "def")); // EXPECT_EQ(input, "abc"); -inline bool ConsumeSuffix(absl::Nonnull<absl::string_view*> str, - absl::string_view expected) { +inline constexpr bool ConsumeSuffix(absl::Nonnull<absl::string_view*> str, + absl::string_view expected) { if (!absl::EndsWith(*str, expected)) return false; str->remove_suffix(expected.size()); return true; @@ -73,8 +74,9 @@ inline bool ConsumeSuffix(absl::Nonnull<absl::string_view*> str, // Returns a view into the input string `str` with the given `prefix` removed, // but leaving the original string intact. If the prefix does not match at the // start of the string, returns the original string instead. -ABSL_MUST_USE_RESULT inline absl::string_view StripPrefix( - absl::string_view str, absl::string_view prefix) { +ABSL_MUST_USE_RESULT inline constexpr absl::string_view StripPrefix( + absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND, + absl::string_view prefix) { if (absl::StartsWith(str, prefix)) str.remove_prefix(prefix.size()); return str; } @@ -84,8 +86,9 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripPrefix( // Returns a view into the input string `str` with the given `suffix` removed, // but leaving the original string intact. If the suffix does not match at the // end of the string, returns the original string instead. -ABSL_MUST_USE_RESULT inline absl::string_view StripSuffix( - absl::string_view str, absl::string_view suffix) { +ABSL_MUST_USE_RESULT inline constexpr absl::string_view StripSuffix( + absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND, + absl::string_view suffix) { if (absl::EndsWith(str, suffix)) str.remove_suffix(suffix.size()); return str; } diff --git a/contrib/restricted/abseil-cpp/absl/strings/ya.make b/contrib/restricted/abseil-cpp/absl/strings/ya.make index ff42ac04ca..95f3fdd5c7 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/ya.make +++ b/contrib/restricted/abseil-cpp/absl/strings/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.cc b/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.cc index d2f82da3bb..a530baf4cc 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.cc +++ b/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.cc @@ -17,6 +17,7 @@ #include <atomic> #include "absl/base/internal/raw_logging.h" +#include "absl/base/internal/tracing.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -40,6 +41,7 @@ bool BlockingCounter::DecrementCount() { ABSL_RAW_CHECK(count >= 0, "BlockingCounter::DecrementCount() called too many times"); if (count == 0) { + base_internal::TraceSignal(this, TraceObjectKind()); MutexLock l(&lock_); done_ = true; return true; @@ -48,19 +50,23 @@ bool BlockingCounter::DecrementCount() { } void BlockingCounter::Wait() { - MutexLock l(&this->lock_); + base_internal::TraceWait(this, TraceObjectKind()); + { + MutexLock l(&this->lock_); - // only one thread may call Wait(). To support more than one thread, - // implement a counter num_to_exit, like in the Barrier class. - ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()"); - num_waiting_++; + // only one thread may call Wait(). To support more than one thread, + // implement a counter num_to_exit, like in the Barrier class. + ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()"); + num_waiting_++; - this->lock_.Await(Condition(IsDone, &this->done_)); + this->lock_.Await(Condition(IsDone, &this->done_)); - // At this point, we know that all threads executing DecrementCount - // will not touch this object again. - // Therefore, the thread calling this method is free to delete the object - // after we return from this method. + // At this point, we know that all threads executing DecrementCount + // will not touch this object again. + // Therefore, the thread calling this method is free to delete the object + // after we return from this method. + } + base_internal::TraceContinue(this, TraceObjectKind()); } ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.h b/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.h index 1908fdb1d9..d0504a19bf 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.h +++ b/contrib/restricted/abseil-cpp/absl/synchronization/blocking_counter.h @@ -22,6 +22,7 @@ #include <atomic> +#include "absl/base/internal/tracing.h" #include "absl/base/thread_annotations.h" #include "absl/synchronization/mutex.h" @@ -89,6 +90,11 @@ class BlockingCounter { void Wait(); private: + // Convenience helper to reduce verbosity at call sites. + static inline constexpr base_internal::ObjectKind TraceObjectKind() { + return base_internal::ObjectKind::kBlockingCounter; + } + Mutex lock_; std::atomic<int> count_; int num_waiting_ ABSL_GUARDED_BY(lock_); diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc b/contrib/restricted/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc index eacaa28d7b..93cd376bde 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc +++ b/contrib/restricted/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc @@ -39,7 +39,8 @@ ABSL_CONST_INIT static base_internal::SpinLock freelist_lock( ABSL_CONST_INIT static base_internal::ThreadIdentity* thread_identity_freelist; // A per-thread destructor for reclaiming associated ThreadIdentity objects. -// Since we must preserve their storage we cache them for re-use. +// Since we must preserve their storage, we cache them for re-use instead of +// truly destructing the object. static void ReclaimThreadIdentity(void* v) { base_internal::ThreadIdentity* identity = static_cast<base_internal::ThreadIdentity*>(v); @@ -124,6 +125,9 @@ static base_internal::ThreadIdentity* NewThreadIdentity() { identity = reinterpret_cast<base_internal::ThreadIdentity*>( RoundUp(reinterpret_cast<intptr_t>(allocation), base_internal::PerThreadSynch::kAlignment)); + // Note that *identity is never constructed. + // TODO(b/357097463): change this "one time init" to be a proper + // constructor. OneTimeInitThreadIdentity(identity); } ResetThreadIdentityBetweenReuse(identity); diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc index cb3c7e74ec..52ed27f696 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc +++ b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc @@ -651,6 +651,13 @@ static const intptr_t kMuSpin = 0x0040L; // spinlock protects wait list static const intptr_t kMuLow = 0x00ffL; // mask all mutex bits static const intptr_t kMuHigh = ~kMuLow; // mask pointer/reader count +static_assert((0xab & (kMuWriter | kMuReader)) == (kMuWriter | kMuReader), + "The debug allocator's uninitialized pattern (0xab) must be an " + "invalid mutex state"); +static_assert((0xcd & (kMuWriter | kMuReader)) == (kMuWriter | kMuReader), + "The debug allocator's freed pattern (0xcd) must be an invalid " + "mutex state"); + // Hack to make constant values available to gdb pretty printer enum { kGdbMuSpin = kMuSpin, @@ -1713,25 +1720,44 @@ void Mutex::Unlock() { // NOTE: optimized out when kDebugMode is false. bool should_try_cas = ((v & (kMuEvent | kMuWriter)) == kMuWriter && (v & (kMuWait | kMuDesig)) != kMuWait); + // But, we can use an alternate computation of it, that compilers // currently don't find on their own. When that changes, this function // can be simplified. - intptr_t x = (v ^ (kMuWriter | kMuWait)) & (kMuWriter | kMuEvent); - intptr_t y = (v ^ (kMuWriter | kMuWait)) & (kMuWait | kMuDesig); - // Claim: "x == 0 && y > 0" is equal to should_try_cas. - // Also, because kMuWriter and kMuEvent exceed kMuDesig and kMuWait, - // all possible non-zero values for x exceed all possible values for y. - // Therefore, (x == 0 && y > 0) == (x < y). - if (kDebugMode && should_try_cas != (x < y)) { + // + // should_try_cas is true iff the bits satisfy the following conditions: + // + // Ev Wr Wa De + // equal to 0 1 + // and not equal to 1 0 + // + // after xoring by 0 1 0 1, this is equivalent to: + // + // equal to 0 0 + // and not equal to 1 1, which is the same as: + // + // smaller than 0 0 1 1 + static_assert(kMuEvent > kMuWait, "Needed for should_try_cas_fast"); + static_assert(kMuEvent > kMuDesig, "Needed for should_try_cas_fast"); + static_assert(kMuWriter > kMuWait, "Needed for should_try_cas_fast"); + static_assert(kMuWriter > kMuDesig, "Needed for should_try_cas_fast"); + + bool should_try_cas_fast = + ((v ^ (kMuWriter | kMuDesig)) & + (kMuEvent | kMuWriter | kMuWait | kMuDesig)) < (kMuWait | kMuDesig); + + if (kDebugMode && should_try_cas != should_try_cas_fast) { // We would usually use PRIdPTR here, but is not correctly implemented // within the android toolchain. ABSL_RAW_LOG(FATAL, "internal logic error %llx %llx %llx\n", - static_cast<long long>(v), static_cast<long long>(x), - static_cast<long long>(y)); + static_cast<long long>(v), + static_cast<long long>(should_try_cas), + static_cast<long long>(should_try_cas_fast)); } - if (x < y && mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter), - std::memory_order_release, - std::memory_order_relaxed)) { + if (should_try_cas_fast && + mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter), + std::memory_order_release, + std::memory_order_relaxed)) { // fast writer release (writer with no waiters or with designated waker) } else { this->UnlockSlow(nullptr /*no waitp*/); // take slow path diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc b/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc index 165ba669fb..a5853ab3d7 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc +++ b/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc @@ -17,6 +17,7 @@ #include <atomic> #include "absl/base/internal/raw_logging.h" +#include "absl/base/internal/tracing.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" @@ -24,6 +25,7 @@ namespace absl { ABSL_NAMESPACE_BEGIN void Notification::Notify() { + base_internal::TraceSignal(this, TraceObjectKind()); MutexLock l(&this->mutex_); #ifndef NDEBUG @@ -45,31 +47,37 @@ Notification::~Notification() { } void Notification::WaitForNotification() const { + base_internal::TraceWait(this, TraceObjectKind()); if (!HasBeenNotifiedInternal(&this->notified_yet_)) { - this->mutex_.LockWhen(Condition(&HasBeenNotifiedInternal, - &this->notified_yet_)); + this->mutex_.LockWhen( + Condition(&HasBeenNotifiedInternal, &this->notified_yet_)); this->mutex_.Unlock(); } + base_internal::TraceContinue(this, TraceObjectKind()); } bool Notification::WaitForNotificationWithTimeout( absl::Duration timeout) const { + base_internal::TraceWait(this, TraceObjectKind()); bool notified = HasBeenNotifiedInternal(&this->notified_yet_); if (!notified) { notified = this->mutex_.LockWhenWithTimeout( Condition(&HasBeenNotifiedInternal, &this->notified_yet_), timeout); this->mutex_.Unlock(); } + base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind()); return notified; } bool Notification::WaitForNotificationWithDeadline(absl::Time deadline) const { + base_internal::TraceWait(this, TraceObjectKind()); bool notified = HasBeenNotifiedInternal(&this->notified_yet_); if (!notified) { notified = this->mutex_.LockWhenWithDeadline( Condition(&HasBeenNotifiedInternal, &this->notified_yet_), deadline); this->mutex_.Unlock(); } + base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind()); return notified; } diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/notification.h b/contrib/restricted/abseil-cpp/absl/synchronization/notification.h index 8986d9a408..78cdf29608 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/notification.h +++ b/contrib/restricted/abseil-cpp/absl/synchronization/notification.h @@ -53,6 +53,7 @@ #include <atomic> #include "absl/base/attributes.h" +#include "absl/base/internal/tracing.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" @@ -75,7 +76,11 @@ class Notification { // // Returns the value of the notification's internal "notified" state. ABSL_MUST_USE_RESULT bool HasBeenNotified() const { - return HasBeenNotifiedInternal(&this->notified_yet_); + if (HasBeenNotifiedInternal(&this->notified_yet_)) { + base_internal::TraceObserved(this, TraceObjectKind()); + return true; + } + return false; } // Notification::WaitForNotification() @@ -108,6 +113,11 @@ class Notification { void Notify(); private: + // Convenience helper to reduce verbosity at call sites. + static inline constexpr base_internal::ObjectKind TraceObjectKind() { + return base_internal::ObjectKind::kNotification; + } + static inline bool HasBeenNotifiedInternal( const std::atomic<bool>* notified_yet) { return notified_yet->load(std::memory_order_acquire); diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/ya.make b/contrib/restricted/abseil-cpp/absl/synchronization/ya.make index 3a2fb1b4de..bd9b7000b2 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/ya.make +++ b/contrib/restricted/abseil-cpp/absl/synchronization/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/time/duration.cc b/contrib/restricted/abseil-cpp/absl/time/duration.cc index 8d0b66f825..19407080a7 100644 --- a/contrib/restricted/abseil-cpp/absl/time/duration.cc +++ b/contrib/restricted/abseil-cpp/absl/time/duration.cc @@ -549,50 +549,6 @@ Duration DurationFromTimeval(timeval tv) { // // Conversion to other duration types. // - -int64_t ToInt64Nanoseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 33 == 0) { - return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) + - (time_internal::GetRepLo(d) / kTicksPerNanosecond); - } - return d / Nanoseconds(1); -} -int64_t ToInt64Microseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 43 == 0) { - return (time_internal::GetRepHi(d) * 1000 * 1000) + - (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000)); - } - return d / Microseconds(1); -} -int64_t ToInt64Milliseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 53 == 0) { - return (time_internal::GetRepHi(d) * 1000) + - (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000)); - } - return d / Milliseconds(1); -} -int64_t ToInt64Seconds(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi; -} -int64_t ToInt64Minutes(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi / 60; -} -int64_t ToInt64Hours(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi / (60 * 60); -} - double ToDoubleNanoseconds(Duration d) { return FDivDuration(d, Nanoseconds(1)); } @@ -718,13 +674,12 @@ struct DisplayUnit { int prec; double pow10; }; -ABSL_CONST_INIT const DisplayUnit kDisplayNano = {"ns", 2, 1e2}; -ABSL_CONST_INIT const DisplayUnit kDisplayMicro = {"us", 5, 1e5}; -ABSL_CONST_INIT const DisplayUnit kDisplayMilli = {"ms", 8, 1e8}; -ABSL_CONST_INIT const DisplayUnit kDisplaySec = {"s", 11, 1e11}; -ABSL_CONST_INIT const DisplayUnit kDisplayMin = {"m", -1, 0.0}; // prec ignored -ABSL_CONST_INIT const DisplayUnit kDisplayHour = {"h", -1, - 0.0}; // prec ignored +constexpr DisplayUnit kDisplayNano = {"ns", 2, 1e2}; +constexpr DisplayUnit kDisplayMicro = {"us", 5, 1e5}; +constexpr DisplayUnit kDisplayMilli = {"ms", 8, 1e8}; +constexpr DisplayUnit kDisplaySec = {"s", 11, 1e11}; +constexpr DisplayUnit kDisplayMin = {"m", -1, 0.0}; // prec ignored +constexpr DisplayUnit kDisplayHour = {"h", -1, 0.0}; // prec ignored void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) { char buf[sizeof("2562047788015216")]; // hours in max duration diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc index e09654eaf3..ed7f9cb97a 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "time_zone_fixed.h" +#include "absl/time/internal/cctz/src/time_zone_fixed.h" #include <algorithm> #include <cassert> diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc index e7e30a2fb7..0e5f32f14a 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc @@ -46,7 +46,7 @@ #endif #include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "time_zone_if.h" +#include "absl/time/internal/cctz/src/time_zone_if.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc index 0e65cd9e73..09f83e82f7 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "time_zone_if.h" +#include "absl/time/internal/cctz/src/time_zone_if.h" #include "absl/base/config.h" -#include "time_zone_info.h" -#include "time_zone_libc.h" +#include "absl/time/internal/cctz/src/time_zone_info.h" +#include "absl/time/internal/cctz/src/time_zone_libc.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc index aadbb77da2..5f2f49e424 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "time_zone_impl.h" +#include "absl/time/internal/cctz/src/time_zone_impl.h" #include <deque> #include <memory> @@ -22,7 +22,7 @@ #include <utility> #include "absl/base/config.h" -#include "time_zone_fixed.h" +#include "absl/time/internal/cctz/src/time_zone_fixed.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h index 8308a3b49e..da3aec525c 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h @@ -21,8 +21,8 @@ #include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" -#include "time_zone_if.h" -#include "time_zone_info.h" +#include "absl/time/internal/cctz/src/time_zone_if.h" +#include "absl/time/internal/cctz/src/time_zone_info.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc index b7178a6b67..f8484c9050 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc @@ -30,7 +30,7 @@ // Note that we assume the proleptic Gregorian calendar and 60-second // minutes throughout. -#include "time_zone_info.h" +#include "absl/time/internal/cctz/src/time_zone_info.h" #include <algorithm> #include <cassert> @@ -49,8 +49,8 @@ #include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "time_zone_fixed.h" -#include "time_zone_posix.h" +#include "absl/time/internal/cctz/src/time_zone_fixed.h" +#include "absl/time/internal/cctz/src/time_zone_posix.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h index 689df6f9c0..efe2f9cbfb 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h @@ -26,8 +26,8 @@ #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" #include "absl/time/internal/cctz/include/cctz/zone_info_source.h" -#include "time_zone_if.h" -#include "tzfile.h" +#include "absl/time/internal/cctz/src/time_zone_if.h" +#include "absl/time/internal/cctz/src/tzfile.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc index b509402783..362da1ab58 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS 1 #endif -#include "time_zone_libc.h" +#include "absl/time/internal/cctz/src/time_zone_libc.h" #include <chrono> #include <ctime> diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h index ae2107376f..f1ed5cd08f 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h @@ -19,7 +19,7 @@ #include <string> #include "absl/base/config.h" -#include "time_zone_if.h" +#include "absl/time/internal/cctz/src/time_zone_if.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc index e0d773b831..a6f3430c4a 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc @@ -47,6 +47,7 @@ #include <wchar.h> #include <windows.globalization.h> #include <windows.h> +#include <winstring.h> #endif #endif @@ -54,8 +55,8 @@ #include <cstring> #include <string> -#include "time_zone_fixed.h" -#include "time_zone_impl.h" +#include "absl/time/internal/cctz/src/time_zone_fixed.h" +#include "absl/time/internal/cctz/src/time_zone_impl.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc index 5cdd09e89d..efea080470 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "time_zone_posix.h" +#include "absl/time/internal/cctz/src/time_zone_posix.h" #include <cstddef> #include <cstring> diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/tzfile.h b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/tzfile.h index 2be3bb8d98..628143894a 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/tzfile.h +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/tzfile.h @@ -25,7 +25,7 @@ #define TZDEFRULES "posixrules" #endif /* !defined TZDEFRULES */ -/* See Internet RFC 8536 for more details about the following format. */ +/* See Internet RFC 9636 for more details about the following format. */ /* ** Each file begins with. . . @@ -75,14 +75,16 @@ struct tzhead { ** If tzh_version is '2' or greater, the above is followed by a second instance ** of tzhead and a second instance of the data in which each coded transition ** time uses 8 rather than 4 chars, -** then a POSIX-TZ-environment-variable-style string for use in handling +** then a POSIX.1-2017 proleptic TZ string for use in handling ** instants after the last transition time stored in the file ** (with nothing between the newlines if there is no POSIX.1-2017 ** representation for such instants). ** -** If tz_version is '3' or greater, the above is extended as follows. +** If tz_version is '3' or greater, the TZ string can be any POSIX.1-2024 +** proleptic TZ string, which means the above is extended as follows. ** First, the TZ string's hour offset may range from -167 -** through 167 as compared to the POSIX-required 0 through 24. +** through 167 as compared to the range 0 through 24 required +** by POSIX.1-2017 and earlier. ** Second, its DST start time may be January 1 at 00:00 and its stop ** time December 31 at 24:00 plus the difference between DST and ** standard time, indicating DST all year. diff --git a/contrib/restricted/abseil-cpp/absl/time/time.h b/contrib/restricted/abseil-cpp/absl/time/time.h index 15edbb4a66..d73a204c12 100644 --- a/contrib/restricted/abseil-cpp/absl/time/time.h +++ b/contrib/restricted/abseil-cpp/absl/time/time.h @@ -74,13 +74,19 @@ // including 'windows.h' so we are picking the lesser of two evils here. struct timeval; #endif -#include <chrono> // NOLINT(build/c++11) +#include "absl/base/config.h" + +// For feature testing and determining which headers can be included. +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#include <version> +#endif + +#include <chrono> // NOLINT(build/c++11) +#include <cmath> #ifdef __cpp_lib_three_way_comparison #include <compare> #endif // __cpp_lib_three_way_comparison - -#include <cmath> #include <cstdint> #include <ctime> #include <limits> @@ -91,12 +97,16 @@ struct timeval; #include <utility> #include "absl/base/attributes.h" -#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/strings/string_view.h" #include "absl/time/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" +#if defined(__cpp_impl_three_way_comparison) && \ + defined(__cpp_lib_three_way_comparison) +#define ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON 1 +#endif + namespace absl { ABSL_NAMESPACE_BEGIN @@ -138,7 +148,8 @@ using EnableIfFloat = // the result of subtracting one `absl::Time` from another. Durations behave // like unit-safe integers and they support all the natural integer-like // arithmetic operations. Arithmetic overflows and saturates at +/- infinity. -// `Duration` should be passed by value rather than const reference. +// `Duration` is trivially destructible and should be passed by value rather +// than const reference. // // Factory functions `Nanoseconds()`, `Microseconds()`, `Milliseconds()`, // `Seconds()`, `Minutes()`, `Hours()` and `InfiniteDuration()` allow for @@ -313,12 +324,12 @@ class Duration { // Relational Operators -#ifdef __cpp_lib_three_way_comparison +#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( Duration lhs, Duration rhs); -#endif // __cpp_lib_three_way_comparison +#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, Duration rhs); @@ -609,12 +620,12 @@ ABSL_ATTRIBUTE_CONST_FUNCTION Duration Hours(T n) { // // absl::Duration d = absl::Milliseconds(1500); // int64_t isec = absl::ToInt64Seconds(d); // isec == 1 -ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Nanoseconds(Duration d); -ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Microseconds(Duration d); -ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d); -ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Seconds(Duration d); -ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Minutes(Duration d); -ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Hours(Duration d); +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Nanoseconds(Duration d); +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Microseconds(Duration d); +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Milliseconds(Duration d); +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Seconds(Duration d); +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Minutes(Duration d); +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Hours(Duration d); // ToDoubleNanoseconds() // ToDoubleMicroseconds() @@ -738,8 +749,9 @@ std::string UnparseFlag(Duration d); // are provided for naturally expressing time calculations. Instances are // created using `absl::Now()` and the `absl::From*()` factory functions that // accept the gamut of other time representations. Formatting and parsing -// functions are provided for conversion to and from strings. `absl::Time` -// should be passed by value rather than const reference. +// functions are provided for conversion to and from strings. `absl::Time` is +// trivially destructible and should be passed by value rather than const +// reference. // // `absl::Time` assumes there are 60 seconds in a minute, which means the // underlying time scales must be "smeared" to eliminate leap seconds. @@ -853,9 +865,9 @@ class Time { friend constexpr Time time_internal::FromUnixDuration(Duration d); friend constexpr Duration time_internal::ToUnixDuration(Time t); -#ifdef __cpp_lib_three_way_comparison +#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs); -#endif // __cpp_lib_three_way_comparison +#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON friend constexpr bool operator<(Time lhs, Time rhs); friend constexpr bool operator==(Time lhs, Time rhs); @@ -868,14 +880,14 @@ class Time { }; // Relational Operators -#ifdef __cpp_lib_three_way_comparison +#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( Time lhs, Time rhs) { return lhs.rep_ <=> rhs.rep_; } -#endif // __cpp_lib_three_way_comparison +#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) { return lhs.rep_ < rhs.rep_; @@ -1752,8 +1764,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs); } - -#ifdef __cpp_lib_three_way_comparison +#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( Duration lhs, Duration rhs) { @@ -1769,7 +1780,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( : lhs_lo <=> rhs_lo; } -#endif // __cpp_lib_three_way_comparison +#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs, Duration rhs) { @@ -1853,6 +1864,56 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromTimeT(time_t t) { return time_internal::FromUnixDuration(Seconds(t)); } +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Nanoseconds(Duration d) { + if (time_internal::GetRepHi(d) >= 0 && + time_internal::GetRepHi(d) >> 33 == 0) { + return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) + + (time_internal::GetRepLo(d) / time_internal::kTicksPerNanosecond); + } + return d / Nanoseconds(1); +} + +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Microseconds(Duration d) { + if (time_internal::GetRepHi(d) >= 0 && + time_internal::GetRepHi(d) >> 43 == 0) { + return (time_internal::GetRepHi(d) * 1000 * 1000) + + (time_internal::GetRepLo(d) / + (time_internal::kTicksPerNanosecond * 1000)); + } + return d / Microseconds(1); +} + +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Milliseconds(Duration d) { + if (time_internal::GetRepHi(d) >= 0 && + time_internal::GetRepHi(d) >> 53 == 0) { + return (time_internal::GetRepHi(d) * 1000) + + (time_internal::GetRepLo(d) / + (time_internal::kTicksPerNanosecond * 1000 * 1000)); + } + return d / Milliseconds(1); +} + +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Seconds(Duration d) { + int64_t hi = time_internal::GetRepHi(d); + if (time_internal::IsInfiniteDuration(d)) return hi; + if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; + return hi; +} + +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Minutes(Duration d) { + int64_t hi = time_internal::GetRepHi(d); + if (time_internal::IsInfiniteDuration(d)) return hi; + if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; + return hi / 60; +} + +ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64Hours(Duration d) { + int64_t hi = time_internal::GetRepHi(d); + if (time_internal::IsInfiniteDuration(d)) return hi; + if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; + return hi / (60 * 60); +} + ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/time/ya.make b/contrib/restricted/abseil-cpp/absl/time/ya.make index 65dd554e05..d1535c64a8 100644 --- a/contrib/restricted/abseil-cpp/absl/time/ya.make +++ b/contrib/restricted/abseil-cpp/absl/time/ya.make @@ -9,7 +9,7 @@ LICENSE( LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/types/internal/span.h b/contrib/restricted/abseil-cpp/absl/types/internal/span.h index ab89ba3ca7..1039f612b6 100644 --- a/contrib/restricted/abseil-cpp/absl/types/internal/span.h +++ b/contrib/restricted/abseil-cpp/absl/types/internal/span.h @@ -22,6 +22,7 @@ #include <type_traits> #include "absl/algorithm/algorithm.h" +#include "absl/base/config.h" #include "absl/base/internal/throw_delegate.h" #include "absl/meta/type_traits.h" @@ -86,13 +87,13 @@ using EnableIfMutable = typename std::enable_if<!std::is_const<T>::value, int>::type; template <template <typename> class SpanT, typename T> -bool EqualImpl(SpanT<T> a, SpanT<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool EqualImpl(SpanT<T> a, SpanT<T> b) { static_assert(std::is_const<T>::value, ""); return std::equal(a.begin(), a.end(), b.begin(), b.end()); } template <template <typename> class SpanT, typename T> -bool LessThanImpl(SpanT<T> a, SpanT<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool LessThanImpl(SpanT<T> a, SpanT<T> b) { // We can't use value_type since that is remove_cv_t<T>, so we go the long way // around. static_assert(std::is_const<T>::value, ""); diff --git a/contrib/restricted/abseil-cpp/absl/types/optional.h b/contrib/restricted/abseil-cpp/absl/types/optional.h index cf7249cbe3..0d8f8704c5 100644 --- a/contrib/restricted/abseil-cpp/absl/types/optional.h +++ b/contrib/restricted/abseil-cpp/absl/types/optional.h @@ -429,14 +429,16 @@ class optional : private optional_internal::optional_data<T>, // Accesses the underlying `T` value of an `optional`. If the `optional` is // empty, behavior is undefined. constexpr const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND { - return ABSL_HARDENING_ASSERT(this->engaged_), reference(); + ABSL_HARDENING_ASSERT(this->engaged_); + return reference(); } T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_HARDENING_ASSERT(this->engaged_); return reference(); } constexpr const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND { - return ABSL_HARDENING_ASSERT(this->engaged_), std::move(reference()); + ABSL_HARDENING_ASSERT(this->engaged_); + return std::move(reference()); } T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_HARDENING_ASSERT(this->engaged_); diff --git a/contrib/restricted/abseil-cpp/absl/types/span.h b/contrib/restricted/abseil-cpp/absl/types/span.h index a0f80272e9..33904a904b 100644 --- a/contrib/restricted/abseil-cpp/absl/types/span.h +++ b/contrib/restricted/abseil-cpp/absl/types/span.h @@ -61,6 +61,7 @@ #include <utility> #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/nullability.h" @@ -72,6 +73,33 @@ namespace absl { ABSL_NAMESPACE_BEGIN +template <typename T> +class Span; + +ABSL_NAMESPACE_END +} // namespace absl + +// If std::ranges is available, mark Span as satisfying the `view` and +// `borrowed_range` concepts, just like std::span. +#if !defined(__has_include) +#define __has_include(header) 0 +#endif +#if __has_include(<version>) +#include <version> // NOLINT(misc-include-cleaner) +#endif +#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L +#include <ranges> // NOLINT(build/c++20) +template <typename T> + // NOLINTNEXTLINE(build/c++20) +inline constexpr bool std::ranges::enable_view<absl::Span<T>> = true; +template <typename T> + // NOLINTNEXTLINE(build/c++20) +inline constexpr bool std::ranges::enable_borrowed_range<absl::Span<T>> = true; +#endif + +namespace absl { +ABSL_NAMESPACE_BEGIN + //------------------------------------------------------------------------------ // Span //------------------------------------------------------------------------------ @@ -151,7 +179,7 @@ ABSL_NAMESPACE_BEGIN // int* my_array = new int[10]; // MyRoutine(absl::Span<const int>(my_array, 10)); template <typename T> -class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { +class ABSL_ATTRIBUTE_VIEW Span { private: // Used to determine whether a Span can be constructed from a container of // type C. @@ -187,15 +215,18 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { using difference_type = ptrdiff_t; using absl_internal_is_view = std::true_type; + // NOLINTNEXTLINE static const size_type npos = ~(size_type(0)); constexpr Span() noexcept : Span(nullptr, 0) {} - constexpr Span(pointer array, size_type length) noexcept + constexpr Span(pointer array ABSL_ATTRIBUTE_LIFETIME_BOUND, + size_type length) noexcept : ptr_(array), len_(length) {} // Implicit conversion constructors template <size_t N> - constexpr Span(T (&a)[N]) noexcept // NOLINT(runtime/explicit) + constexpr Span(T( // NOLINT(google-explicit-constructor) + &a ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) noexcept : Span(a, N) {} // Explicit reference constructor for a mutable `Span<T>` type. Can be @@ -212,9 +243,8 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { template <typename V, typename = EnableIfConvertibleFrom<V>, typename = EnableIfValueIsConst<V>, typename = span_internal::EnableIfNotIsView<V>> - constexpr Span( - const V& v - ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/explicit) + // NOLINTNEXTLINE(google-explicit-constructor) + constexpr Span(const V& v ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept : Span(span_internal::GetData(v), v.size()) {} // Overloads of the above two functions that are only enabled for view types. @@ -229,7 +259,7 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { template <typename V, typename = EnableIfConvertibleFrom<V>, typename = EnableIfValueIsConst<V>, span_internal::EnableIfIsView<V> = 0> - constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit) + constexpr Span(const V& v) noexcept // NOLINT(google-explicit-constructor) : Span(span_internal::GetData(v), v.size()) {} // Implicit constructor from an initializer list, making it possible to pass a @@ -300,7 +330,8 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { // // Returns a reference to the i'th element of this span. constexpr reference operator[](size_type i) const noexcept { - return ABSL_HARDENING_ASSERT(i < size()), ptr_[i]; + ABSL_HARDENING_ASSERT(i < size()); + return ptr_[i]; } // Span::at() @@ -319,7 +350,8 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { // Returns a reference to the first element of this span. The span must not // be empty. constexpr reference front() const noexcept { - return ABSL_HARDENING_ASSERT(size() > 0), *data(); + ABSL_HARDENING_ASSERT(size() > 0); + return *data(); } // Span::back() @@ -327,7 +359,8 @@ class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { // Returns a reference to the last element of this span. The span must not // be empty. constexpr reference back() const noexcept { - return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1); + ABSL_HARDENING_ASSERT(size() > 0); + return *(data() + size() - 1); } // Span::begin() @@ -492,157 +525,165 @@ const typename Span<T>::size_type Span<T>::npos; // operator== template <typename T> -bool operator==(Span<T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, Span<T> b) { return span_internal::EqualImpl<Span, const T>(a, b); } template <typename T> -bool operator==(Span<const T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<const T> a, + Span<T> b) { return span_internal::EqualImpl<Span, const T>(a, b); } template <typename T> -bool operator==(Span<T> a, Span<const T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, + Span<const T> b) { return span_internal::EqualImpl<Span, const T>(a, b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator==(const U& a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(const U& a, Span<T> b) { return span_internal::EqualImpl<Span, const T>(a, b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator==(Span<T> a, const U& b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, const U& b) { return span_internal::EqualImpl<Span, const T>(a, b); } // operator!= template <typename T> -bool operator!=(Span<T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, Span<T> b) { return !(a == b); } template <typename T> -bool operator!=(Span<const T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<const T> a, + Span<T> b) { return !(a == b); } template <typename T> -bool operator!=(Span<T> a, Span<const T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, + Span<const T> b) { return !(a == b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator!=(const U& a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(const U& a, Span<T> b) { return !(a == b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator!=(Span<T> a, const U& b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, const U& b) { return !(a == b); } // operator< template <typename T> -bool operator<(Span<T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<T> b) { return span_internal::LessThanImpl<Span, const T>(a, b); } template <typename T> -bool operator<(Span<const T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<const T> a, Span<T> b) { return span_internal::LessThanImpl<Span, const T>(a, b); } template <typename T> -bool operator<(Span<T> a, Span<const T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<const T> b) { return span_internal::LessThanImpl<Span, const T>(a, b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<(const U& a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(const U& a, Span<T> b) { return span_internal::LessThanImpl<Span, const T>(a, b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<(Span<T> a, const U& b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, const U& b) { return span_internal::LessThanImpl<Span, const T>(a, b); } // operator> template <typename T> -bool operator>(Span<T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<T> b) { return b < a; } template <typename T> -bool operator>(Span<const T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<const T> a, Span<T> b) { return b < a; } template <typename T> -bool operator>(Span<T> a, Span<const T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<const T> b) { return b < a; } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>(const U& a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(const U& a, Span<T> b) { return b < a; } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>(Span<T> a, const U& b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, const U& b) { return b < a; } // operator<= template <typename T> -bool operator<=(Span<T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, Span<T> b) { return !(b < a); } template <typename T> -bool operator<=(Span<const T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<const T> a, + Span<T> b) { return !(b < a); } template <typename T> -bool operator<=(Span<T> a, Span<const T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, + Span<const T> b) { return !(b < a); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<=(const U& a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(const U& a, Span<T> b) { return !(b < a); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator<=(Span<T> a, const U& b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, const U& b) { return !(b < a); } // operator>= template <typename T> -bool operator>=(Span<T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, Span<T> b) { return !(a < b); } template <typename T> -bool operator>=(Span<const T> a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<const T> a, + Span<T> b) { return !(a < b); } template <typename T> -bool operator>=(Span<T> a, Span<const T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, + Span<const T> b) { return !(a < b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>=(const U& a, Span<T> b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(const U& a, Span<T> b) { return !(a < b); } template < typename T, typename U, typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> -bool operator>=(Span<T> a, const U& b) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, const U& b) { return !(a < b); } @@ -689,8 +730,8 @@ constexpr Span<T> MakeSpan(absl::Nullable<T*> ptr, size_t size) noexcept { template <int&... ExplicitArgumentBarrier, typename T> Span<T> MakeSpan(absl::Nullable<T*> begin, absl::Nullable<T*> end) noexcept { - return ABSL_HARDENING_ASSERT(begin <= end), - Span<T>(begin, static_cast<size_t>(end - begin)); + ABSL_HARDENING_ASSERT(begin <= end); + return Span<T>(begin, static_cast<size_t>(end - begin)); } template <int&... ExplicitArgumentBarrier, typename C> @@ -737,7 +778,8 @@ constexpr Span<const T> MakeConstSpan(absl::Nullable<T*> ptr, template <int&... ExplicitArgumentBarrier, typename T> Span<const T> MakeConstSpan(absl::Nullable<T*> begin, absl::Nullable<T*> end) noexcept { - return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin); + ABSL_HARDENING_ASSERT(begin <= end); + return Span<const T>(begin, end - begin); } template <int&... ExplicitArgumentBarrier, typename C> diff --git a/contrib/restricted/abseil-cpp/absl/types/ya.make b/contrib/restricted/abseil-cpp/absl/types/ya.make index 9b6bb742e8..6dbfc699fe 100644 --- a/contrib/restricted/abseil-cpp/absl/types/ya.make +++ b/contrib/restricted/abseil-cpp/absl/types/ya.make @@ -6,7 +6,7 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/utility/ya.make b/contrib/restricted/abseil-cpp/absl/utility/ya.make index 4e3328995c..2deef3b2a7 100644 --- a/contrib/restricted/abseil-cpp/absl/utility/ya.make +++ b/contrib/restricted/abseil-cpp/absl/utility/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240722.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20250127.0.tar.gz) NO_RUNTIME() diff --git a/contrib/restricted/abseil-cpp/patches/pr1728-fix-ndk-r25.patch b/contrib/restricted/abseil-cpp/patches/pr1728-fix-ndk-r25.patch deleted file mode 100644 index 6c2740f66f..0000000000 --- a/contrib/restricted/abseil-cpp/patches/pr1728-fix-ndk-r25.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 90a8bda23077508ca208e7afc535da1e2c7d59ae Mon Sep 17 00:00:00 2001 -From: Yuriy Chernyshov <thegeorg@yandex-team.com> -Date: Thu, 25 Jul 2024 22:50:40 +0300 -Subject: [PATCH 1/3] Workaround broken compilation against NDK r25 - ---- - absl/time/time.h | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/absl/time/time.h b/absl/time/time.h -index f133c2d2ca8..15edbb4a667 100644 ---- a/absl/time/time.h -+++ b/absl/time/time.h -@@ -76,9 +76,9 @@ struct timeval; - #endif - #include <chrono> // NOLINT(build/c++11) - --#ifdef __cpp_impl_three_way_comparison -+#ifdef __cpp_lib_three_way_comparison - #include <compare> --#endif // __cpp_impl_three_way_comparison -+#endif // __cpp_lib_three_way_comparison - - #include <cmath> - #include <cstdint> -@@ -313,12 +313,12 @@ class Duration { - - // Relational Operators - --#ifdef __cpp_impl_three_way_comparison -+#ifdef __cpp_lib_three_way_comparison - - ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( - Duration lhs, Duration rhs); - --#endif // __cpp_impl_three_way_comparison -+#endif // __cpp_lib_three_way_comparison - - ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, - Duration rhs); -@@ -853,9 +853,9 @@ class Time { - friend constexpr Time time_internal::FromUnixDuration(Duration d); - friend constexpr Duration time_internal::ToUnixDuration(Time t); - --#ifdef __cpp_impl_three_way_comparison -+#ifdef __cpp_lib_three_way_comparison - friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs); --#endif // __cpp_impl_three_way_comparison -+#endif // __cpp_lib_three_way_comparison - - friend constexpr bool operator<(Time lhs, Time rhs); - friend constexpr bool operator==(Time lhs, Time rhs); -@@ -868,14 +868,14 @@ class Time { - }; - - // Relational Operators --#ifdef __cpp_impl_three_way_comparison -+#ifdef __cpp_lib_three_way_comparison - - ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( - Time lhs, Time rhs) { - return lhs.rep_ <=> rhs.rep_; - } - --#endif // __cpp_impl_three_way_comparison -+#endif // __cpp_lib_three_way_comparison - - ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) { - return lhs.rep_ < rhs.rep_; -@@ -1753,7 +1753,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, - } - - --#ifdef __cpp_impl_three_way_comparison -+#ifdef __cpp_lib_three_way_comparison - - ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( - Duration lhs, Duration rhs) { -@@ -1769,7 +1769,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( - : lhs_lo <=> rhs_lo; - } - --#endif // __cpp_impl_three_way_comparison -+#endif // __cpp_lib_three_way_comparison - - ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs, - Duration rhs) { diff --git a/contrib/restricted/abseil-cpp/ya.make b/contrib/restricted/abseil-cpp/ya.make index 4e45866048..51c20bfbc2 100644 --- a/contrib/restricted/abseil-cpp/ya.make +++ b/contrib/restricted/abseil-cpp/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(20240722.1) +VERSION(20250127.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240722.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20250127.0.tar.gz) PEERDIR( contrib/restricted/abseil-cpp/absl/algorithm |