diff options
author | Innokentii Mokin <innokentii@ydb.tech> | 2024-01-27 10:01:54 +0000 |
---|---|---|
committer | Innokentii Mokin <innokentii@ydb.tech> | 2024-01-27 10:01:54 +0000 |
commit | 621e3d86c4e02bf3c88bb68e5aba5856fbf0185d (patch) | |
tree | 2d517d0985015d27ce6862003509de502be44ccc | |
parent | a7dad28338e49d920879eb2b3e728ee6dd166b6e (diff) | |
parent | 00b9982cd019afca788639aa8279f2dc1f342383 (diff) | |
download | ydb-621e3d86c4e02bf3c88bb68e5aba5856fbf0185d.tar.gz |
Merge branch 'mergelibs11' into main
646 files changed, 17057 insertions, 9254 deletions
diff --git a/build/conf/go.conf b/build/conf/go.conf index c58492e17c..397a55cd5e 100644 --- a/build/conf/go.conf +++ b/build/conf/go.conf @@ -63,9 +63,6 @@ GOSTD_VERSION=1.21 when ($GOSTD_VERSION == "1.21") { GOSTD=contrib/go/_std_1.21/src } -elsewhen ($GOSTD_VERSION == "1.20") { - GOSTD=contrib/go/_std_1.20/src -} otherwise { GOSTD=__unsupported_go_std_library_version_[$GOSTD_VERSION]__ } diff --git a/build/conf/python.conf b/build/conf/python.conf index 8fcd11593d..27a8bcd47a 100644 --- a/build/conf/python.conf +++ b/build/conf/python.conf @@ -237,6 +237,17 @@ macro STYLE_PYTHON(pyproject...) { } # tag:python-specific tag:test +STYLE_RUFF_VALUE=no +STYLE_RUFF_PYPROJECT_VALUE= +### @usage: STYLE_RUFF([pyproject]) +### +### Check python3 sources for style issues using ruff. +macro STYLE_RUFF(pyproject...) { + SET(STYLE_RUFF_VALUE yes) + SET(STYLE_RUFF_PYPROJECT_VALUE ${pyproject}) +} + +# tag:python-specific tag:test ### @usage: NO_DOCTESTS() ### ### Disable doctests in PY[|3|23_]TEST diff --git a/build/export_generators/hardcoded-cmake/cmake/common.cmake b/build/export_generators/hardcoded-cmake/cmake/common.cmake index 0ffe61ad17..f85875ec40 100644 --- a/build/export_generators/hardcoded-cmake/cmake/common.cmake +++ b/build/export_generators/hardcoded-cmake/cmake/common.cmake @@ -296,13 +296,13 @@ function(set_yunittest_property) get_property(SPLIT_FACTOR TARGET ${YUNITTEST_ARGS_TEST} PROPERTY SPLIT_FACTOR) if ((${SPLIT_FACTOR} EQUAL 1) OR (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/run_testpack")) - set_property(TEST ${YUNITTEST_ARGS_TEST} PROPERTY ${YUNITTEST_ARGS_PROPERTY} ${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}) + set_property(TEST ${YUNITTEST_ARGS_TEST} PROPERTY ${YUNITTEST_ARGS_PROPERTY} "${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}") return() endif() math(EXPR LastIdx "${SPLIT_FACTOR} - 1") foreach(Idx RANGE ${LastIdx}) - set_property(TEST ${YUNITTEST_ARGS_TEST}_${Idx} PROPERTY ${YUNITTEST_ARGS_PROPERTY} ${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}) + set_property(TEST ${YUNITTEST_ARGS_TEST}_${Idx} PROPERTY ${YUNITTEST_ARGS_PROPERTY} "${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}") endforeach() endfunction() diff --git a/build/export_generators/hardcoded-cmake/generator.toml b/build/export_generators/hardcoded-cmake/generator.toml index 648d69108a..8d1fe96420 100644 --- a/build/export_generators/hardcoded-cmake/generator.toml +++ b/build/export_generators/hardcoded-cmake/generator.toml @@ -84,7 +84,7 @@ attrs=[ "target_sources_custom", "use_export_script", "add_yunittest", - "set_yunittest_property", + "set_yunittest_property", ] copy=[ "cmake/common.cmake", diff --git a/build/external_resources/gdb/resources.json b/build/external_resources/gdb/resources.json index 15c8f4e246..4f14a48ebe 100644 --- a/build/external_resources/gdb/resources.json +++ b/build/external_resources/gdb/resources.json @@ -7,10 +7,10 @@ "uri": "sbr:2319130389" }, "linux-x86_64": { - "uri": "sbr:5709310220" + "uri": "sbr:5720181629" }, "linux-aarch64": { - "uri": "sbr:5709435327" + "uri": "sbr:5720688825" } }, "platform_replacements": {}, diff --git a/build/external_resources/go_tools/go1.20.json b/build/external_resources/go_tools/go1.20.json deleted file mode 100644 index 703d0ede76..0000000000 --- a/build/external_resources/go_tools/go1.20.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "by_platform": { - "darwin-arm64": { - "uri": "sbr:4773521027" - }, - "darwin-x86_64": { - "uri": "sbr:4773516480" - }, - "linux-x86_64": { - "uri": "sbr:4773507347" - }, - "linux-aarch64": { - "uri": "sbr:4773511397" - }, - "win32-x86_64": { - "uri": "sbr:4773525032" - } - } -} diff --git a/build/external_resources/go_tools/go1.21.json b/build/external_resources/go_tools/go1.21.json index 7cc1c52c3d..30dd9f3369 100644 --- a/build/external_resources/go_tools/go1.21.json +++ b/build/external_resources/go_tools/go1.21.json @@ -1,19 +1,19 @@ { "by_platform": { "darwin-arm64": { - "uri": "sbr:5424061624" + "uri": "sbr:5720722976" }, "darwin-x86_64": { - "uri": "sbr:5424057306" + "uri": "sbr:5720717636" }, "linux-x86_64": { - "uri": "sbr:5424033677" + "uri": "sbr:5720706939" }, "linux-aarch64": { - "uri": "sbr:5424038053" + "uri": "sbr:5720713011" }, "win32-x86_64": { - "uri": "sbr:5424051723" + "uri": "sbr:5720736838" } } } diff --git a/build/external_resources/go_tools/ya.make b/build/external_resources/go_tools/ya.make index 24807da914..697ae83a5e 100644 --- a/build/external_resources/go_tools/ya.make +++ b/build/external_resources/go_tools/ya.make @@ -1,8 +1,6 @@ RESOURCES_LIBRARY() -IF(GOSTD_VERSION == 1.20) - DECLARE_EXTERNAL_HOST_RESOURCES_BUNDLE_BY_JSON(GO_TOOLS go1.20.json) -ELSEIF(GOSTD_VERSION == 1.21) +IF(GOSTD_VERSION == 1.21) DECLARE_EXTERNAL_HOST_RESOURCES_BUNDLE_BY_JSON(GO_TOOLS go1.21.json) ELSE() MESSAGE(FATAL_ERROR Unsupported version [${GOSTD_VERSION}] of Go Standard Library) diff --git a/build/mapping.conf.json b/build/mapping.conf.json index 07c8b9afc5..d931e3d12a 100644 --- a/build/mapping.conf.json +++ b/build/mapping.conf.json @@ -36,6 +36,11 @@ "5424033677": "https://devtools-registry.s3.yandex.net/5424033677", "5424038053": "https://devtools-registry.s3.yandex.net/5424038053", "5424051723": "https://devtools-registry.s3.yandex.net/5424051723", + "5720717636": "https://devtools-registry.s3.yandex.net/5720717636", + "5720722976": "https://devtools-registry.s3.yandex.net/5720722976", + "5720706939": "https://devtools-registry.s3.yandex.net/5720706939", + "5720713011": "https://devtools-registry.s3.yandex.net/5720713011", + "5720736838": "https://devtools-registry.s3.yandex.net/5720736838", "5543659225": "https://devtools-registry.s3.yandex.net/5543659225", "5560184603": "https://devtools-registry.s3.yandex.net/5560184603", "5553311553": "https://devtools-registry.s3.yandex.net/5553311553", @@ -51,7 +56,9 @@ "1966560555": "https://devtools-registry.s3.yandex.net/1966560555", "309054781": "https://devtools-registry.s3.yandex.net/309054781", "5298918458": "https://devtools-registry.s3.yandex.net/5298918458", + "5720688825": "https://devtools-registry.s3.yandex.net/5720688825", "5298901591": "https://devtools-registry.s3.yandex.net/5298901591", + "5720181629": "https://devtools-registry.s3.yandex.net/5720181629", "5709310220": "https://devtools-registry.s3.yandex.net/5709310220", "5709435327": "https://devtools-registry.s3.yandex.net/5709435327", "360916612": "https://devtools-registry.s3.yandex.net/360916612", @@ -102,6 +109,7 @@ "5675381622": "https://devtools-registry.s3.yandex.net/5675381622", "5683487438": "https://devtools-registry.s3.yandex.net/5683487438", "5707396874": "https://devtools-registry.s3.yandex.net/5707396874", + "5720350134": "https://devtools-registry.s3.yandex.net/5720350134", "5486731632": "https://devtools-registry.s3.yandex.net/5486731632", "5514350352": "https://devtools-registry.s3.yandex.net/5514350352", "5514360398": "https://devtools-registry.s3.yandex.net/5514360398", @@ -121,6 +129,8 @@ "5683523790": "https://devtools-registry.s3.yandex.net/5683523790", "5707396152": "https://devtools-registry.s3.yandex.net/5707396152", "5707407435": "https://devtools-registry.s3.yandex.net/5707407435", + "5720351188": "https://devtools-registry.s3.yandex.net/5720351188", + "5720356918": "https://devtools-registry.s3.yandex.net/5720356918", "4307890075": "https://devtools-registry.s3.yandex.net/4307890075", "5517245192": "https://devtools-registry.s3.yandex.net/5517245192", "4307901240": "https://devtools-registry.s3.yandex.net/4307901240", @@ -235,6 +245,11 @@ "5424033677": "OTHER_RESOURCE-none-1.21.3-y_go1.21.3.linux-amd64.tar.gz", "5424038053": "OTHER_RESOURCE-none-1.21.3-y_go1.21.3.linux-arm64.tar.gz", "5424051723": "OTHER_RESOURCE-none-1.21.3-y_go1.21.3.windows-amd64.tar.gz", + "5720717636": "OTHER_RESOURCE-none-1.21.6-y_go1.21.6.darwin-amd64.tar.gz", + "5720722976": "OTHER_RESOURCE-none-1.21.6-y_go1.21.6.darwin-arm64.tar.gz", + "5720706939": "OTHER_RESOURCE-none-1.21.6-y_go1.21.6.linux-amd64.tar.gz", + "5720713011": "OTHER_RESOURCE-none-1.21.6-y_go1.21.6.linux-arm64.tar.gz", + "5720736838": "OTHER_RESOURCE-none-1.21.6-y_go1.21.6.windows-amd64.tar.gz", "5543659225": "OTHER_RESOURCE-none-none-clang-darwin-arm64.tgz", "5560184603": "OTHER_RESOURCE-none-none-clang-mingw64.tgz", "5553311553": "OTHER_RESOURCE-none-none-clang-new-darwin-arm64.tgz", @@ -250,7 +265,9 @@ "1966560555": "Ubuntu 14 x86-64 native SDK (patched, v3)", "309054781": "Ubuntu 16 x86-64 -> Ubuntu 16 aarch64 cross SDK", "5298918458": "bin-gdb-reloc-ya-linux-aarch64-62901b3b39a8b08c2d39a3bf08a1fc3a6d76eb78", + "5720688825": "bin-gdb-reloc-ya-linux-aarch64-62901b3b39a8b08c2d39a3bf08a1fc3a6d76eb78", "5298901591": "bin-gdb-reloc-ya-linux-x86_64-62901b3b39a8b08c2d39a3bf08a1fc3a6d76eb78", + "5720181629": "bin-gdb-reloc-ya-linux-x86_64-62901b3b39a8b08c2d39a3bf08a1fc3a6d76eb78", "5709310220": "bin-gdb-reloc-ya-linux-x86_64-70970b31ef83c56b51291cd8fe4f24449b582b59", "5709435327": "bin-gdb-reloc-ya-linux-x86_64-70970b31ef83c56b51291cd8fe4f24449b582b59", "360916612": "binutils 2.26 for linux_ubuntu_10.04_lucid", @@ -301,6 +318,7 @@ "5675381622": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", "5683487438": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", "5707396874": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", + "5720350134": "devtools/ya/test/programs/test_tool/bin/test_tool for linux", "5486731632": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", "5514350352": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", "5514360398": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", @@ -320,6 +338,8 @@ "5683523790": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", "5707396152": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", "5707407435": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", + "5720351188": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", + "5720356918": "devtools/ya/test/programs/test_tool/bin3/test_tool3 for linux", "4307890075": "flake8_linter for linux", "5517245192": "flake8_linter for linux", "4307901240": "flake8_linter for linux-aarch64", diff --git a/build/platform/test_tool/host.ya.make.inc b/build/platform/test_tool/host.ya.make.inc index 00cdf84292..6c7d6bb454 100644 --- a/build/platform/test_tool/host.ya.make.inc +++ b/build/platform/test_tool/host.ya.make.inc @@ -1,17 +1,17 @@ IF (HOST_OS_DARWIN AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707394532) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707406472) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720349017) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720356281) ELSEIF (HOST_OS_DARWIN AND HOST_ARCH_ARM64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707393572) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707406025) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720348354) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720355987) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707396874) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707407435) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720350134) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720356918) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_AARCH64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707391802) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707405475) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720347692) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720355628) ELSEIF (HOST_OS_WINDOWS AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707395940) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707406839) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720349493) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720356619) ENDIF() diff --git a/build/platform/test_tool/host_os.ya.make.inc b/build/platform/test_tool/host_os.ya.make.inc index 3f4805fef4..96dc65b607 100644 --- a/build/platform/test_tool/host_os.ya.make.inc +++ b/build/platform/test_tool/host_os.ya.make.inc @@ -1,17 +1,17 @@ IF (HOST_OS_DARWIN AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707395021) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707395021) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720350265) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720350265) ELSEIF (HOST_OS_DARWIN AND HOST_ARCH_ARM64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707394418) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707394418) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720349877) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720349877) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707396152) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707396152) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720351188) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720351188) ELSEIF (HOST_OS_LINUX AND HOST_ARCH_AARCH64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707393967) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707393967) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720349514) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720349514) ELSEIF (HOST_OS_WINDOWS AND HOST_ARCH_X86_64) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5707395714) - DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5707395714) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL_HOST sbr:5720350722) + DECLARE_EXTERNAL_RESOURCE(TEST_TOOL3_HOST sbr:5720350722) ENDIF() diff --git a/build/plugins/lib/test_const/__init__.py b/build/plugins/lib/test_const/__init__.py index 8037a5c266..8a91bd5ebe 100644 --- a/build/plugins/lib/test_const/__init__.py +++ b/build/plugins/lib/test_const/__init__.py @@ -200,6 +200,7 @@ GO_TOOLS_RESOURCE = 'GO_TOOLS_RESOURCE_GLOBAL' JSTYLE_RUNNER_LIB = 'JSTYLE_LIB_RESOURCE_GLOBAL' NODEJS_RESOURCE = 'NODEJS_RESOURCE_GLOBAL' NYC_RESOURCE = 'NYC_RESOURCE_GLOBAL' +RUFF_RESOURCE = 'RUFF_RESOURCE_GLOBAL' TEST_TOOL3_HOST = 'TEST_TOOL3_HOST_RESOURCE_GLOBAL' TEST_TOOL3_HOST_LOCAL = 'TEST_TOOL3_HOST_LOCAL' TEST_TOOL_HOST = 'TEST_TOOL_HOST_RESOURCE_GLOBAL' diff --git a/build/plugins/pybuild.py b/build/plugins/pybuild.py index 23ace17669..e58f0906cd 100644 --- a/build/plugins/pybuild.py +++ b/build/plugins/pybuild.py @@ -145,6 +145,8 @@ def add_python_lint_checks(unit, py_ver, files): resolved_files.append(resolved) return resolved_files + upath = unit.path()[3:] + no_lint_value = get_no_lint_value(unit) if no_lint_value == "none": no_lint_allowed_paths = ( @@ -161,8 +163,6 @@ def add_python_lint_checks(unit, py_ver, files): "yt/python/", # YT-20053 ) - upath = unit.path()[3:] - if not upath.startswith(no_lint_allowed_paths): ymake.report_configure_error("NO_LINT() is allowed only in " + ", ".join(no_lint_allowed_paths)) @@ -193,6 +193,27 @@ def add_python_lint_checks(unit, py_ver, files): params += ["EXTRA_PARAMS"] + extra_params unit.on_add_linter_check(params) + # ruff related stuff + if unit.get('STYLE_RUFF_VALUE') == 'yes': + if no_lint_value in ("none", "none_internal"): + ymake.report_configure_error( + 'NO_LINT() and STYLE_RUFF() can\'t be enabled both at the same time', + ) + # temporary allow using ruff for taxi only + ruff_allowed_paths = ("taxi/",) + if not upath.startswith(ruff_allowed_paths): + ymake.report_configure_error("STYLE_RUFF() is allowed only in " + ", ".join(ruff_allowed_paths)) + + resolved_files = get_resolved_files() + if resolved_files: + resource = "build/external_resources/ruff" + params = ["ruff", "tools/ruff_linter/bin/ruff_linter"] + params += ["FILES"] + resolved_files + params += ["GLOBAL_RESOURCES", resource] + ruff_cfg = unit.get('STYLE_RUFF_PYPROJECT_VALUE') or 'build/config/tests/ruff/ruff.toml' + params += ['CONFIGS', ruff_cfg] + unit.on_add_linter_check(params) + if files and unit.get('STYLE_PYTHON_VALUE') == 'yes' and is_py3(unit): resolved_files = get_resolved_files() if resolved_files: diff --git a/build/sysincl/stl-to-libcxx.yml b/build/sysincl/stl-to-libcxx.yml index 102c1b517e..7b3149fef0 100644 --- a/build/sysincl/stl-to-libcxx.yml +++ b/build/sysincl/stl-to-libcxx.yml @@ -88,6 +88,7 @@ - cwctype: contrib/libs/cxxsupp/libcxx/include/cwctype - deque: contrib/libs/cxxsupp/libcxx/include/deque - exception: contrib/libs/cxxsupp/libcxx/include/exception + - expected: contrib/libs/cxxsupp/libcxx/include/expected - filesystem: contrib/libs/cxxsupp/libcxx/include/filesystem - forward_list: contrib/libs/cxxsupp/libcxx/include/forward_list - fstream: contrib/libs/cxxsupp/libcxx/include/fstream @@ -119,6 +120,7 @@ - scoped_allocator: contrib/libs/cxxsupp/libcxx/include/scoped_allocator - set: contrib/libs/cxxsupp/libcxx/include/set - shared_mutex: contrib/libs/cxxsupp/libcxx/include/shared_mutex + - source_location: contrib/libs/cxxsupp/libcxx/include/source_location - span: contrib/libs/cxxsupp/libcxx/include/span - sstream: contrib/libs/cxxsupp/libcxx/include/sstream - stack: contrib/libs/cxxsupp/libcxx/include/stack @@ -168,7 +170,6 @@ - __assert: contrib/libs/cxxsupp/libcxx/include/__assert - __availability: contrib/libs/cxxsupp/libcxx/include/__availability - __bit_reference: contrib/libs/cxxsupp/libcxx/include/__bit_reference - - __bits: contrib/libs/cxxsupp/libcxx/include/__bits - __bsd_locale_defaults.h: contrib/libs/cxxsupp/libcxx/include/__bsd_locale_defaults.h - __bsd_locale_fallbacks.h: contrib/libs/cxxsupp/libcxx/include/__bsd_locale_fallbacks.h - __config: contrib/libs/cxxsupp/libcxx/include/__config @@ -197,6 +198,7 @@ - __algorithm/copy.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/copy.h - __algorithm/copy_backward.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_backward.h - __algorithm/copy_if.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_if.h + - __algorithm/copy_move_common.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_move_common.h - __algorithm/copy_n.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_n.h - __algorithm/count.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/count.h - __algorithm/count_if.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/count_if.h @@ -378,7 +380,18 @@ - __algorithm/unwrap_range.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/unwrap_range.h - __algorithm/upper_bound.h: contrib/libs/cxxsupp/libcxx/include/__algorithm/upper_bound.h - __bit/bit_cast.h: contrib/libs/cxxsupp/libcxx/include/__bit/bit_cast.h + - __bit/bit_ceil.h: contrib/libs/cxxsupp/libcxx/include/__bit/bit_ceil.h + - __bit/bit_floor.h: contrib/libs/cxxsupp/libcxx/include/__bit/bit_floor.h + - __bit/bit_log2.h: contrib/libs/cxxsupp/libcxx/include/__bit/bit_log2.h + - __bit/bit_width.h: contrib/libs/cxxsupp/libcxx/include/__bit/bit_width.h + - __bit/blsr.h: contrib/libs/cxxsupp/libcxx/include/__bit/blsr.h - __bit/byteswap.h: contrib/libs/cxxsupp/libcxx/include/__bit/byteswap.h + - __bit/countl.h: contrib/libs/cxxsupp/libcxx/include/__bit/countl.h + - __bit/countr.h: contrib/libs/cxxsupp/libcxx/include/__bit/countr.h + - __bit/endian.h: contrib/libs/cxxsupp/libcxx/include/__bit/endian.h + - __bit/has_single_bit.h: contrib/libs/cxxsupp/libcxx/include/__bit/has_single_bit.h + - __bit/popcount.h: contrib/libs/cxxsupp/libcxx/include/__bit/popcount.h + - __bit/rotate.h: contrib/libs/cxxsupp/libcxx/include/__bit/rotate.h - __charconv/chars_format.h: contrib/libs/cxxsupp/libcxx/include/__charconv/chars_format.h - __charconv/from_chars_result.h: contrib/libs/cxxsupp/libcxx/include/__charconv/from_chars_result.h - __charconv/tables.h: contrib/libs/cxxsupp/libcxx/include/__charconv/tables.h @@ -448,6 +461,10 @@ - __coroutine/noop_coroutine_handle.h: contrib/libs/cxxsupp/libcxx/include/__coroutine/noop_coroutine_handle.h - __coroutine/trivial_awaitables.h: contrib/libs/cxxsupp/libcxx/include/__coroutine/trivial_awaitables.h - __debug_utils/randomize_range.h: contrib/libs/cxxsupp/libcxx/include/__debug_utils/randomize_range.h + - __expected/bad_expected_access.h: contrib/libs/cxxsupp/libcxx/include/__expected/bad_expected_access.h + - __expected/expected.h: contrib/libs/cxxsupp/libcxx/include/__expected/expected.h + - __expected/unexpect.h: contrib/libs/cxxsupp/libcxx/include/__expected/unexpect.h + - __expected/unexpected.h: contrib/libs/cxxsupp/libcxx/include/__expected/unexpected.h - __filesystem/copy_options.h: contrib/libs/cxxsupp/libcxx/include/__filesystem/copy_options.h - __filesystem/directory_entry.h: contrib/libs/cxxsupp/libcxx/include/__filesystem/directory_entry.h - __filesystem/directory_iterator.h: contrib/libs/cxxsupp/libcxx/include/__filesystem/directory_iterator.h @@ -466,6 +483,7 @@ - __filesystem/u8path.h: contrib/libs/cxxsupp/libcxx/include/__filesystem/u8path.h - __format/buffer.h: contrib/libs/cxxsupp/libcxx/include/__format/buffer.h - __format/concepts.h: contrib/libs/cxxsupp/libcxx/include/__format/concepts.h + - __format/container_adaptor.h: contrib/libs/cxxsupp/libcxx/include/__format/container_adaptor.h - __format/enable_insertable.h: contrib/libs/cxxsupp/libcxx/include/__format/enable_insertable.h - __format/escaped_output_table.h: contrib/libs/cxxsupp/libcxx/include/__format/escaped_output_table.h - __format/extended_grapheme_cluster_table.h: contrib/libs/cxxsupp/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -488,7 +506,10 @@ - __format/formatter_output.h: contrib/libs/cxxsupp/libcxx/include/__format/formatter_output.h - __format/formatter_pointer.h: contrib/libs/cxxsupp/libcxx/include/__format/formatter_pointer.h - __format/formatter_string.h: contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h + - __format/formatter_tuple.h: contrib/libs/cxxsupp/libcxx/include/__format/formatter_tuple.h - __format/parser_std_format_spec.h: contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h + - __format/range_default_formatter.h: contrib/libs/cxxsupp/libcxx/include/__format/range_default_formatter.h + - __format/range_formatter.h: contrib/libs/cxxsupp/libcxx/include/__format/range_formatter.h - __format/unicode.h: contrib/libs/cxxsupp/libcxx/include/__format/unicode.h - __functional/binary_function.h: contrib/libs/cxxsupp/libcxx/include/__functional/binary_function.h - __functional/binary_negate.h: contrib/libs/cxxsupp/libcxx/include/__functional/binary_negate.h @@ -526,6 +547,7 @@ - __fwd/span.h: contrib/libs/cxxsupp/libcxx/include/__fwd/span.h - __fwd/string.h: contrib/libs/cxxsupp/libcxx/include/__fwd/string.h - __fwd/string_view.h: contrib/libs/cxxsupp/libcxx/include/__fwd/string_view.h + - __fwd/subrange.h: contrib/libs/cxxsupp/libcxx/include/__fwd/subrange.h - __fwd/tuple.h: contrib/libs/cxxsupp/libcxx/include/__fwd/tuple.h - __ios/fpos.h: contrib/libs/cxxsupp/libcxx/include/__ios/fpos.h - __iterator/access.h: contrib/libs/cxxsupp/libcxx/include/__iterator/access.h @@ -550,6 +572,7 @@ - __iterator/iter_swap.h: contrib/libs/cxxsupp/libcxx/include/__iterator/iter_swap.h - __iterator/iterator.h: contrib/libs/cxxsupp/libcxx/include/__iterator/iterator.h - __iterator/iterator_traits.h: contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_traits.h + - __iterator/iterator_with_data.h: contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_with_data.h - __iterator/mergeable.h: contrib/libs/cxxsupp/libcxx/include/__iterator/mergeable.h - __iterator/move_iterator.h: contrib/libs/cxxsupp/libcxx/include/__iterator/move_iterator.h - __iterator/move_sentinel.h: contrib/libs/cxxsupp/libcxx/include/__iterator/move_sentinel.h @@ -562,6 +585,7 @@ - __iterator/readable_traits.h: contrib/libs/cxxsupp/libcxx/include/__iterator/readable_traits.h - __iterator/reverse_access.h: contrib/libs/cxxsupp/libcxx/include/__iterator/reverse_access.h - __iterator/reverse_iterator.h: contrib/libs/cxxsupp/libcxx/include/__iterator/reverse_iterator.h + - __iterator/segmented_iterator.h: contrib/libs/cxxsupp/libcxx/include/__iterator/segmented_iterator.h - __iterator/size.h: contrib/libs/cxxsupp/libcxx/include/__iterator/size.h - __iterator/sortable.h: contrib/libs/cxxsupp/libcxx/include/__iterator/sortable.h - __iterator/unreachable_sentinel.h: contrib/libs/cxxsupp/libcxx/include/__iterator/unreachable_sentinel.h @@ -653,6 +677,7 @@ - __random/weibull_distribution.h: contrib/libs/cxxsupp/libcxx/include/__random/weibull_distribution.h - __ranges/access.h: contrib/libs/cxxsupp/libcxx/include/__ranges/access.h - __ranges/all.h: contrib/libs/cxxsupp/libcxx/include/__ranges/all.h + - __ranges/as_rvalue_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/as_rvalue_view.h - __ranges/common_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/common_view.h - __ranges/concepts.h: contrib/libs/cxxsupp/libcxx/include/__ranges/concepts.h - __ranges/copyable_box.h: contrib/libs/cxxsupp/libcxx/include/__ranges/copyable_box.h @@ -661,6 +686,7 @@ - __ranges/data.h: contrib/libs/cxxsupp/libcxx/include/__ranges/data.h - __ranges/drop_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/drop_view.h - __ranges/drop_while_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/drop_while_view.h + - __ranges/elements_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/elements_view.h - __ranges/empty.h: contrib/libs/cxxsupp/libcxx/include/__ranges/empty.h - __ranges/empty_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/empty_view.h - __ranges/enable_borrowed_range.h: contrib/libs/cxxsupp/libcxx/include/__ranges/enable_borrowed_range.h @@ -679,6 +705,7 @@ - __ranges/reverse_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/reverse_view.h - __ranges/single_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/single_view.h - __ranges/size.h: contrib/libs/cxxsupp/libcxx/include/__ranges/size.h + - __ranges/split_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/split_view.h - __ranges/subrange.h: contrib/libs/cxxsupp/libcxx/include/__ranges/subrange.h - __ranges/take_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h - __ranges/take_while_view.h: contrib/libs/cxxsupp/libcxx/include/__ranges/take_while_view.h @@ -707,14 +734,16 @@ - __support/xlocale/__strtonum_fallback.h: contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__strtonum_fallback.h - __thread/poll_with_backoff.h: contrib/libs/cxxsupp/libcxx/include/__thread/poll_with_backoff.h - __thread/timed_backoff_policy.h: contrib/libs/cxxsupp/libcxx/include/__thread/timed_backoff_policy.h - - __tuple/apply_cv.h: contrib/libs/cxxsupp/libcxx/include/__tuple/apply_cv.h - - __tuple/make_tuple_types.h: contrib/libs/cxxsupp/libcxx/include/__tuple/make_tuple_types.h - - __tuple/sfinae_helpers.h: contrib/libs/cxxsupp/libcxx/include/__tuple/sfinae_helpers.h - - __tuple/tuple_element.h: contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_element.h - - __tuple/tuple_indices.h: contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_indices.h - - __tuple/tuple_like.h: contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_like.h - - __tuple/tuple_size.h: contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_size.h - - __tuple/tuple_types.h: contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_types.h + - __tuple_dir/apply_cv.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/apply_cv.h + - __tuple_dir/make_tuple_types.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/make_tuple_types.h + - __tuple_dir/pair_like.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/pair_like.h + - __tuple_dir/sfinae_helpers.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/sfinae_helpers.h + - __tuple_dir/tuple_element.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_element.h + - __tuple_dir/tuple_indices.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_indices.h + - __tuple_dir/tuple_like.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_like.h + - __tuple_dir/tuple_like_ext.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_like_ext.h + - __tuple_dir/tuple_size.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_size.h + - __tuple_dir/tuple_types.h: contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_types.h - __type_traits/add_const.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/add_const.h - __type_traits/add_cv.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/add_cv.h - __type_traits/add_lvalue_reference.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/add_lvalue_reference.h @@ -743,6 +772,7 @@ - __type_traits/is_abstract.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_abstract.h - __type_traits/is_aggregate.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_aggregate.h - __type_traits/is_allocator.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_allocator.h + - __type_traits/is_always_bitcastable.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_always_bitcastable.h - __type_traits/is_arithmetic.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_arithmetic.h - __type_traits/is_array.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_array.h - __type_traits/is_assignable.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_assignable.h @@ -798,6 +828,7 @@ - __type_traits/is_scoped_enum.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_scoped_enum.h - __type_traits/is_signed.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_signed.h - __type_traits/is_signed_integer.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_signed_integer.h + - __type_traits/is_specialization.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_specialization.h - __type_traits/is_standard_layout.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_standard_layout.h - __type_traits/is_swappable.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_swappable.h - __type_traits/is_trivial.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/is_trivial.h @@ -838,6 +869,7 @@ - __type_traits/remove_reference.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/remove_reference.h - __type_traits/remove_volatile.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/remove_volatile.h - __type_traits/result_of.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/result_of.h + - __type_traits/strip_signature.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/strip_signature.h - __type_traits/type_identity.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/type_identity.h - __type_traits/type_list.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/type_list.h - __type_traits/underlying_type.h: contrib/libs/cxxsupp/libcxx/include/__type_traits/underlying_type.h @@ -847,6 +879,7 @@ - __utility/cmp.h: contrib/libs/cxxsupp/libcxx/include/__utility/cmp.h - __utility/convert_to_integral.h: contrib/libs/cxxsupp/libcxx/include/__utility/convert_to_integral.h - __utility/declval.h: contrib/libs/cxxsupp/libcxx/include/__utility/declval.h + - __utility/exception_guard.h: contrib/libs/cxxsupp/libcxx/include/__utility/exception_guard.h - __utility/exchange.h: contrib/libs/cxxsupp/libcxx/include/__utility/exchange.h - __utility/forward.h: contrib/libs/cxxsupp/libcxx/include/__utility/forward.h - __utility/forward_like.h: contrib/libs/cxxsupp/libcxx/include/__utility/forward_like.h @@ -859,7 +892,6 @@ - __utility/rel_ops.h: contrib/libs/cxxsupp/libcxx/include/__utility/rel_ops.h - __utility/swap.h: contrib/libs/cxxsupp/libcxx/include/__utility/swap.h - __utility/to_underlying.h: contrib/libs/cxxsupp/libcxx/include/__utility/to_underlying.h - - __utility/transaction.h: contrib/libs/cxxsupp/libcxx/include/__utility/transaction.h - __utility/unreachable.h: contrib/libs/cxxsupp/libcxx/include/__utility/unreachable.h - __variant/monostate.h: contrib/libs/cxxsupp/libcxx/include/__variant/monostate.h # END OF GENERATION diff --git a/build/sysincl/stl-to-nothing.yml b/build/sysincl/stl-to-nothing.yml index 2d03265c86..f2f3efdcab 100644 --- a/build/sysincl/stl-to-nothing.yml +++ b/build/sysincl/stl-to-nothing.yml @@ -71,6 +71,7 @@ - cxxabi.h - deque - exception + - expected - filesystem - forward_list - fstream @@ -102,6 +103,7 @@ - scoped_allocator - set - shared_mutex + - source_location - span - sstream - stack diff --git a/build/ya.conf.json b/build/ya.conf.json index b85b11a80a..44022d1330 100644 --- a/build/ya.conf.json +++ b/build/ya.conf.json @@ -58,6 +58,55 @@ } } }, + "clang14": { + "executable": { + "c++": [ + "bin", + "clang++" + ], + "c++filt": [ + "bin", + "llvm-cxxfilt" + ], + "cc": [ + "bin", + "clang" + ], + "clang-rename": [ + "bin", + "clang-rename" + ], + "llvm-cov": [ + "bin", + "llvm-cov" + ], + "llvm-gcov": [ + "bin", + "llvm-gcov" + ], + "llvm-nm": [ + "bin", + "llvm-nm" + ], + "llvm-objcopy": [ + "bin", + "llvm-objcopy" + ], + "llvm-profdata": [ + "bin", + "llvm-profdata" + ], + "llvm-strip": [ + "bin", + "llvm-strip" + ], + "llvm-symbolizer": [ + "bin", + "llvm-symbolizer" + ] + }, + "formula": "build/platform/clang/clang14.json" + }, "clang16": { "executable": { "c++": [ @@ -313,6 +362,555 @@ } } }, + "clang14": { + "env": { + "CPATH": [ + "" + ], + "LIBRARY_PATH": [ + "" + ], + "SDKROOT": [ + "" + ] + }, + "params": { + "c_compiler": "$(CLANG)/bin/clang", + "cxx_compiler": "$(CLANG)/bin/clang++", + "gcc_version": "14", + "llvm-symbolizer": "$(CLANG)/bin/llvm-symbolizer", + "match_root": "CLANG", + "objcopy": "$(CLANG)/bin/llvm-objcopy", + "profiles": "$(XCODE_TOOLS_ROOT-sbr:799017771)/Xcode/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles", + "simctl": "$(XCODE_TOOLS_ROOT-sbr:799017771)/Xcode/SystemRoot/PrivateFrameworks/CoreSimulator.framework/Resources/bin/simctl", + "strip": "$(CLANG)/bin/llvm-strip", + "type": "clang", + "use_bundle": true, + "werror_mode": "all" + }, + "platforms": [ + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "x86_64", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "aarch64", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "aarch64", + "os": "LINUX" + }, + "target": { + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "aarch64", + "os": "LINUX" + }, + "target": { + "arch": "aarch64", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "ppc64le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "power9le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "x86_64", + "os": "DARWIN" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "arm64", + "os": "DARWIN" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "i386", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "x86_64", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv7", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "arm64", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "arm64", + "os": "IOSSIM" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv7a", + "os": "YOCTO" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "x86_64", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "aarch64", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "ppc64le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "power9le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "x86_64", + "os": "DARWIN" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "arm64", + "os": "DARWIN" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "i386", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "x86_64", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "armv7", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "arm64", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "arm64", + "os": "IOSSIM" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "x86_64", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "aarch64", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "ppc64le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "power9le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "x86_64", + "os": "DARWIN" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "arm64", + "os": "DARWIN" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "i386", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "x86_64", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "armv7", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "arm64", + "os": "IOS" + } + }, + { + "default": false, + "host": { + "arch": "arm64", + "os": "DARWIN" + }, + "target": { + "arch": "arm64", + "os": "IOSSIM" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv7a", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv7a_cortex_a9", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv7ahf_cortex_a35", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv7ahf_cortex_a53", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv7ahf", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv8a_cortex_a35", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "LINUX" + }, + "target": { + "arch": "armv8a_cortex_a53", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "ppc64le", + "os": "LINUX" + }, + "target": { + "arch": "ppc64le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "arch": "ppc64le", + "os": "LINUX" + }, + "target": { + "arch": "power9le", + "os": "LINUX" + } + }, + { + "default": false, + "host": { + "os": "DARWIN" + }, + "target": { + "arch": "armv7ahf_cortex_a53", + "os": "LINUX" + } + } + ], + "tools": { + "c++": { + "bottle": "clang14", + "executable": "c++" + }, + "c++filt": { + "bottle": "clang14", + "executable": "c++filt" + }, + "cc": { + "bottle": "clang14", + "executable": "cc" + }, + "clang-rename": { + "bottle": "clang14", + "executable": "clang-rename" + }, + "gcov": { + "bottle": "clang14", + "executable": "llvm-gcov" + }, + "llvm-cov": { + "bottle": "clang14", + "executable": "llvm-cov" + }, + "llvm-profdata": { + "bottle": "clang14", + "executable": "llvm-profdata" + }, + "llvm-symbolizer": { + "bottle": "clang14", + "executable": "llvm-symbolizer" + }, + "nm": { + "bottle": "clang14", + "executable": "llvm-nm" + }, + "objcopy": { + "bottle": "clang14", + "executable": "llvm-objcopy" + }, + "strip": { + "bottle": "clang14", + "executable": "llvm-strip" + } + } + }, "clang16": { "env": { "CPATH": [ diff --git a/build/ymake.core.conf b/build/ymake.core.conf index 1ccfa2d48d..c0c2a070f5 100644 --- a/build/ymake.core.conf +++ b/build/ymake.core.conf @@ -9,7 +9,7 @@ FAKEID=628318530716 SANDBOX_FAKEID=${FAKEID}.7600000 -CPP_FAKEID=2023-12-08 +CPP_FAKEID=2024-01-23 GO_FAKEID=11100371 ANDROID_FAKEID=2023-05-17 CLANG_TIDY_FAKEID=2023-06-06 @@ -1248,6 +1248,7 @@ UNITTEST_SEM=$CPP_PROGRAM_SEM \ && add_yunittest NAME $REALPRJNAME TEST_TARGET $REALPRJNAME TEST_ARG --print-before-suite --print-before-test --fork-tests --print-times --show-fails \ && set_yunittest_property TEST $REALPRJNAME PROPERTY LABELS $TEST_SIZE_NAME $FILTER_ONLY_TEST_TAGS \ && add_ytest_requirements $REALPRJNAME $DEFAULT_REQUIREMENTS $TEST_REQUIREMENTS_VALUE \ + && set_yunittest_property_escaped TEST $REALPRJNAME PROPERTY ENVIRONMENT $TEST_ENV_VALUE \ $_TEST_TIMEOUT_SEM # tag:test @@ -1301,6 +1302,7 @@ GTEST_SEM=$CPP_PROGRAM_SEM \ && add_test NAME $REALPRJNAME COMMAND $REALPRJNAME \ && set_property TEST $REALPRJNAME PROPERTY LABELS $TEST_SIZE_NAME $FILTER_ONLY_TEST_TAGS \ && add_test_requirements $REALPRJNAME $DEFAULT_REQUIREMENTS $TEST_REQUIREMENTS_VALUE \ + && set_property_escaped TEST $REALPRJNAME PROPERTY ENVIRONMENT $TEST_ENV_VALUE \ $_TEST_TIMEOUT_SEM # tag:cpp-specific tag:test diff --git a/cmake/common.cmake b/cmake/common.cmake index 0ffe61ad17..f85875ec40 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -296,13 +296,13 @@ function(set_yunittest_property) get_property(SPLIT_FACTOR TARGET ${YUNITTEST_ARGS_TEST} PROPERTY SPLIT_FACTOR) if ((${SPLIT_FACTOR} EQUAL 1) OR (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/run_testpack")) - set_property(TEST ${YUNITTEST_ARGS_TEST} PROPERTY ${YUNITTEST_ARGS_PROPERTY} ${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}) + set_property(TEST ${YUNITTEST_ARGS_TEST} PROPERTY ${YUNITTEST_ARGS_PROPERTY} "${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}") return() endif() math(EXPR LastIdx "${SPLIT_FACTOR} - 1") foreach(Idx RANGE ${LastIdx}) - set_property(TEST ${YUNITTEST_ARGS_TEST}_${Idx} PROPERTY ${YUNITTEST_ARGS_PROPERTY} ${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}) + set_property(TEST ${YUNITTEST_ARGS_TEST}_${Idx} PROPERTY ${YUNITTEST_ARGS_PROPERTY} "${YUNITTEST_ARGS_UNPARSED_ARGUMENTS}") endforeach() endfunction() diff --git a/contrib/go/_std_1.21/src/crypto/internal/boring/notboring.go b/contrib/go/_std_1.21/src/crypto/internal/boring/notboring.go index 1c5e4c742d..e478791217 100644 --- a/contrib/go/_std_1.21/src/crypto/internal/boring/notboring.go +++ b/contrib/go/_std_1.21/src/crypto/internal/boring/notboring.go @@ -50,6 +50,7 @@ func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("boringcrypto: no func NewAESCipher(key []byte) (cipher.Block, error) { panic("boringcrypto: not available") } func NewGCMTLS(cipher.Block) (cipher.AEAD, error) { panic("boringcrypto: not available") } +func NewGCMTLS13(cipher.Block) (cipher.AEAD, error) { panic("boringcrypto: not available") } type PublicKeyECDSA struct{ _ int } type PrivateKeyECDSA struct{ _ int } diff --git a/contrib/go/_std_1.21/src/crypto/rand/rand.go b/contrib/go/_std_1.21/src/crypto/rand/rand.go index 62738e2cb1..d0dcc7cc71 100644 --- a/contrib/go/_std_1.21/src/crypto/rand/rand.go +++ b/contrib/go/_std_1.21/src/crypto/rand/rand.go @@ -15,7 +15,7 @@ import "io" // available, /dev/urandom otherwise. // On OpenBSD and macOS, Reader uses getentropy(2). // On other Unix-like systems, Reader reads from /dev/urandom. -// On Windows systems, Reader uses the RtlGenRandom API. +// On Windows systems, Reader uses the ProcessPrng API. // On JS/Wasm, Reader uses the Web Crypto API. // On WASIP1/Wasm, Reader uses random_get from wasi_snapshot_preview1. var Reader io.Reader diff --git a/contrib/go/_std_1.21/src/crypto/rand/rand_windows.go b/contrib/go/_std_1.21/src/crypto/rand/rand_windows.go index 6c0655c72b..7380f1f0f1 100644 --- a/contrib/go/_std_1.21/src/crypto/rand/rand_windows.go +++ b/contrib/go/_std_1.21/src/crypto/rand/rand_windows.go @@ -15,11 +15,8 @@ func init() { Reader = &rngReader{} } type rngReader struct{} -func (r *rngReader) Read(b []byte) (n int, err error) { - // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at - // most 1<<31-1 bytes at a time so that this works the same on 32-bit - // and 64-bit systems. - if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil { +func (r *rngReader) Read(b []byte) (int, error) { + if err := windows.ProcessPrng(b); err != nil { return 0, err } return len(b), nil diff --git a/contrib/go/_std_1.21/src/crypto/tls/cipher_suites.go b/contrib/go/_std_1.21/src/crypto/tls/cipher_suites.go index 589e8b6faf..fd538da0f7 100644 --- a/contrib/go/_std_1.21/src/crypto/tls/cipher_suites.go +++ b/contrib/go/_std_1.21/src/crypto/tls/cipher_suites.go @@ -532,7 +532,13 @@ func aeadAESGCMTLS13(key, nonceMask []byte) aead { if err != nil { panic(err) } - aead, err := cipher.NewGCM(aes) + var aead cipher.AEAD + if boring.Enabled { + aead, err = boring.NewGCMTLS13(aes) + } else { + boring.Unreachable() + aead, err = cipher.NewGCM(aes) + } if err != nil { panic(err) } diff --git a/contrib/go/_std_1.21/src/crypto/tls/handshake_client.go b/contrib/go/_std_1.21/src/crypto/tls/handshake_client.go index 4649f36dea..e81764a912 100644 --- a/contrib/go/_std_1.21/src/crypto/tls/handshake_client.go +++ b/contrib/go/_std_1.21/src/crypto/tls/handshake_client.go @@ -139,7 +139,9 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) { if len(hello.supportedVersions) == 1 { hello.cipherSuites = nil } - if hasAESGCMHardwareSupport { + if needFIPS() { + hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13FIPS...) + } else if hasAESGCMHardwareSupport { hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...) } else { hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) diff --git a/contrib/go/_std_1.21/src/crypto/tls/handshake_client_tls13.go b/contrib/go/_std_1.21/src/crypto/tls/handshake_client_tls13.go index 2f59f6888c..a84cede1b0 100644 --- a/contrib/go/_std_1.21/src/crypto/tls/handshake_client_tls13.go +++ b/contrib/go/_std_1.21/src/crypto/tls/handshake_client_tls13.go @@ -41,10 +41,6 @@ type clientHandshakeStateTLS13 struct { func (hs *clientHandshakeStateTLS13) handshake() error { c := hs.c - if needFIPS() { - return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode") - } - // The server must not select TLS 1.3 in a renegotiation. See RFC 8446, // sections 4.1.2 and 4.1.3. if c.handshakes > 0 { diff --git a/contrib/go/_std_1.21/src/crypto/tls/handshake_server_tls13.go b/contrib/go/_std_1.21/src/crypto/tls/handshake_server_tls13.go index 07b1a3851e..dd5298b728 100644 --- a/contrib/go/_std_1.21/src/crypto/tls/handshake_server_tls13.go +++ b/contrib/go/_std_1.21/src/crypto/tls/handshake_server_tls13.go @@ -45,10 +45,6 @@ type serverHandshakeStateTLS13 struct { func (hs *serverHandshakeStateTLS13) handshake() error { c := hs.c - if needFIPS() { - return errors.New("tls: internal error: TLS 1.3 reached in FIPS mode") - } - // For an overview of the TLS 1.3 handshake, see RFC 8446, Section 2. if err := hs.processClientHello(); err != nil { return err @@ -163,6 +159,9 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { preferenceList = defaultCipherSuitesTLS13NoAES } + if needFIPS() { + preferenceList = defaultCipherSuitesTLS13FIPS + } for _, suiteID := range preferenceList { hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID) if hs.suite != nil { diff --git a/contrib/go/_std_1.21/src/crypto/tls/notboring.go b/contrib/go/_std_1.21/src/crypto/tls/notboring.go index 7d85b39c59..edccb44d87 100644 --- a/contrib/go/_std_1.21/src/crypto/tls/notboring.go +++ b/contrib/go/_std_1.21/src/crypto/tls/notboring.go @@ -18,3 +18,5 @@ func fipsCurvePreferences(c *Config) []CurveID { panic("fipsCurvePreferences") } func fipsCipherSuites(c *Config) []uint16 { panic("fipsCipherSuites") } var fipsSupportedSignatureAlgorithms []SignatureScheme + +var defaultCipherSuitesTLS13FIPS []uint16 diff --git a/contrib/go/_std_1.21/src/go/types/call.go b/contrib/go/_std_1.21/src/go/types/call.go index 8a3cec7309..f00290a74f 100644 --- a/contrib/go/_std_1.21/src/go/types/call.go +++ b/contrib/go/_std_1.21/src/go/types/call.go @@ -571,6 +571,14 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type for i, arg := range args { // generic arguments cannot have a defined (*Named) type - no need for underlying type below if asig, _ := arg.typ.(*Signature); asig != nil && asig.TypeParams().Len() > 0 { + // The argument type is a generic function signature. This type is + // pointer-identical with (it's copied from) the type of the generic + // function argument and thus the function object. + // Before we change the type (type parameter renaming, below), make + // a clone of it as otherwise we implicitly modify the object's type + // (go.dev/issues/63260). + clone := *asig + asig = &clone // Rename type parameters for cases like f(g, g); this gives each // generic function argument a unique type identity (go.dev/issues/59956). // TODO(gri) Consider only doing this if a function argument appears diff --git a/contrib/go/_std_1.21/src/internal/buildcfg/zbootstrap.go b/contrib/go/_std_1.21/src/internal/buildcfg/zbootstrap.go index f5b4f3486b..b83b3ead43 100644 --- a/contrib/go/_std_1.21/src/internal/buildcfg/zbootstrap.go +++ b/contrib/go/_std_1.21/src/internal/buildcfg/zbootstrap.go @@ -13,6 +13,6 @@ const defaultGOPPC64 = `power8` const defaultGOEXPERIMENT = `` const defaultGO_EXTLINK_ENABLED = `` const defaultGO_LDSO = `` -const version = `go1.21.3` +const version = `go1.21.6` const defaultGOOS = runtime.GOOS const defaultGOARCH = runtime.GOARCH diff --git a/contrib/go/_std_1.21/src/internal/poll/splice_linux.go b/contrib/go/_std_1.21/src/internal/poll/splice_linux.go index 9505c5dcfc..72cca34fe4 100644 --- a/contrib/go/_std_1.21/src/internal/poll/splice_linux.go +++ b/contrib/go/_std_1.21/src/internal/poll/splice_linux.go @@ -13,6 +13,12 @@ import ( ) const ( + // spliceNonblock doesn't make the splice itself necessarily nonblocking + // (because the actual file descriptors that are spliced from/to may block + // unless they have the O_NONBLOCK flag set), but it makes the splice pipe + // operations nonblocking. + spliceNonblock = 0x2 + // maxSpliceSize is the maximum amount of data Splice asks // the kernel to move in a single call to splice(2). // We use 1MB as Splice writes data through a pipe, and 1MB is the default maximum pipe buffer size, @@ -89,7 +95,11 @@ func spliceDrain(pipefd int, sock *FD, max int) (int, error) { return 0, err } for { - n, err := splice(pipefd, sock.Sysfd, max, 0) + // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here, + // because it could return EAGAIN ceaselessly when the write end of the pipe is full, + // but this shouldn't be a concern here, since the pipe buffer must be sufficient for + // this data transmission on the basis of the workflow in Splice. + n, err := splice(pipefd, sock.Sysfd, max, spliceNonblock) if err == syscall.EINTR { continue } @@ -127,7 +137,14 @@ func splicePump(sock *FD, pipefd int, inPipe int) (int, error) { } written := 0 for inPipe > 0 { - n, err := splice(sock.Sysfd, pipefd, inPipe, 0) + // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here, + // because it could return EAGAIN ceaselessly when the read end of the pipe is empty, + // but this shouldn't be a concern here, since the pipe buffer must contain inPipe size of + // data on the basis of the workflow in Splice. + n, err := splice(sock.Sysfd, pipefd, inPipe, spliceNonblock) + if err == syscall.EINTR { + continue + } // Here, the condition n == 0 && err == nil should never be // observed, since Splice controls the write side of the pipe. if n > 0 { diff --git a/contrib/go/_std_1.21/src/internal/safefilepath/path_windows.go b/contrib/go/_std_1.21/src/internal/safefilepath/path_windows.go index 909c150edc..7cfd6ce2ea 100644 --- a/contrib/go/_std_1.21/src/internal/safefilepath/path_windows.go +++ b/contrib/go/_std_1.21/src/internal/safefilepath/path_windows.go @@ -20,15 +20,10 @@ func fromFS(path string) (string, error) { for p := path; p != ""; { // Find the next path element. i := 0 - dot := -1 for i < len(p) && p[i] != '/' { switch p[i] { case 0, '\\', ':': return "", errInvalidPath - case '.': - if dot < 0 { - dot = i - } } i++ } @@ -39,22 +34,8 @@ func fromFS(path string) (string, error) { } else { p = "" } - // Trim the extension and look for a reserved name. - base := part - if dot >= 0 { - base = part[:dot] - } - if isReservedName(base) { - if dot < 0 { - return "", errInvalidPath - } - // The path element is a reserved name with an extension. - // Some Windows versions consider this a reserved name, - // while others do not. Use FullPath to see if the name is - // reserved. - if p, _ := syscall.FullPath(part); len(p) >= 4 && p[:4] == `\\.\` { - return "", errInvalidPath - } + if IsReservedName(part) { + return "", errInvalidPath } } if containsSlash { @@ -70,23 +51,88 @@ func fromFS(path string) (string, error) { return path, nil } -// isReservedName reports if name is a Windows reserved device name. +// IsReservedName reports if name is a Windows reserved device name. // It does not detect names with an extension, which are also reserved on some Windows versions. // // For details, search for PRN in // https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file. -func isReservedName(name string) bool { - if 3 <= len(name) && len(name) <= 4 { +func IsReservedName(name string) bool { + // Device names can have arbitrary trailing characters following a dot or colon. + base := name + for i := 0; i < len(base); i++ { + switch base[i] { + case ':', '.': + base = base[:i] + } + } + // Trailing spaces in the last path element are ignored. + for len(base) > 0 && base[len(base)-1] == ' ' { + base = base[:len(base)-1] + } + if !isReservedBaseName(base) { + return false + } + if len(base) == len(name) { + return true + } + // The path element is a reserved name with an extension. + // Some Windows versions consider this a reserved name, + // while others do not. Use FullPath to see if the name is + // reserved. + if p, _ := syscall.FullPath(name); len(p) >= 4 && p[:4] == `\\.\` { + return true + } + return false +} + +func isReservedBaseName(name string) bool { + if len(name) == 3 { switch string([]byte{toUpper(name[0]), toUpper(name[1]), toUpper(name[2])}) { case "CON", "PRN", "AUX", "NUL": - return len(name) == 3 + return true + } + } + if len(name) >= 4 { + switch string([]byte{toUpper(name[0]), toUpper(name[1]), toUpper(name[2])}) { case "COM", "LPT": - return len(name) == 4 && '1' <= name[3] && name[3] <= '9' + if len(name) == 4 && '1' <= name[3] && name[3] <= '9' { + return true + } + // Superscript ¹, ², and ³ are considered numbers as well. + switch name[3:] { + case "\u00b2", "\u00b3", "\u00b9": + return true + } + return false } } + + // Passing CONIN$ or CONOUT$ to CreateFile opens a console handle. + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#consoles + // + // While CONIN$ and CONOUT$ aren't documented as being files, + // they behave the same as CON. For example, ./CONIN$ also opens the console input. + if len(name) == 6 && name[5] == '$' && equalFold(name, "CONIN$") { + return true + } + if len(name) == 7 && name[6] == '$' && equalFold(name, "CONOUT$") { + return true + } return false } +func equalFold(a, b string) bool { + if len(a) != len(b) { + return false + } + for i := 0; i < len(a); i++ { + if toUpper(a[i]) != toUpper(b[i]) { + return false + } + } + return true +} + func toUpper(c byte) byte { if 'a' <= c && c <= 'z' { return c - ('a' - 'A') diff --git a/contrib/go/_std_1.21/src/internal/syscall/windows/reparse_windows.go b/contrib/go/_std_1.21/src/internal/syscall/windows/reparse_windows.go index 6e111392f0..6caf47e867 100644 --- a/contrib/go/_std_1.21/src/internal/syscall/windows/reparse_windows.go +++ b/contrib/go/_std_1.21/src/internal/syscall/windows/reparse_windows.go @@ -12,6 +12,7 @@ import ( const ( FSCTL_SET_REPARSE_POINT = 0x000900A4 IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 + IO_REPARSE_TAG_DEDUP = 0x80000013 SYMLINK_FLAG_RELATIVE = 1 ) diff --git a/contrib/go/_std_1.21/src/internal/syscall/windows/syscall_windows.go b/contrib/go/_std_1.21/src/internal/syscall/windows/syscall_windows.go index 892b878d16..e9390b07cd 100644 --- a/contrib/go/_std_1.21/src/internal/syscall/windows/syscall_windows.go +++ b/contrib/go/_std_1.21/src/internal/syscall/windows/syscall_windows.go @@ -373,7 +373,7 @@ func ErrorLoadingGetTempPath2() error { //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW -//sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036 +//sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng //sys RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) = kernel32.RtlLookupFunctionEntry //sys RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) = kernel32.RtlVirtualUnwind diff --git a/contrib/go/_std_1.21/src/internal/syscall/windows/zsyscall_windows.go b/contrib/go/_std_1.21/src/internal/syscall/windows/zsyscall_windows.go index a5c246b773..26ec290e02 100644 --- a/contrib/go/_std_1.21/src/internal/syscall/windows/zsyscall_windows.go +++ b/contrib/go/_std_1.21/src/internal/syscall/windows/zsyscall_windows.go @@ -37,13 +37,14 @@ func errnoErr(e syscall.Errno) error { } var ( - modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) - modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll")) - modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) - modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) - modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll")) - moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll")) - modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll")) + modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) + modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll")) + modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll")) + modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) + modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) + modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll")) + moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll")) + modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll")) procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") @@ -52,7 +53,7 @@ var ( procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") - procSystemFunction036 = modadvapi32.NewProc("SystemFunction036") + procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procCreateEventW = modkernel32.NewProc("CreateEventW") procGetACP = modkernel32.NewProc("GetACP") @@ -148,12 +149,12 @@ func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32 return } -func RtlGenRandom(buf []byte) (err error) { +func ProcessPrng(buf []byte) (err error) { var _p0 *byte if len(buf) > 0 { _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall(procSystemFunction036.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0) + r1, _, e1 := syscall.Syscall(procProcessPrng.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0) if r1 == 0 { err = errnoErr(e1) } diff --git a/contrib/go/_std_1.21/src/net/http/h2_bundle.go b/contrib/go/_std_1.21/src/net/http/h2_bundle.go index 9cd6a3490f..dd59e1f4f2 100644 --- a/contrib/go/_std_1.21/src/net/http/h2_bundle.go +++ b/contrib/go/_std_1.21/src/net/http/h2_bundle.go @@ -7012,6 +7012,7 @@ func (sc *http2serverConn) startPush(msg *http2startPushRequest) { panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err)) } + sc.curHandlers++ go sc.runHandler(rw, req, sc.handler.ServeHTTP) return promisedID, nil } diff --git a/contrib/go/_std_1.21/src/net/http/internal/chunked.go b/contrib/go/_std_1.21/src/net/http/internal/chunked.go index 5a174415dc..aad8e5aa09 100644 --- a/contrib/go/_std_1.21/src/net/http/internal/chunked.go +++ b/contrib/go/_std_1.21/src/net/http/internal/chunked.go @@ -39,7 +39,8 @@ type chunkedReader struct { n uint64 // unread bytes in chunk err error buf [2]byte - checkEnd bool // whether need to check for \r\n chunk footer + checkEnd bool // whether need to check for \r\n chunk footer + excess int64 // "excessive" chunk overhead, for malicious sender detection } func (cr *chunkedReader) beginChunk() { @@ -49,10 +50,36 @@ func (cr *chunkedReader) beginChunk() { if cr.err != nil { return } + cr.excess += int64(len(line)) + 2 // header, plus \r\n after the chunk data + line = trimTrailingWhitespace(line) + line, cr.err = removeChunkExtension(line) + if cr.err != nil { + return + } cr.n, cr.err = parseHexUint(line) if cr.err != nil { return } + // A sender who sends one byte per chunk will send 5 bytes of overhead + // for every byte of data. ("1\r\nX\r\n" to send "X".) + // We want to allow this, since streaming a byte at a time can be legitimate. + // + // A sender can use chunk extensions to add arbitrary amounts of additional + // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".) + // We don't want to disallow extensions (although we discard them), + // but we also don't want to allow a sender to reduce the signal/noise ratio + // arbitrarily. + // + // We track the amount of excess overhead read, + // and produce an error if it grows too large. + // + // Currently, we say that we're willing to accept 16 bytes of overhead per chunk, + // plus twice the amount of real data in the chunk. + cr.excess -= 16 + (2 * int64(cr.n)) + cr.excess = max(cr.excess, 0) + if cr.excess > 16*1024 { + cr.err = errors.New("chunked encoding contains too much non-data") + } if cr.n == 0 { cr.err = io.EOF } @@ -140,11 +167,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) { if len(p) >= maxLineLength { return nil, ErrLineTooLong } - p = trimTrailingWhitespace(p) - p, err = removeChunkExtension(p) - if err != nil { - return nil, err - } return p, nil } diff --git a/contrib/go/_std_1.21/src/os/rlimit.go b/contrib/go/_std_1.21/src/os/rlimit.go deleted file mode 100644 index e0d0ef9b62..0000000000 --- a/contrib/go/_std_1.21/src/os/rlimit.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build unix - -package os - -import "syscall" - -// Some systems set an artificially low soft limit on open file count, for compatibility -// with code that uses select and its hard-coded maximum file descriptor -// (limited by the size of fd_set). -// -// Go does not use select, so it should not be subject to these limits. -// On some systems the limit is 256, which is very easy to run into, -// even in simple programs like gofmt when they parallelize walking -// a file tree. -// -// After a long discussion on go.dev/issue/46279, we decided the -// best approach was for Go to raise the limit unconditionally for itself, -// and then leave old software to set the limit back as needed. -// Code that really wants Go to leave the limit alone can set the hard limit, -// which Go of course has no choice but to respect. -func init() { - var lim syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err == nil && lim.Cur != lim.Max { - lim.Cur = lim.Max - adjustFileLimit(&lim) - syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim) - } -} diff --git a/contrib/go/_std_1.21/src/os/rlimit_darwin.go b/contrib/go/_std_1.21/src/os/rlimit_darwin.go deleted file mode 100644 index b28982a83a..0000000000 --- a/contrib/go/_std_1.21/src/os/rlimit_darwin.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin - -package os - -import "syscall" - -// adjustFileLimit adds per-OS limitations on the Rlimit used for RLIMIT_NOFILE. See rlimit.go. -func adjustFileLimit(lim *syscall.Rlimit) { - // On older macOS, setrlimit(RLIMIT_NOFILE, lim) with lim.Cur = infinity fails. - // Set to the value of kern.maxfilesperproc instead. - n, err := syscall.SysctlUint32("kern.maxfilesperproc") - if err != nil { - return - } - if lim.Cur > uint64(n) { - lim.Cur = uint64(n) - } -} diff --git a/contrib/go/_std_1.21/src/os/rlimit_stub.go b/contrib/go/_std_1.21/src/os/rlimit_stub.go deleted file mode 100644 index cbe28400c5..0000000000 --- a/contrib/go/_std_1.21/src/os/rlimit_stub.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build aix || dragonfly || freebsd || linux || netbsd || openbsd || solaris - -package os - -import "syscall" - -// adjustFileLimit adds per-OS limitations on the Rlimit used for RLIMIT_NOFILE. See rlimit.go. -func adjustFileLimit(lim *syscall.Rlimit) {} diff --git a/contrib/go/_std_1.21/src/os/types_windows.go b/contrib/go/_std_1.21/src/os/types_windows.go index 9a3d508783..effb0148df 100644 --- a/contrib/go/_std_1.21/src/os/types_windows.go +++ b/contrib/go/_std_1.21/src/os/types_windows.go @@ -141,7 +141,23 @@ func (fs *fileStat) Mode() (m FileMode) { m |= ModeDevice | ModeCharDevice } if fs.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 && m&ModeType == 0 { - m |= ModeIrregular + if fs.ReparseTag == windows.IO_REPARSE_TAG_DEDUP { + // If the Data Deduplication service is enabled on Windows Server, its + // Optimization job may convert regular files to IO_REPARSE_TAG_DEDUP + // whenever that job runs. + // + // However, DEDUP reparse points remain similar in most respects to + // regular files: they continue to support random-access reads and writes + // of persistent data, and they shouldn't add unexpected latency or + // unavailability in the way that a network filesystem might. + // + // Go programs may use ModeIrregular to filter out unusual files (such as + // raw device files on Linux, POSIX FIFO special files, and so on), so + // to avoid files changing unpredictably from regular to irregular we will + // consider DEDUP files to be close enough to regular to treat as such. + } else { + m |= ModeIrregular + } } return m } diff --git a/contrib/go/_std_1.21/src/os/ya.make b/contrib/go/_std_1.21/src/os/ya.make index dc812bdd07..8c4c417f82 100644 --- a/contrib/go/_std_1.21/src/os/ya.make +++ b/contrib/go/_std_1.21/src/os/ya.make @@ -29,8 +29,6 @@ ELSEIF (OS_LINUX AND ARCH_X86_64) rawconn.go readfrom_linux.go removeall_at.go - rlimit.go - rlimit_stub.go stat.go stat_linux.go stat_unix.go @@ -71,8 +69,6 @@ ELSEIF (OS_LINUX AND ARCH_ARM64) rawconn.go readfrom_linux.go removeall_at.go - rlimit.go - rlimit_stub.go stat.go stat_linux.go stat_unix.go @@ -113,8 +109,6 @@ ELSEIF (OS_LINUX AND ARCH_AARCH64) rawconn.go readfrom_linux.go removeall_at.go - rlimit.go - rlimit_stub.go stat.go stat_linux.go stat_unix.go @@ -154,8 +148,6 @@ ELSEIF (OS_DARWIN AND ARCH_X86_64) rawconn.go readfrom_stub.go removeall_at.go - rlimit.go - rlimit_darwin.go stat.go stat_darwin.go stat_unix.go @@ -195,8 +187,6 @@ ELSEIF (OS_DARWIN AND ARCH_ARM64) rawconn.go readfrom_stub.go removeall_at.go - rlimit.go - rlimit_darwin.go stat.go stat_darwin.go stat_unix.go @@ -236,8 +226,6 @@ ELSEIF (OS_DARWIN AND ARCH_AARCH64) rawconn.go readfrom_stub.go removeall_at.go - rlimit.go - rlimit_darwin.go stat.go stat_darwin.go stat_unix.go diff --git a/contrib/go/_std_1.21/src/path/filepath/path.go b/contrib/go/_std_1.21/src/path/filepath/path.go index ca1d8b3116..3bf3ff6b89 100644 --- a/contrib/go/_std_1.21/src/path/filepath/path.go +++ b/contrib/go/_std_1.21/src/path/filepath/path.go @@ -15,7 +15,6 @@ import ( "errors" "io/fs" "os" - "runtime" "sort" "strings" ) @@ -167,21 +166,7 @@ func Clean(path string) string { out.append('.') } - if runtime.GOOS == "windows" && out.volLen == 0 && out.buf != nil { - // If a ':' appears in the path element at the start of a Windows path, - // insert a .\ at the beginning to avoid converting relative paths - // like a/../c: into c:. - for _, c := range out.buf { - if os.IsPathSeparator(c) { - break - } - if c == ':' { - out.prepend('.', Separator) - break - } - } - } - + postClean(&out) // avoid creating absolute paths on Windows return FromSlash(out.string()) } diff --git a/contrib/go/_std_1.21/src/path/filepath/path_nonwindows.go b/contrib/go/_std_1.21/src/path/filepath/path_nonwindows.go new file mode 100644 index 0000000000..db69f0228b --- /dev/null +++ b/contrib/go/_std_1.21/src/path/filepath/path_nonwindows.go @@ -0,0 +1,9 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !windows + +package filepath + +func postClean(out *lazybuf) {} diff --git a/contrib/go/_std_1.21/src/path/filepath/path_windows.go b/contrib/go/_std_1.21/src/path/filepath/path_windows.go index 4dca9e0f55..eacab0e5ce 100644 --- a/contrib/go/_std_1.21/src/path/filepath/path_windows.go +++ b/contrib/go/_std_1.21/src/path/filepath/path_windows.go @@ -5,6 +5,8 @@ package filepath import ( + "internal/safefilepath" + "os" "strings" "syscall" ) @@ -20,34 +22,6 @@ func toUpper(c byte) byte { return c } -// isReservedName reports if name is a Windows reserved device name or a console handle. -// It does not detect names with an extension, which are also reserved on some Windows versions. -// -// For details, search for PRN in -// https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file. -func isReservedName(name string) bool { - if 3 <= len(name) && len(name) <= 4 { - switch string([]byte{toUpper(name[0]), toUpper(name[1]), toUpper(name[2])}) { - case "CON", "PRN", "AUX", "NUL": - return len(name) == 3 - case "COM", "LPT": - return len(name) == 4 && '1' <= name[3] && name[3] <= '9' - } - } - // Passing CONIN$ or CONOUT$ to CreateFile opens a console handle. - // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#consoles - // - // While CONIN$ and CONOUT$ aren't documented as being files, - // they behave the same as CON. For example, ./CONIN$ also opens the console input. - if len(name) == 6 && name[5] == '$' && strings.EqualFold(name, "CONIN$") { - return true - } - if len(name) == 7 && name[6] == '$' && strings.EqualFold(name, "CONOUT$") { - return true - } - return false -} - func isLocal(path string) bool { if path == "" { return false @@ -68,25 +42,8 @@ func isLocal(path string) bool { if part == "." || part == ".." { hasDots = true } - // Trim the extension and look for a reserved name. - base, _, hasExt := strings.Cut(part, ".") - if isReservedName(base) { - if !hasExt { - return false - } - // The path element is a reserved name with an extension. Some Windows - // versions consider this a reserved name, while others do not. Use - // FullPath to see if the name is reserved. - // - // FullPath will convert references to reserved device names to their - // canonical form: \\.\${DEVICE_NAME} - // - // FullPath does not perform this conversion for paths which contain - // a reserved device name anywhere other than in the last element, - // so check the part rather than the full path. - if p, _ := syscall.FullPath(part); len(p) >= 4 && p[:4] == `\\.\` { - return false - } + if safefilepath.IsReservedName(part) { + return false } } if hasDots { @@ -118,40 +75,93 @@ func IsAbs(path string) (b bool) { // volumeNameLen returns length of the leading volume name on Windows. // It returns 0 elsewhere. // -// See: https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats +// See: +// https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats +// https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html func volumeNameLen(path string) int { - if len(path) < 2 { - return 0 - } - // with drive letter - c := path[0] - if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { + switch { + case len(path) >= 2 && path[1] == ':': + // Path starts with a drive letter. + // + // Not all Windows functions necessarily enforce the requirement that + // drive letters be in the set A-Z, and we don't try to here. + // + // We don't handle the case of a path starting with a non-ASCII character, + // in which case the "drive letter" might be multiple bytes long. return 2 - } - // UNC and DOS device paths start with two slashes. - if !isSlash(path[0]) || !isSlash(path[1]) { + + case len(path) == 0 || !isSlash(path[0]): + // Path does not have a volume component. return 0 + + case pathHasPrefixFold(path, `\\.\UNC`): + // We're going to treat the UNC host and share as part of the volume + // prefix for historical reasons, but this isn't really principled; + // Windows's own GetFullPathName will happily remove the first + // component of the path in this space, converting + // \\.\unc\a\b\..\c into \\.\unc\a\c. + return uncLen(path, len(`\\.\UNC\`)) + + case pathHasPrefixFold(path, `\\.`) || + pathHasPrefixFold(path, `\\?`) || pathHasPrefixFold(path, `\??`): + // Path starts with \\.\, and is a Local Device path; or + // path starts with \\?\ or \??\ and is a Root Local Device path. + // + // We treat the next component after the \\.\ prefix as + // part of the volume name, which means Clean(`\\?\c:\`) + // won't remove the trailing \. (See #64028.) + if len(path) == 3 { + return 3 // exactly \\. + } + _, rest, ok := cutPath(path[4:]) + if !ok { + return len(path) + } + return len(path) - len(rest) - 1 + + case len(path) >= 2 && isSlash(path[1]): + // Path starts with \\, and is a UNC path. + return uncLen(path, 2) } - rest := path[2:] - p1, rest, _ := cutPath(rest) - p2, rest, ok := cutPath(rest) - if !ok { - return len(path) + return 0 +} + +// pathHasPrefixFold tests whether the path s begins with prefix, +// ignoring case and treating all path separators as equivalent. +// If s is longer than prefix, then s[len(prefix)] must be a path separator. +func pathHasPrefixFold(s, prefix string) bool { + if len(s) < len(prefix) { + return false } - if p1 != "." && p1 != "?" { - // This is a UNC path: \\${HOST}\${SHARE}\ - return len(path) - len(rest) - 1 + for i := 0; i < len(prefix); i++ { + if isSlash(prefix[i]) { + if !isSlash(s[i]) { + return false + } + } else if toUpper(prefix[i]) != toUpper(s[i]) { + return false + } } - // This is a DOS device path. - if len(p2) == 3 && toUpper(p2[0]) == 'U' && toUpper(p2[1]) == 'N' && toUpper(p2[2]) == 'C' { - // This is a DOS device path that links to a UNC: \\.\UNC\${HOST}\${SHARE}\ - _, rest, _ = cutPath(rest) // host - _, rest, ok = cutPath(rest) // share - if !ok { - return len(path) + if len(s) > len(prefix) && !isSlash(s[len(prefix)]) { + return false + } + return true +} + +// uncLen returns the length of the volume prefix of a UNC path. +// prefixLen is the prefix prior to the start of the UNC host; +// for example, for "//host/share", the prefixLen is len("//")==2. +func uncLen(path string, prefixLen int) int { + count := 0 + for i := prefixLen; i < len(path); i++ { + if isSlash(path[i]) { + count++ + if count == 2 { + return i + } } } - return len(path) - len(rest) - 1 + return len(path) } // cutPath slices path around the first path separator. @@ -238,6 +248,12 @@ func join(elem []string) string { for len(e) > 0 && isSlash(e[0]) { e = e[1:] } + // If the path is \ and the next path element is ??, + // add an extra .\ to create \.\?? rather than \??\ + // (a Root Local Device path). + if b.Len() == 1 && pathHasPrefixFold(e, "??") { + b.WriteString(`.\`) + } case lastChar == ':': // If the path ends in a colon, keep the path relative to the current directory // on a drive and don't add a separator. Preserve leading slashes in the next @@ -304,3 +320,29 @@ func isUNC(path string) bool { func sameWord(a, b string) bool { return strings.EqualFold(a, b) } + +// postClean adjusts the results of Clean to avoid turning a relative path +// into an absolute or rooted one. +func postClean(out *lazybuf) { + if out.volLen != 0 || out.buf == nil { + return + } + // If a ':' appears in the path element at the start of a path, + // insert a .\ at the beginning to avoid converting relative paths + // like a/../c: into c:. + for _, c := range out.buf { + if os.IsPathSeparator(c) { + break + } + if c == ':' { + out.prepend('.', Separator) + return + } + } + // If a path begins with \??\, insert a \. at the beginning + // to avoid converting paths like \a\..\??\c:\x into \??\c:\x + // (equivalent to c:\x). + if len(out.buf) >= 3 && os.IsPathSeparator(out.buf[0]) && out.buf[1] == '?' && out.buf[2] == '?' { + out.prepend(Separator, '.') + } +} diff --git a/contrib/go/_std_1.21/src/path/filepath/ya.make b/contrib/go/_std_1.21/src/path/filepath/ya.make index 4b6a0333a7..9d04957bac 100644 --- a/contrib/go/_std_1.21/src/path/filepath/ya.make +++ b/contrib/go/_std_1.21/src/path/filepath/ya.make @@ -6,6 +6,7 @@ ELSEIF (OS_LINUX AND ARCH_X86_64) SRCS( match.go path.go + path_nonwindows.go path_unix.go symlink.go symlink_unix.go @@ -14,6 +15,7 @@ ELSEIF (OS_LINUX AND ARCH_ARM64) SRCS( match.go path.go + path_nonwindows.go path_unix.go symlink.go symlink_unix.go @@ -22,6 +24,7 @@ ELSEIF (OS_LINUX AND ARCH_AARCH64) SRCS( match.go path.go + path_nonwindows.go path_unix.go symlink.go symlink_unix.go @@ -30,6 +33,7 @@ ELSEIF (OS_DARWIN AND ARCH_X86_64) SRCS( match.go path.go + path_nonwindows.go path_unix.go symlink.go symlink_unix.go @@ -38,6 +42,7 @@ ELSEIF (OS_DARWIN AND ARCH_ARM64) SRCS( match.go path.go + path_nonwindows.go path_unix.go symlink.go symlink_unix.go @@ -46,6 +51,7 @@ ELSEIF (OS_DARWIN AND ARCH_AARCH64) SRCS( match.go path.go + path_nonwindows.go path_unix.go symlink.go symlink_unix.go diff --git a/contrib/go/_std_1.21/src/runtime/cgo/asm_amd64.s b/contrib/go/_std_1.21/src/runtime/cgo/asm_amd64.s index f254622f23..e319094a45 100644 --- a/contrib/go/_std_1.21/src/runtime/cgo/asm_amd64.s +++ b/contrib/go/_std_1.21/src/runtime/cgo/asm_amd64.s @@ -7,12 +7,17 @@ // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVQ _crosscall2_ptr(SB), AX - MOVQ $crosscall2(SB), BX + MOVQ $crosscall2_trampoline<>(SB), BX MOVQ BX, (AX) RET +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) + // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) // Saves C callee-saved registers and calls cgocallback with three arguments. diff --git a/contrib/go/_std_1.21/src/runtime/cgo/asm_arm64.s b/contrib/go/_std_1.21/src/runtime/cgo/asm_arm64.s index ce8909b492..5492dc142c 100644 --- a/contrib/go/_std_1.21/src/runtime/cgo/asm_arm64.s +++ b/contrib/go/_std_1.21/src/runtime/cgo/asm_arm64.s @@ -7,12 +7,17 @@ // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 +// Use a local trampoline, to avoid taking the address of a dynamically exported +// function. TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVD _crosscall2_ptr(SB), R1 - MOVD $crosscall2(SB), R2 + MOVD $crosscall2_trampoline<>(SB), R2 MOVD R2, (R1) RET +TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 + JMP crosscall2(SB) + // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) // Saves C callee-saved registers and calls cgocallback with three arguments. diff --git a/contrib/go/_std_1.21/src/runtime/extern.go b/contrib/go/_std_1.21/src/runtime/extern.go index 26dcf0bd52..de4a0ca2da 100644 --- a/contrib/go/_std_1.21/src/runtime/extern.go +++ b/contrib/go/_std_1.21/src/runtime/extern.go @@ -55,6 +55,13 @@ It is a comma-separated list of name=val pairs setting these named variables: cgocheck mode can be enabled using GOEXPERIMENT (which requires a rebuild), see https://pkg.go.dev/internal/goexperiment for details. + disablethp: setting disablethp=1 on Linux disables transparent huge pages for the heap. + It has no effect on other platforms. disablethp is meant for compatibility with versions + of Go before 1.21, which stopped working around a Linux kernel default that can result + in significant memory overuse. See https://go.dev/issue/64332. This setting will be + removed in a future release, so operators should tweak their Linux configuration to suit + their needs before then. See https://go.dev/doc/gc-guide#Linux_transparent_huge_pages. + dontfreezetheworld: by default, the start of a fatal panic or throw "freezes the world", preempting all threads to stop all running goroutines, which makes it possible to traceback all goroutines, and diff --git a/contrib/go/_std_1.21/src/runtime/malloc.go b/contrib/go/_std_1.21/src/runtime/malloc.go index 44479cc2be..b2026ad0dc 100644 --- a/contrib/go/_std_1.21/src/runtime/malloc.go +++ b/contrib/go/_std_1.21/src/runtime/malloc.go @@ -853,6 +853,10 @@ retry: // // The heap lock must not be held over this operation, since it will briefly acquire // the heap lock. +// +// Must be called on the system stack because it acquires the heap lock. +// +//go:systemstack func (h *mheap) enableMetadataHugePages() { // Enable huge pages for page structure. h.pages.enableChunkHugePages() diff --git a/contrib/go/_std_1.21/src/runtime/map.go b/contrib/go/_std_1.21/src/runtime/map.go index 6b85681447..22aeb86847 100644 --- a/contrib/go/_std_1.21/src/runtime/map.go +++ b/contrib/go/_std_1.21/src/runtime/map.go @@ -1481,12 +1481,24 @@ func moveToBmap(t *maptype, h *hmap, dst *bmap, pos int, src *bmap) (*bmap, int) dst.tophash[pos] = src.tophash[i] if t.IndirectKey() { - *(*unsafe.Pointer)(dstK) = *(*unsafe.Pointer)(srcK) + srcK = *(*unsafe.Pointer)(srcK) + if t.NeedKeyUpdate() { + kStore := newobject(t.Key) + typedmemmove(t.Key, kStore, srcK) + srcK = kStore + } + // Note: if NeedKeyUpdate is false, then the memory + // used to store the key is immutable, so we can share + // it between the original map and its clone. + *(*unsafe.Pointer)(dstK) = srcK } else { typedmemmove(t.Key, dstK, srcK) } if t.IndirectElem() { - *(*unsafe.Pointer)(dstEle) = *(*unsafe.Pointer)(srcEle) + srcEle = *(*unsafe.Pointer)(srcEle) + eStore := newobject(t.Elem) + typedmemmove(t.Elem, eStore, srcEle) + *(*unsafe.Pointer)(dstEle) = eStore } else { typedmemmove(t.Elem, dstEle, srcEle) } @@ -1510,14 +1522,14 @@ func mapclone2(t *maptype, src *hmap) *hmap { fatal("concurrent map clone and map write") } - if src.B == 0 { + if src.B == 0 && !(t.IndirectKey() && t.NeedKeyUpdate()) && !t.IndirectElem() { + // Quick copy for small maps. dst.buckets = newobject(t.Bucket) dst.count = src.count typedmemmove(t.Bucket, dst.buckets, src.buckets) return dst } - //src.B != 0 if dst.B == 0 { dst.buckets = newobject(t.Bucket) } @@ -1565,6 +1577,8 @@ func mapclone2(t *maptype, src *hmap) *hmap { continue } + // oldB < dst.B, so a single source bucket may go to multiple destination buckets. + // Process entries one at a time. for srcBmap != nil { // move from oldBlucket to new bucket for i := uintptr(0); i < bucketCnt; i++ { diff --git a/contrib/go/_std_1.21/src/runtime/mem_linux.go b/contrib/go/_std_1.21/src/runtime/mem_linux.go index c9823d3011..d63c38c209 100644 --- a/contrib/go/_std_1.21/src/runtime/mem_linux.go +++ b/contrib/go/_std_1.21/src/runtime/mem_linux.go @@ -170,4 +170,12 @@ func sysMapOS(v unsafe.Pointer, n uintptr) { print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n") throw("runtime: cannot map pages in arena address space") } + + // Disable huge pages if the GODEBUG for it is set. + // + // Note that there are a few sysHugePage calls that can override this, but + // they're all for GC metadata. + if debug.disablethp != 0 { + sysNoHugePageOS(v, n) + } } diff --git a/contrib/go/_std_1.21/src/runtime/mgc.go b/contrib/go/_std_1.21/src/runtime/mgc.go index de5ae0ae00..a12dbfe9df 100644 --- a/contrib/go/_std_1.21/src/runtime/mgc.go +++ b/contrib/go/_std_1.21/src/runtime/mgc.go @@ -1186,7 +1186,9 @@ func gcMarkTermination() { // Enable huge pages on some metadata if we cross a heap threshold. if gcController.heapGoal() > minHeapForMetadataHugePages { - mheap_.enableMetadataHugePages() + systemstack(func() { + mheap_.enableMetadataHugePages() + }) } semrelease(&worldsema) diff --git a/contrib/go/_std_1.21/src/runtime/mgcscavenge.go b/contrib/go/_std_1.21/src/runtime/mgcscavenge.go index 4c6d6be4f0..659ca8df2e 100644 --- a/contrib/go/_std_1.21/src/runtime/mgcscavenge.go +++ b/contrib/go/_std_1.21/src/runtime/mgcscavenge.go @@ -1145,21 +1145,11 @@ func (s *scavengeIndex) alloc(ci chunkIdx, npages uint) { // Mark that we're considering this chunk as backed by huge pages. sc.setHugePage() - // Collapse dense chunks into huge pages and mark that - // we did that, but only if we're not allocating to - // use the entire chunk. If we're allocating an entire chunk, - // this is likely part of a much bigger allocation. For - // instance, if the caller is allocating a 1 GiB slice of bytes, we - // don't want to go and manually collapse all those pages; we want - // them to be demand-paged. If the caller is actually going to use - // all that memory, it'll naturally get backed by huge pages later. - // - // This also avoids having sysHugePageCollapse fail. On Linux, - // the call requires that some part of the huge page being collapsed - // is already paged in. - if !s.test && npages < pallocChunkPages { - sysHugePageCollapse(unsafe.Pointer(chunkBase(ci)), pallocChunkBytes) - } + // TODO(mknyszek): Consider eagerly backing memory with huge pages + // here. In the past we've attempted to use sysHugePageCollapse + // (which uses MADV_COLLAPSE on Linux, and is unsupported elswhere) + // for this purpose, but that caused performance issues in production + // environments. } s.chunks[ci].store(sc) } diff --git a/contrib/go/_std_1.21/src/runtime/mpagealloc.go b/contrib/go/_std_1.21/src/runtime/mpagealloc.go index 3e789ab85c..2861fa93eb 100644 --- a/contrib/go/_std_1.21/src/runtime/mpagealloc.go +++ b/contrib/go/_std_1.21/src/runtime/mpagealloc.go @@ -437,6 +437,10 @@ func (p *pageAlloc) grow(base, size uintptr) { // // The heap lock must not be held over this operation, since it will briefly acquire // the heap lock. +// +// Must be called on the system stack because it acquires the heap lock. +// +//go:systemstack func (p *pageAlloc) enableChunkHugePages() { // Grab the heap lock to turn on huge pages for new chunks and clone the current // heap address space ranges. diff --git a/contrib/go/_std_1.21/src/runtime/mstats.go b/contrib/go/_std_1.21/src/runtime/mstats.go index 9cdc565137..308bed67d7 100644 --- a/contrib/go/_std_1.21/src/runtime/mstats.go +++ b/contrib/go/_std_1.21/src/runtime/mstats.go @@ -367,6 +367,11 @@ func ReadMemStats(m *MemStats) { startTheWorld() } +// doubleCheckReadMemStats controls a double-check mode for ReadMemStats that +// ensures consistency between the values that ReadMemStats is using and the +// runtime-internal stats. +var doubleCheckReadMemStats = false + // readmemstats_m populates stats for internal runtime values. // // The world must be stopped. @@ -441,56 +446,65 @@ func readmemstats_m(stats *MemStats) { heapGoal := gcController.heapGoal() - // The world is stopped, so the consistent stats (after aggregation) - // should be identical to some combination of memstats. In particular: - // - // * memstats.heapInUse == inHeap - // * memstats.heapReleased == released - // * memstats.heapInUse + memstats.heapFree == committed - inStacks - inWorkBufs - inPtrScalarBits - // * memstats.totalAlloc == totalAlloc - // * memstats.totalFree == totalFree - // - // Check if that's actually true. - // - // TODO(mknyszek): Maybe don't throw here. It would be bad if a - // bug in otherwise benign accounting caused the whole application - // to crash. - if gcController.heapInUse.load() != uint64(consStats.inHeap) { - print("runtime: heapInUse=", gcController.heapInUse.load(), "\n") - print("runtime: consistent value=", consStats.inHeap, "\n") - throw("heapInUse and consistent stats are not equal") - } - if gcController.heapReleased.load() != uint64(consStats.released) { - print("runtime: heapReleased=", gcController.heapReleased.load(), "\n") - print("runtime: consistent value=", consStats.released, "\n") - throw("heapReleased and consistent stats are not equal") - } - heapRetained := gcController.heapInUse.load() + gcController.heapFree.load() - consRetained := uint64(consStats.committed - consStats.inStacks - consStats.inWorkBufs - consStats.inPtrScalarBits) - if heapRetained != consRetained { - print("runtime: global value=", heapRetained, "\n") - print("runtime: consistent value=", consRetained, "\n") - throw("measures of the retained heap are not equal") - } - if gcController.totalAlloc.Load() != totalAlloc { - print("runtime: totalAlloc=", gcController.totalAlloc.Load(), "\n") - print("runtime: consistent value=", totalAlloc, "\n") - throw("totalAlloc and consistent stats are not equal") - } - if gcController.totalFree.Load() != totalFree { - print("runtime: totalFree=", gcController.totalFree.Load(), "\n") - print("runtime: consistent value=", totalFree, "\n") - throw("totalFree and consistent stats are not equal") - } - // Also check that mappedReady lines up with totalMapped - released. - // This isn't really the same type of "make sure consistent stats line up" situation, - // but this is an opportune time to check. - if gcController.mappedReady.Load() != totalMapped-uint64(consStats.released) { - print("runtime: mappedReady=", gcController.mappedReady.Load(), "\n") - print("runtime: totalMapped=", totalMapped, "\n") - print("runtime: released=", uint64(consStats.released), "\n") - print("runtime: totalMapped-released=", totalMapped-uint64(consStats.released), "\n") - throw("mappedReady and other memstats are not equal") + if doubleCheckReadMemStats { + // Only check this if we're debugging. It would be bad to crash an application + // just because the debugging stats are wrong. We mostly rely on tests to catch + // these issues, and we enable the double check mode for tests. + // + // The world is stopped, so the consistent stats (after aggregation) + // should be identical to some combination of memstats. In particular: + // + // * memstats.heapInUse == inHeap + // * memstats.heapReleased == released + // * memstats.heapInUse + memstats.heapFree == committed - inStacks - inWorkBufs - inPtrScalarBits + // * memstats.totalAlloc == totalAlloc + // * memstats.totalFree == totalFree + // + // Check if that's actually true. + // + // Prevent sysmon and the tracer from skewing the stats since they can + // act without synchronizing with a STW. See #64401. + lock(&sched.sysmonlock) + lock(&trace.lock) + if gcController.heapInUse.load() != uint64(consStats.inHeap) { + print("runtime: heapInUse=", gcController.heapInUse.load(), "\n") + print("runtime: consistent value=", consStats.inHeap, "\n") + throw("heapInUse and consistent stats are not equal") + } + if gcController.heapReleased.load() != uint64(consStats.released) { + print("runtime: heapReleased=", gcController.heapReleased.load(), "\n") + print("runtime: consistent value=", consStats.released, "\n") + throw("heapReleased and consistent stats are not equal") + } + heapRetained := gcController.heapInUse.load() + gcController.heapFree.load() + consRetained := uint64(consStats.committed - consStats.inStacks - consStats.inWorkBufs - consStats.inPtrScalarBits) + if heapRetained != consRetained { + print("runtime: global value=", heapRetained, "\n") + print("runtime: consistent value=", consRetained, "\n") + throw("measures of the retained heap are not equal") + } + if gcController.totalAlloc.Load() != totalAlloc { + print("runtime: totalAlloc=", gcController.totalAlloc.Load(), "\n") + print("runtime: consistent value=", totalAlloc, "\n") + throw("totalAlloc and consistent stats are not equal") + } + if gcController.totalFree.Load() != totalFree { + print("runtime: totalFree=", gcController.totalFree.Load(), "\n") + print("runtime: consistent value=", totalFree, "\n") + throw("totalFree and consistent stats are not equal") + } + // Also check that mappedReady lines up with totalMapped - released. + // This isn't really the same type of "make sure consistent stats line up" situation, + // but this is an opportune time to check. + if gcController.mappedReady.Load() != totalMapped-uint64(consStats.released) { + print("runtime: mappedReady=", gcController.mappedReady.Load(), "\n") + print("runtime: totalMapped=", totalMapped, "\n") + print("runtime: released=", uint64(consStats.released), "\n") + print("runtime: totalMapped-released=", totalMapped-uint64(consStats.released), "\n") + throw("mappedReady and other memstats are not equal") + } + unlock(&trace.lock) + unlock(&sched.sysmonlock) } // We've calculated all the values we need. Now, populate stats. diff --git a/contrib/go/_std_1.21/src/runtime/os_windows.go b/contrib/go/_std_1.21/src/runtime/os_windows.go index f5c2429a05..735a905b61 100644 --- a/contrib/go/_std_1.21/src/runtime/os_windows.go +++ b/contrib/go/_std_1.21/src/runtime/os_windows.go @@ -127,15 +127,8 @@ var ( _AddVectoredContinueHandler, _ stdFunction - // Use RtlGenRandom to generate cryptographically random data. - // This approach has been recommended by Microsoft (see issue - // 15589 for details). - // The RtlGenRandom is not listed in advapi32.dll, instead - // RtlGenRandom function can be found by searching for SystemFunction036. - // Also some versions of Mingw cannot link to SystemFunction036 - // when building executable as Cgo. So load SystemFunction036 - // manually during runtime startup. - _RtlGenRandom stdFunction + // Use ProcessPrng to generate cryptographically random data. + _ProcessPrng stdFunction // Load ntdll.dll manually during startup, otherwise Mingw // links wrong printf function to cgo executable (see issue @@ -152,12 +145,12 @@ var ( ) var ( - advapi32dll = [...]uint16{'a', 'd', 'v', 'a', 'p', 'i', '3', '2', '.', 'd', 'l', 'l', 0} - kernel32dll = [...]uint16{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0} - ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0} - powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0} - winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0} - ws2_32dll = [...]uint16{'w', 's', '2', '_', '3', '2', '.', 'd', 'l', 'l', 0} + bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', 'd', 'l', 'l', 0} + kernel32dll = [...]uint16{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0} + ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0} + powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0} + winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0} + ws2_32dll = [...]uint16{'w', 's', '2', '_', '3', '2', '.', 'd', 'l', 'l', 0} ) // Function to be called by windows CreateThread @@ -256,11 +249,11 @@ func loadOptionalSyscalls() { } _AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000")) - a32 := windowsLoadSystemLib(advapi32dll[:]) - if a32 == 0 { - throw("advapi32.dll not found") + bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:]) + if bcryptPrimitives == 0 { + throw("bcryptprimitives.dll not found") } - _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000")) + _ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000")) n32 := windowsLoadSystemLib(ntdlldll[:]) if n32 == 0 { @@ -617,7 +610,7 @@ func initWine(k32 uintptr) { //go:nosplit func getRandomData(r []byte) { n := 0 - if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { + if stdcall2(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { n = len(r) } extendRandom(r, n) diff --git a/contrib/go/_std_1.21/src/runtime/pprof/proto.go b/contrib/go/_std_1.21/src/runtime/pprof/proto.go index cdc4bd7c80..db9384eb21 100644 --- a/contrib/go/_std_1.21/src/runtime/pprof/proto.go +++ b/contrib/go/_std_1.21/src/runtime/pprof/proto.go @@ -611,13 +611,14 @@ func (b *profileBuilder) emitLocation() uint64 { b.pb.uint64Opt(tagLocation_Address, uint64(firstFrame.PC)) for _, frame := range b.deck.frames { // Write out each line in frame expansion. - funcID := uint64(b.funcs[frame.Function]) + funcName := runtime_FrameSymbolName(&frame) + funcID := uint64(b.funcs[funcName]) if funcID == 0 { funcID = uint64(len(b.funcs)) + 1 - b.funcs[frame.Function] = int(funcID) + b.funcs[funcName] = int(funcID) newFuncs = append(newFuncs, newFunc{ id: funcID, - name: runtime_FrameSymbolName(&frame), + name: funcName, file: frame.File, startLine: int64(runtime_FrameStartLine(&frame)), }) diff --git a/contrib/go/_std_1.21/src/runtime/runtime.go b/contrib/go/_std_1.21/src/runtime/runtime.go index 0822d0e805..15119cf5df 100644 --- a/contrib/go/_std_1.21/src/runtime/runtime.go +++ b/contrib/go/_std_1.21/src/runtime/runtime.go @@ -101,12 +101,17 @@ func (g *godebugInc) IncNonDefault() { if newInc == nil { return } - // If other goroutines are racing here, no big deal. One will win, - // and all the inc functions will be using the same underlying - // *godebug.Setting. inc = new(func()) *inc = (*newInc)(g.name) - g.inc.Store(inc) + if raceenabled { + racereleasemerge(unsafe.Pointer(&g.inc)) + } + if !g.inc.CompareAndSwap(nil, inc) { + inc = g.inc.Load() + } + } + if raceenabled { + raceacquire(unsafe.Pointer(&g.inc)) } (*inc)() } diff --git a/contrib/go/_std_1.21/src/runtime/runtime1.go b/contrib/go/_std_1.21/src/runtime/runtime1.go index 92a7e021ee..7174c63af3 100644 --- a/contrib/go/_std_1.21/src/runtime/runtime1.go +++ b/contrib/go/_std_1.21/src/runtime/runtime1.go @@ -309,6 +309,7 @@ type dbgVar struct { var debug struct { cgocheck int32 clobberfree int32 + disablethp int32 dontfreezetheworld int32 efence int32 gccheckmark int32 @@ -342,6 +343,7 @@ var dbgvars = []*dbgVar{ {name: "allocfreetrace", value: &debug.allocfreetrace}, {name: "clobberfree", value: &debug.clobberfree}, {name: "cgocheck", value: &debug.cgocheck}, + {name: "disablethp", value: &debug.disablethp}, {name: "dontfreezetheworld", value: &debug.dontfreezetheworld}, {name: "efence", value: &debug.efence}, {name: "gccheckmark", value: &debug.gccheckmark}, diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/comp_ref_type.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/comp_ref_type.h index f0a0a31665..f2338e1446 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/comp_ref_type.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/comp_ref_type.h @@ -49,8 +49,8 @@ struct __debug_less template <class _LHS, class _RHS> _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_INLINE_VISIBILITY - decltype((void)declval<_Compare&>()( - declval<_LHS &>(), declval<_RHS &>())) + decltype((void)std::declval<_Compare&>()( + std::declval<_LHS &>(), std::declval<_RHS &>())) __do_compare_assert(int, _LHS & __l, _RHS & __r) { _LIBCPP_DEBUG_ASSERT(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering"); diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy.h index d6a46f6952..193a6df316 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy.h @@ -9,100 +9,118 @@ #ifndef _LIBCPP___ALGORITHM_COPY_H #define _LIBCPP___ALGORITHM_COPY_H -#include <__algorithm/unwrap_iter.h> -#include <__algorithm/unwrap_range.h> +#include <__algorithm/copy_move_common.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/min.h> #include <__config> -#include <__iterator/iterator_traits.h> -#include <__iterator/reverse_iterator.h> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <cstring> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -// copy +template <class, class _InIter, class _Sent, class _OutIter> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); + +template <class _AlgPolicy> +struct __copy_loop { + template <class _InIter, class _Sent, class _OutIter> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + while (__first != __last) { + *__result = *__first; + ++__first; + ++__result; + } -template <class _InIter, class _Sent, class _OutIter> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -pair<_InIter, _OutIter> __copy_impl(_InIter __first, _Sent __last, _OutIter __result) { - while (__first != __last) { - *__result = *__first; - ++__first; - ++__result; + return std::make_pair(std::move(__first), std::move(__result)); } - return pair<_InIter, _OutIter>(std::move(__first), std::move(__result)); -} -template <class _InValueT, - class _OutValueT, - class = __enable_if_t<is_same<__remove_const_t<_InValueT>, _OutValueT>::value - && is_trivially_copy_assignable<_OutValueT>::value> > -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -pair<_InValueT*, _OutValueT*> __copy_impl(_InValueT* __first, _InValueT* __last, _OutValueT* __result) { - if (__libcpp_is_constant_evaluated() -// TODO: Remove this once GCC supports __builtin_memmove during constant evaluation -#ifndef _LIBCPP_COMPILER_GCC - && !is_trivially_copyable<_InValueT>::value -#endif - ) - return std::__copy_impl<_InValueT*, _InValueT*, _OutValueT*>(__first, __last, __result); - const size_t __n = static_cast<size_t>(__last - __first); - if (__n > 0) - ::__builtin_memmove(__result, __first, __n * sizeof(_OutValueT)); - return std::make_pair(__first + __n, __result + __n); -} + template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, std::move(__iters.second)); + } -template <class _InIter, class _OutIter, - __enable_if_t<is_same<__remove_const_t<__iter_value_type<_InIter> >, __iter_value_type<_OutIter> >::value - && __is_cpp17_contiguous_iterator<typename _InIter::iterator_type>::value - && __is_cpp17_contiguous_iterator<typename _OutIter::iterator_type>::value - && is_trivially_copy_assignable<__iter_value_type<_OutIter> >::value - && __is_reverse_iterator<_InIter>::value - && __is_reverse_iterator<_OutIter>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -pair<_InIter, _OutIter> -__copy_impl(_InIter __first, _InIter __last, _OutIter __result) { - auto __first_base = std::__unwrap_iter(__first.base()); - auto __last_base = std::__unwrap_iter(__last.base()); - auto __result_base = std::__unwrap_iter(__result.base()); - auto __result_first = __result_base - (__first_base - __last_base); - std::__copy_impl(__last_base, __first_base, __result_first); - return std::make_pair(__last, _OutIter(std::__rewrap_iter(__result.base(), __result_first))); -} + __result = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + while (__sfirst != __slast) { + __result = + std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + } + __result = + std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + return std::make_pair(__last, std::move(__result)); + } -template <class _InIter, class _Sent, class _OutIter, - __enable_if_t<!(is_copy_constructible<_InIter>::value - && is_copy_constructible<_Sent>::value - && is_copy_constructible<_OutIter>::value), int> = 0 > -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result) { - return std::__copy_impl(std::move(__first), std::move(__last), std::move(__result)); -} + template <class _InIter, + class _OutIter, + __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; -template <class _InIter, class _Sent, class _OutIter, - __enable_if_t<is_copy_constructible<_InIter>::value - && is_copy_constructible<_Sent>::value - && is_copy_constructible<_OutIter>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result) { - auto __range = std::__unwrap_range(__first, __last); - auto __ret = std::__copy_impl(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__result)); - return std::make_pair( - std::__rewrap_range<_Sent>(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); + if (__first == __last) + return std::make_pair(std::move(__first), std::move(__result)); + + auto __local_first = _Traits::__local(__result); + auto __segment_iterator = _Traits::__segment(__result); + while (true) { + auto __local_last = _Traits::__end(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iters = std::__copy<_AlgPolicy>(__first, __first + __size, __local_first); + __first = std::move(__iters.first); + + if (__first == __last) + return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second))); + + __local_first = _Traits::__begin(++__segment_iterator); + } + } +}; + +struct __copy_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template <class _In, class _Out, + __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_trivial_impl(__first, __last, __result); + } +}; + +template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> +pair<_InIter, _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +__copy(_InIter __first, _Sent __last, _OutIter __result) { + return std::__dispatch_copy_or_move<_AlgPolicy, __copy_loop<_AlgPolicy>, __copy_trivial>( + std::move(__first), std::move(__last), std::move(__result)); } template <class _InputIterator, class _OutputIterator> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 -_OutputIterator +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return std::__copy(__first, __last, __result).second; + return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second; } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_COPY_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_backward.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_backward.h index 1db4f1e2d5..bb2a432878 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_backward.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_backward.h @@ -9,54 +9,135 @@ #ifndef _LIBCPP___ALGORITHM_COPY_BACKWARD_H #define _LIBCPP___ALGORITHM_COPY_BACKWARD_H -#include <__algorithm/copy.h> +#include <__algorithm/copy_move_common.h> #include <__algorithm/iterator_operations.h> -#include <__algorithm/ranges_copy.h> -#include <__algorithm/unwrap_iter.h> -#include <__concepts/same_as.h> +#include <__algorithm/min.h> #include <__config> -#include <__iterator/iterator_traits.h> -#include <__iterator/reverse_iterator.h> -#include <__ranges/subrange.h> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <cstring> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -template <class _AlgPolicy, class _InputIterator, class _OutputIterator, - __enable_if_t<is_same<_AlgPolicy, _ClassicAlgPolicy>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InputIterator, _OutputIterator> -__copy_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - auto __ret = std::__copy( - __unconstrained_reverse_iterator<_InputIterator>(__last), - __unconstrained_reverse_iterator<_InputIterator>(__first), - __unconstrained_reverse_iterator<_OutputIterator>(__result)); - return pair<_InputIterator, _OutputIterator>(__ret.first.base(), __ret.second.base()); -} +template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter> +__copy_backward(_InIter __first, _Sent __last, _OutIter __result); + +template <class _AlgPolicy> +struct __copy_backward_loop { + template <class _InIter, class _Sent, class _OutIter> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + auto __original_last_iter = __last_iter; + + while (__first != __last_iter) { + *--__result = *--__last_iter; + } + + return std::make_pair(std::move(__original_last_iter), std::move(__result)); + } + + template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = + std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, __iters.second); + } + + __result = + std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result)) + .second; + --__slast; + while (__sfirst != __slast) { + __result = + std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result)) + .second; + --__slast; + } + __result = std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result)) + .second; + return std::make_pair(__last, std::move(__result)); + } + + template <class _InIter, + class _OutIter, + __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + auto __orig_last = __last; + auto __segment_iterator = _Traits::__segment(__result); -#if _LIBCPP_STD_VER > 17 -template <class _AlgPolicy, class _Iter1, class _Sent1, class _Iter2, - __enable_if_t<is_same<_AlgPolicy, _RangeAlgPolicy>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI constexpr pair<_Iter1, _Iter2> __copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) { - auto __last_iter = _IterOps<_AlgPolicy>::next(__first, std::move(__last)); - auto __reverse_range = std::__reverse_range(std::ranges::subrange(std::move(__first), __last_iter)); - auto __ret = ranges::copy(std::move(__reverse_range), std::make_reverse_iterator(__result)); - return std::make_pair(__last_iter, __ret.out.base()); + // When the range contains no elements, __result might not be a valid iterator + if (__first == __last) + return std::make_pair(__first, __result); + + auto __local_last = _Traits::__local(__result); + while (true) { + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; + + auto __local_first = _Traits::__begin(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iter = std::__copy_backward<_AlgPolicy>(__last - __size, __last, __local_last).second; + __last -= __size; + + if (__first == __last) + return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter))); + --__segment_iterator; + __local_last = _Traits::__end(__segment_iterator); + } + } +}; + +struct __copy_backward_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template <class _In, class _Out, + __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_backward_trivial_impl(__first, __last, __result); + } +}; + +template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> +__copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { + return std::__dispatch_copy_or_move<_AlgPolicy, __copy_backward_loop<_AlgPolicy>, __copy_backward_trivial>( + std::move(__first), std::move(__last), std::move(__result)); } -#endif // _LIBCPP_STD_VER > 17 template <class _BidirectionalIterator1, class _BidirectionalIterator2> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 -copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { - return std::__copy_backward<_ClassicAlgPolicy>(__first, __last, __result).second; +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_BidirectionalIterator2 +copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, + _BidirectionalIterator2 __result) +{ + static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value && + std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); + + return std::__copy_backward<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::move(__result)).second; } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_move_common.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_move_common.h new file mode 100644 index 0000000000..b88c14911b --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/copy_move_common.h @@ -0,0 +1,163 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H +#define _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/unwrap_iter.h> +#include <__algorithm/unwrap_range.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_always_bitcastable.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_trivially_assignable.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/is_volatile.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Type traits. + +template <class _From, class _To> +struct __can_lower_copy_assignment_to_memmove { + static const bool value = + // If the types are always bitcastable, it's valid to do a bitwise copy between them. + __is_always_bitcastable<_From, _To>::value && + // Reject conversions that wouldn't be performed by the regular built-in assignment (e.g. between arrays). + is_trivially_assignable<_To&, const _From&>::value && + // `memmove` doesn't accept `volatile` pointers, make sure the optimization SFINAEs away in that case. + !is_volatile<_From>::value && + !is_volatile<_To>::value; +}; + +template <class _From, class _To> +struct __can_lower_move_assignment_to_memmove { + static const bool value = + __is_always_bitcastable<_From, _To>::value && + is_trivially_assignable<_To&, _From&&>::value && + !is_volatile<_From>::value && + !is_volatile<_To>::value; +}; + +// `memmove` algorithms implementation. + +template <class _In, class _Out> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> +__copy_trivial_impl(_In* __first, _In* __last, _Out* __result) { + const size_t __n = static_cast<size_t>(__last - __first); + ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + + return std::make_pair(__last, __result + __n); +} + +template <class _In, class _Out> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> +__copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) { + const size_t __n = static_cast<size_t>(__last - __first); + __result -= __n; + + ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + + return std::make_pair(__last, __result); +} + +// Iterator unwrapping and dispatching to the correct overload. + +template <class _F1, class _F2> +struct __overload : _F1, _F2 { + using _F1::operator(); + using _F2::operator(); +}; + +template <class _InIter, class _Sent, class _OutIter, class = void> +struct __can_rewrap : false_type {}; + +template <class _InIter, class _Sent, class _OutIter> +struct __can_rewrap<_InIter, + _Sent, + _OutIter, + // Note that sentinels are always copy-constructible. + __enable_if_t< is_copy_constructible<_InIter>::value && + is_copy_constructible<_OutIter>::value > > : true_type {}; + +template <class _Algorithm, + class _InIter, + class _Sent, + class _OutIter, + __enable_if_t<__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> +__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { + auto __range = std::__unwrap_range(__first, std::move(__last)); + auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first)); + return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)), + std::__rewrap_iter(std::move(__out_first), std::move(__result.second))); +} + +template <class _Algorithm, + class _InIter, + class _Sent, + class _OutIter, + __enable_if_t<!__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> +__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { + return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first)); +} + +template <class _IterOps, class _InValue, class _OutIter, class = void> +struct __can_copy_without_conversion : false_type {}; + +template <class _IterOps, class _InValue, class _OutIter> +struct __can_copy_without_conversion< + _IterOps, + _InValue, + _OutIter, + __enable_if_t<is_same<_InValue, typename _IterOps::template __value_type<_OutIter> >::value> > : true_type {}; + +template <class _AlgPolicy, + class _NaiveAlgorithm, + class _OptimizedAlgorithm, + class _InIter, + class _Sent, + class _OutIter> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> +__dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) { +#ifdef _LIBCPP_COMPILER_GCC + // GCC doesn't support `__builtin_memmove` during constant evaluation. + if (__libcpp_is_constant_evaluated()) { + return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); + } +#else + // In Clang, `__builtin_memmove` only supports fully trivially copyable types (just having trivial copy assignment is + // insufficient). Also, conversions are not supported. + if (__libcpp_is_constant_evaluated()) { + using _InValue = typename _IterOps<_AlgPolicy>::template __value_type<_InIter>; + if (!is_trivially_copyable<_InValue>::value || + !__can_copy_without_conversion<_IterOps<_AlgPolicy>, _InValue, _OutIter>::value) { + return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); + } + } +#endif // _LIBCPP_COMPILER_GCC + + using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>; + return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/iter_swap.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/iter_swap.h index 0d93f7f756..44422b5de0 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/iter_swap.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/iter_swap.h @@ -23,7 +23,7 @@ template <class _ForwardIterator1, class _ForwardIterator2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) // _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b))) - _NOEXCEPT_(_NOEXCEPT_(swap(*declval<_ForwardIterator1>(), *declval<_ForwardIterator2>()))) { + _NOEXCEPT_(_NOEXCEPT_(swap(*std::declval<_ForwardIterator1>(), *std::declval<_ForwardIterator2>()))) { swap(*__a, *__b); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/iterator_operations.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/iterator_operations.h index bfe82c2028..bd3e6f1d38 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/iterator_operations.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/iterator_operations.h @@ -21,10 +21,13 @@ #include <__iterator/next.h> #include <__iterator/prev.h> #include <__iterator/readable_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cvref.h> #include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/move.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/move.h index e2f8b22800..ac95bda7b6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/move.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/move.h @@ -9,111 +9,122 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_H #define _LIBCPP___ALGORITHM_MOVE_H +#include <__algorithm/copy_move_common.h> #include <__algorithm/iterator_operations.h> -#include <__algorithm/unwrap_iter.h> +#include <__algorithm/min.h> #include <__config> -#include <__iterator/iterator_traits.h> -#include <__iterator/reverse_iterator.h> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <cstring> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -_LIBCPP_BEGIN_NAMESPACE_STD +_LIBCPP_PUSH_MACROS +#include <__undef_macros> -// move +_LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 -pair<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { - while (__first != __last) { - *__result = _IterOps<_AlgPolicy>::__iter_move(__first); - ++__first; - ++__result; +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> +__move(_InIter __first, _Sent __last, _OutIter __result); + +template <class _AlgPolicy> +struct __move_loop { + template <class _InIter, class _Sent, class _OutIter> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + while (__first != __last) { + *__result = _IterOps<_AlgPolicy>::__iter_move(__first); + ++__first; + ++__result; + } + return std::make_pair(std::move(__first), std::move(__result)); } - return std::make_pair(std::move(__first), std::move(__result)); -} - -template <class _AlgPolicy, - class _InType, - class _OutType, - class = __enable_if_t<is_same<__remove_const_t<_InType>, _OutType>::value - && is_trivially_move_assignable<_OutType>::value> > -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -pair<_InType*, _OutType*> __move_impl(_InType* __first, _InType* __last, _OutType* __result) { - if (__libcpp_is_constant_evaluated() -// TODO: Remove this once GCC supports __builtin_memmove during constant evaluation -#ifndef _LIBCPP_COMPILER_GCC - && !is_trivially_copyable<_InType>::value -#endif - ) - return std::__move_impl<_AlgPolicy, _InType*, _InType*, _OutType*>(__first, __last, __result); - const size_t __n = static_cast<size_t>(__last - __first); - ::__builtin_memmove(__result, __first, __n * sizeof(_OutType)); - return std::make_pair(__first + __n, __result + __n); -} -template <class> -struct __is_trivially_move_assignable_unwrapped_impl : false_type {}; - -template <class _Type> -struct __is_trivially_move_assignable_unwrapped_impl<_Type*> : is_trivially_move_assignable<_Type> {}; - -template <class _Iter> -struct __is_trivially_move_assignable_unwrapped - : __is_trivially_move_assignable_unwrapped_impl<decltype(std::__unwrap_iter<_Iter>(std::declval<_Iter>()))> {}; - -template <class _AlgPolicy, - class _InIter, - class _OutIter, - __enable_if_t<is_same<__remove_const_t<typename iterator_traits<_InIter>::value_type>, - typename iterator_traits<_OutIter>::value_type>::value - && __is_cpp17_contiguous_iterator<_InIter>::value - && __is_cpp17_contiguous_iterator<_OutIter>::value - && is_trivially_move_assignable<__iter_value_type<_OutIter> >::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -pair<reverse_iterator<_InIter>, reverse_iterator<_OutIter> > -__move_impl(reverse_iterator<_InIter> __first, - reverse_iterator<_InIter> __last, - reverse_iterator<_OutIter> __result) { - auto __first_base = std::__unwrap_iter(__first.base()); - auto __last_base = std::__unwrap_iter(__last.base()); - auto __result_base = std::__unwrap_iter(__result.base()); - auto __result_first = __result_base - (__first_base - __last_base); - std::__move_impl<_AlgPolicy>(__last_base, __first_base, __result_first); - return std::make_pair(__last, reverse_iterator<_OutIter>(std::__rewrap_iter(__result.base(), __result_first))); -} + template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, std::move(__iters.second)); + } + + __result = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + while (__sfirst != __slast) { + __result = + std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; + ++__sfirst; + } + __result = + std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + return std::make_pair(__last, std::move(__result)); + } -template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -__enable_if_t<is_copy_constructible<_InIter>::value - && is_copy_constructible<_Sent>::value - && is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > -__move(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = std::__move_impl<_AlgPolicy>( - std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); - return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); -} + template <class _InIter, + class _OutIter, + __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; + + if (__first == __last) + return std::make_pair(std::move(__first), std::move(__result)); + + auto __local_first = _Traits::__local(__result); + auto __segment_iterator = _Traits::__segment(__result); + while (true) { + auto __local_last = _Traits::__end(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iters = std::__move<_AlgPolicy>(__first, __first + __size, __local_first); + __first = std::move(__iters.first); + + if (__first == __last) + return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second))); + + __local_first = _Traits::__begin(++__segment_iterator); + } + } +}; + +struct __move_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template <class _In, class _Out, + __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_trivial_impl(__first, __last, __result); + } +}; template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -__enable_if_t<!is_copy_constructible<_InIter>::value - || !is_copy_constructible<_Sent>::value - || !is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __move(_InIter __first, _Sent __last, _OutIter __result) { - return std::__move_impl<_AlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); + return std::__dispatch_copy_or_move<_AlgPolicy, __move_loop<_AlgPolicy>, __move_trivial>( + std::move(__first), std::move(__last), std::move(__result)); } template <class _InputIterator, class _OutputIterator> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 -_OutputIterator move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return std::__move<_ClassicAlgPolicy>(__first, __last, __result).second; +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + static_assert(is_copy_constructible<_InputIterator>::value, "Iterators has to be copy constructible."); + static_assert(is_copy_constructible<_OutputIterator>::value, "The output iterator has to be copy constructible."); + + return std::__move<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second; } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_MOVE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/move_backward.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/move_backward.h index 02aae26fc4..d4f013be68 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/move_backward.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/move_backward.h @@ -9,81 +9,131 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H +#include <__algorithm/copy_move_common.h> #include <__algorithm/iterator_operations.h> -#include <__algorithm/unwrap_iter.h> +#include <__algorithm/min.h> #include <__config> +#include <__iterator/segmented_iterator.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include <cstring> -#include <type_traits> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -template <class _AlgPolicy, class _InputIterator, class _OutputIterator> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 -_OutputIterator -__move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - while (__first != __last) - *--__result = _IterOps<_AlgPolicy>::__iter_move(--__last); - return __result; -} +template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> +__move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result); -template <class _AlgPolicy, class _InputIterator, class _OutputIterator> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 -_OutputIterator -__move_backward_impl(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result); -} +template <class _AlgPolicy> +struct __move_backward_loop { + template <class _InIter, class _Sent, class _OutIter> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { + auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + auto __original_last_iter = __last_iter; -template <class _AlgPolicy, class _Tp, class _Up> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 -typename enable_if -< - is_same<__remove_const_t<_Tp>, _Up>::value && - is_trivially_move_assignable<_Up>::value, - _Up* ->::type -__move_backward_impl(_Tp* __first, _Tp* __last, _Up* __result) -{ - const size_t __n = static_cast<size_t>(__last - __first); - if (__n > 0) - { - __result -= __n; - _VSTD::memmove(__result, __first, __n * sizeof(_Up)); + while (__first != __last_iter) { + *--__result = _IterOps<_AlgPolicy>::__iter_move(--__last_iter); } - return __result; -} -template <class _AlgPolicy, class _BidirectionalIterator1, class _BidirectionalIterator2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 -_BidirectionalIterator2 -__move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, - _BidirectionalIterator2 __result) -{ - if (__libcpp_is_constant_evaluated()) { - return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result); - } else { - return _VSTD::__rewrap_iter(__result, - _VSTD::__move_backward_impl<_AlgPolicy>(_VSTD::__unwrap_iter(__first), - _VSTD::__unwrap_iter(__last), - _VSTD::__unwrap_iter(__result))); + return std::make_pair(std::move(__original_last_iter), std::move(__result)); + } + + template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + using _Traits = __segmented_iterator_traits<_InIter>; + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + if (__sfirst == __slast) { + auto __iters = + std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); + return std::make_pair(__last, __iters.second); + } + + __result = + std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result)) + .second; + --__slast; + while (__sfirst != __slast) { + __result = + std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result)) + .second; + --__slast; + } + __result = std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result)) + .second; + return std::make_pair(__last, std::move(__result)); + } + + template <class _InIter, + class _OutIter, + __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, + int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) { + using _Traits = __segmented_iterator_traits<_OutIter>; + using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; + + // When the range contains no elements, __result might not be a valid iterator + if (__first == __last) + return std::make_pair(__first, __result); + + auto __orig_last = __last; + + auto __local_last = _Traits::__local(__result); + auto __segment_iterator = _Traits::__segment(__result); + while (true) { + auto __local_first = _Traits::__begin(__segment_iterator); + auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); + auto __iter = std::__move_backward<_AlgPolicy>(__last - __size, __last, __local_last).second; + __last -= __size; + + if (__first == __last) + return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter))); + + __local_last = _Traits::__end(--__segment_iterator); } + } +}; + +struct __move_backward_trivial { + // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. + template <class _In, class _Out, + __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> + operator()(_In* __first, _In* __last, _Out* __result) const { + return std::__copy_backward_trivial_impl(__first, __last, __result); + } +}; + +template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> +__move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { + static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value && + std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); + + return std::__dispatch_copy_or_move<_AlgPolicy, __move_backward_loop<_AlgPolicy>, __move_backward_trivial>( + std::move(__first), std::move(__last), std::move(__result)); } template <class _BidirectionalIterator1, class _BidirectionalIterator2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 -_BidirectionalIterator2 -move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, - _BidirectionalIterator2 __result) -{ - return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2 +move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { + return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second; } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/partial_sort.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/partial_sort.h index 861a5b28dd..e0812affe6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/partial_sort.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/partial_sort.h @@ -47,7 +47,6 @@ _RandomAccessIterator __partial_sort_impl( _IterOps<_AlgPolicy>::iter_swap(__i, __first); std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first); } - } std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp); diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_binary_search.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_binary_search.h index b2a8977652..d72d4e0574 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_binary_search.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_binary_search.h @@ -36,7 +36,7 @@ struct __fn { _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); - return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } template <forward_range _Range, class _Type, class _Proj = identity, @@ -46,7 +46,7 @@ struct __fn { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); - return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } }; } // namespace __binary_search diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy.h index 87a6a1e136..bb02c84efb 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy.h @@ -11,6 +11,7 @@ #include <__algorithm/copy.h> #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> #include <__iterator/concepts.h> @@ -40,7 +41,7 @@ struct __fn { requires indirectly_copyable<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { - auto __ret = std::__copy(std::move(__first), std::move(__last), std::move(__result)); + auto __ret = std::__copy<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -48,7 +49,7 @@ struct __fn { requires indirectly_copyable<iterator_t<_Range>, _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr copy_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __r, _OutIter __result) const { - auto __ret = std::__copy(ranges::begin(__r), ranges::end(__r), std::move(__result)); + auto __ret = std::__copy<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } }; diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_backward.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_backward.h index 67977201fa..f41af66f39 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_backward.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_backward.h @@ -14,7 +14,6 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/concepts.h> -#include <__iterator/reverse_iterator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_n.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_n.h index 38a0a308d3..04bb80b3ba 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_n.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_copy_n.h @@ -11,6 +11,7 @@ #include <__algorithm/copy.h> #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/ranges_copy.h> #include <__config> #include <__functional/identity.h> @@ -51,7 +52,7 @@ struct __fn { template <random_access_iterator _InIter, class _DiffType, random_access_iterator _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { - auto __ret = std::__copy(__first, __first + __n, __result); + auto __ret = std::__copy<_RangeAlgPolicy>(__first, __first + __n, __result); return {__ret.first, __ret.second}; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_iterator_concept.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_iterator_concept.h index c2a508dc9a..3ac6b31703 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_iterator_concept.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -12,7 +12,7 @@ #include <__config> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> -#include <type_traits> +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move.h index 94f9970ed2..46a0970f83 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move.h @@ -14,7 +14,6 @@ #include <__algorithm/move.h> #include <__config> #include <__iterator/concepts.h> -#include <__iterator/iter_move.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move_backward.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move_backward.h index 134e087737..d4e8eb1a50 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move_backward.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_move_backward.h @@ -10,12 +10,12 @@ #define _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H #include <__algorithm/in_out_result.h> -#include <__algorithm/ranges_move.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/move_backward.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iter_move.h> #include <__iterator/next.h> -#include <__iterator/reverse_iterator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> @@ -40,11 +40,8 @@ struct __fn { template <class _InIter, class _Sent, class _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr static move_backward_result<_InIter, _OutIter> __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { - auto __last_iter = ranges::next(__first, std::move(__last)); - auto __ret = ranges::move(std::make_reverse_iterator(__last_iter), - std::make_reverse_iterator(__first), - std::make_reverse_iterator(__result)); - return {std::move(__last_iter), std::move(__ret.out.base())}; + auto __ret = std::__move_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); + return {std::move(__ret.first), std::move(__ret.second)}; } template <bidirectional_iterator _InIter, sentinel_for<_InIter> _Sent, bidirectional_iterator _OutIter> diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_search_n.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_search_n.h index f44afde03e..56ec8f33d4 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_search_n.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_search_n.h @@ -53,12 +53,8 @@ struct __fn { } if constexpr (random_access_iterator<_Iter1>) { - auto __ret = __search_n_random_access_impl<_RangeAlgPolicy>(__first, __last, - __count, - __value, - __pred, - __proj, - __size); + auto __ret = std::__search_n_random_access_impl<_RangeAlgPolicy>( + __first, __last, __count, __value, __pred, __proj, __size); return {std::move(__ret.first), std::move(__ret.second)}; } } diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_difference.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_difference.h index 398ccc975f..607dd687a5 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_difference.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_difference.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/set_difference.h> #include <__config> @@ -60,7 +61,7 @@ struct __fn { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_difference( + auto __ret = std::__set_difference<_RangeAlgPolicy>( __first1, __last1, __first2, __last2, __result, ranges::__make_projected_comp(__comp, __proj1, __proj2)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -81,7 +82,7 @@ struct __fn { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_difference( + auto __ret = std::__set_difference<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_symmetric_difference.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_symmetric_difference.h index b0c79537b1..bc4a906550 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_symmetric_difference.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_symmetric_difference.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H #include <__algorithm/in_in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/set_symmetric_difference.h> #include <__config> @@ -58,7 +59,7 @@ struct __fn { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_symmetric_difference( + auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( std::move(__first1), std::move(__last1), std::move(__first2), @@ -92,7 +93,7 @@ struct __fn { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_symmetric_difference( + auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_union.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_union.h index 500c0b2c2d..f8cd45ca0e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_union.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/ranges_set_union.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_SET_UNION_H #include <__algorithm/in_in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/set_union.h> #include <__config> @@ -61,7 +62,7 @@ struct __fn { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_union( + auto __ret = std::__set_union<_RangeAlgPolicy>( std::move(__first1), std::move(__last1), std::move(__first2), @@ -95,7 +96,7 @@ struct __fn { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_union( + auto __ret = std::__set_union<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/rotate.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/rotate.h index 32682936e3..8934ce095b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/rotate.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/rotate.h @@ -48,7 +48,7 @@ __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) _BidirectionalIterator __lm1 = _Ops::prev(__last); value_type __tmp = _Ops::__iter_move(__lm1); - _BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)); + _BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)).second; *__first = _VSTD::move(__tmp); return __fp1; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_difference.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_difference.h index e0385bf822..cffdc8fc4f 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_difference.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_difference.h @@ -12,6 +12,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -26,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template < class _Comp, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter> +template <class _AlgPolicy, class _Comp, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__remove_cvref_t<_InIter1>, __remove_cvref_t<_OutIter> > __set_difference( _InIter1&& __first1, _Sent1&& __last1, _InIter2&& __first2, _Sent2&& __last2, _OutIter&& __result, _Comp&& __comp) { @@ -42,7 +43,7 @@ __set_difference( ++__first2; } } - return std::__copy(std::move(__first1), std::move(__last1), std::move(__result)); + return std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); } template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare> @@ -53,7 +54,8 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_d _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) { - return std::__set_difference<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __result, __comp) + return std::__set_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( + __first1, __last1, __first2, __last2, __result, __comp) .second; } @@ -64,7 +66,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_d _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) { - return std::__set_difference( + return std::__set_difference<_ClassicAlgPolicy>( __first1, __last1, __first2, diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_symmetric_difference.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_symmetric_difference.h index 97d3f1da7c..bcb0958703 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_symmetric_difference.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_symmetric_difference.h @@ -12,6 +12,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> @@ -35,13 +36,13 @@ struct __set_symmetric_difference_result { : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} }; -template <class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter> +template <class _AlgPolicy, class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter> __set_symmetric_difference( _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { while (__first1 != __last1) { if (__first2 == __last2) { - auto __ret1 = std::__copy_impl(std::move(__first1), std::move(__last1), std::move(__result)); + auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>( std::move(__ret1.first), std::move(__first2), std::move((__ret1.second))); } @@ -59,7 +60,7 @@ __set_symmetric_difference( ++__first2; } } - auto __ret2 = std::__copy_impl(std::move(__first2), std::move(__last2), std::move(__result)); + auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result)); return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>( std::move(__first1), std::move(__ret2.first), std::move((__ret2.second))); } @@ -72,7 +73,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetri _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) { - return std::__set_symmetric_difference<__comp_ref_type<_Compare> >( + return std::__set_symmetric_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( std::move(__first1), std::move(__last1), std::move(__first2), diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_union.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_union.h index addc77b7d8..4d154b81e0 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_union.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/set_union.h @@ -12,6 +12,7 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> @@ -35,12 +36,12 @@ struct __set_union_result { : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} }; -template <class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter> +template <class _AlgPolicy, class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_union_result<_InIter1, _InIter2, _OutIter> __set_union( _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { for (; __first1 != __last1; ++__result) { if (__first2 == __last2) { - auto __ret1 = std::__copy_impl(std::move(__first1), std::move(__last1), std::move(__result)); + auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); return __set_union_result<_InIter1, _InIter2, _OutIter>( std::move(__ret1.first), std::move(__first2), std::move((__ret1.second))); } @@ -55,7 +56,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_union_result<_InIter1, ++__first1; } } - auto __ret2 = std::__copy_impl(std::move(__first2), std::move(__last2), std::move(__result)); + auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result)); return __set_union_result<_InIter1, _InIter2, _OutIter>( std::move(__first1), std::move(__ret2.first), std::move((__ret2.second))); } @@ -68,7 +69,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union( _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) { - return std::__set_union<__comp_ref_type<_Compare> >( + return std::__set_union<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( std::move(__first1), std::move(__last1), std::move(__first2), diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/shuffle.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/shuffle.h index c2f5c37efa..f7bce68697 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/shuffle.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/shuffle.h @@ -16,6 +16,7 @@ #include <__random/uniform_int_distribution.h> #include <__utility/forward.h> #include <__utility/move.h> +#include <__utility/swap.h> #include <cstddef> #include <cstdint> diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/sort.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/sort.h index 81f6eeb238..a236be0a4d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/sort.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/sort.h @@ -15,7 +15,6 @@ #include <__algorithm/min_element.h> #include <__algorithm/partial_sort.h> #include <__algorithm/unwrap_iter.h> -#include <__bits> #include <__config> #include <__debug> #include <__debug_utils/randomize_range.h> @@ -24,8 +23,13 @@ #include <__iterator/iterator_traits.h> #include <__memory/destruct_n.h> #include <__memory/unique_ptr.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_trivially_copy_assignable.h> +#include <__type_traits/is_trivially_copy_constructible.h> #include <__utility/move.h> +#include <bit> #include <climits> +#include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -626,7 +630,7 @@ inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { template <class _WrappedComp, class _RandomAccessIterator> _LIBCPP_HIDDEN void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; - difference_type __depth_limit = 2 * __log2i(__last - __first); + difference_type __depth_limit = 2 * std::__log2i(__last - __first); using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; using _AlgPolicy = typename _Unwrap::_AlgPolicy; diff --git a/contrib/libs/cxxsupp/libcxx/include/__algorithm/unwrap_iter.h b/contrib/libs/cxxsupp/libcxx/include/__algorithm/unwrap_iter.h index 07d8d23e33..0f661e10a7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__algorithm/unwrap_iter.h +++ b/contrib/libs/cxxsupp/libcxx/include/__algorithm/unwrap_iter.h @@ -12,8 +12,10 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/declval.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__assert b/contrib/libs/cxxsupp/libcxx/include/__assert index 5905d28c02..9bfab8716e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__assert +++ b/contrib/libs/cxxsupp/libcxx/include/__assert @@ -41,7 +41,7 @@ # define _LIBCPP_ASSERT(expression, message) \ (__builtin_expect(static_cast<bool>(expression), 1) ? \ (void)0 : \ - ::std::__libcpp_verbose_abort("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message)) + _LIBCPP_VERBOSE_ABORT("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message)) // Disable Clang builtins which nvcc does not understand #elif !defined(_LIBCPP_ASSERTIONS_DISABLE_ASSUME) && __has_builtin(__builtin_assume) && !defined(__CUDACC__) # define _LIBCPP_ASSERT(expression, message) \ diff --git a/contrib/libs/cxxsupp/libcxx/include/__availability b/contrib/libs/cxxsupp/libcxx/include/__availability index 72ff663334..6dfca3fa8b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__availability +++ b/contrib/libs/cxxsupp/libcxx/include/__availability @@ -156,20 +156,9 @@ # define _LIBCPP_AVAILABILITY_FORMAT // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format - // This controls whether the default verbose termination function is - // provided by the library. - // - // Note that when users provide their own custom function, it doesn't - // matter whether the dylib provides a default function, and the - // availability markup can actually give a false positive diagnostic - // (it will think that no function is provided, when in reality the - // user has provided their own). - // - // Users can pass -D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED - // to the compiler to tell the library not to define its own verbose abort. - // Note that defining this macro but failing to define a custom function - // will lead to a load-time error on back-deployment targets, so it should - // be avoided. + // This controls whether the library claims to provide a default verbose + // termination function, and consequently whether the headers will try + // to use it when the mechanism isn't overriden at compile-time. // # define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY #elif defined(__APPLE__) diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/bit_cast.h b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_cast.h index 831207671e..2ca4120c76 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__bit/bit_cast.h +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_cast.h @@ -11,7 +11,7 @@ #define _LIBCPP___BIT_BIT_CAST_H #include <__config> -#include <type_traits> +#include <__type_traits/is_trivially_copyable.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/bit_ceil.h b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_ceil.h new file mode 100644 index 0000000000..a558d61942 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_ceil.h @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_CEIL_H +#define _LIBCPP___BIT_BIT_CEIL_H + +#include <__assert> +#include <__bit/countl.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { + if (__t < 2) + return 1; + const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u)); + _LIBCPP_ASSERT(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); + + if constexpr (sizeof(_Tp) >= sizeof(unsigned)) + return _Tp{1} << __n; + else { + const unsigned __extra = numeric_limits<unsigned>::digits - numeric_limits<_Tp>::digits; + const unsigned __retVal = 1u << (__n + __extra); + return (_Tp)(__retVal >> __extra); + } +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BIT_CEIL_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/bit_floor.h b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_floor.h new file mode 100644 index 0000000000..b2e38092f2 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_floor.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_FLOOR_H +#define _LIBCPP___BIT_BIT_FLOOR_H + +#include <__bit/bit_log2.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { + return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BIT_FLOOR_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/bit_log2.h b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_log2.h new file mode 100644 index 0000000000..62936f6786 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_log2.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_LOG2_H +#define _LIBCPP___BIT_BIT_LOG2_H + +#include <__bit/countl.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept { + return numeric_limits<_Tp>::digits - 1 - std::countl_zero(__t); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BIT_LOG2_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/bit_width.h b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_width.h new file mode 100644 index 0000000000..4381f227f5 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/bit_width.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BIT_WIDTH_H +#define _LIBCPP___BIT_BIT_WIDTH_H + +#include <__bit/bit_log2.h> +#include <__concepts/arithmetic.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { + return __t == 0 ? 0 : std::__bit_log2(__t) + 1; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___BIT_BIT_WIDTH_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/blsr.h b/contrib/libs/cxxsupp/libcxx/include/__bit/blsr.h new file mode 100644 index 0000000000..de991e9adb --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/blsr.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_BLSR_H +#define _LIBCPP___BIT_BLSR_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unsigned __libcpp_blsr(unsigned __x) _NOEXCEPT { + return __x ^ (__x & -__x); +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unsigned long __libcpp_blsr(unsigned long __x) _NOEXCEPT { + return __x ^ (__x & -__x); +} + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unsigned long long __libcpp_blsr(unsigned long long __x) _NOEXCEPT { + return __x ^ (__x & -__x); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_BLSR_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/countl.h b/contrib/libs/cxxsupp/libcxx/include/__bit/countl.h new file mode 100644 index 0000000000..86eaee0c1b --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/countl.h @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_COUNTL_H +#define _LIBCPP___BIT_COUNTL_H + +#include <__bit/rotate.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__type_traits/is_unsigned_integer.h> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); } + +# ifndef _LIBCPP_HAS_NO_INT128 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_clz(__uint128_t __x) _NOEXCEPT { + // The function is written in this form due to C++ constexpr limitations. + // The algorithm: + // - Test whether any bit in the high 64-bits is set + // - No bits set: + // - The high 64-bits contain 64 leading zeros, + // - Add the result of the low 64-bits. + // - Any bits set: + // - The number of leading zeros of the input is the number of leading + // zeros in the high 64-bits. + return ((__x >> 64) == 0) + ? (64 + __builtin_clzll(static_cast<unsigned long long>(__x))) + : __builtin_clzll(static_cast<unsigned long long>(__x >> 64)); +} +# endif // _LIBCPP_HAS_NO_INT128 + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +int __countl_zero(_Tp __t) _NOEXCEPT +{ + static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type"); + if (__t == 0) + return numeric_limits<_Tp>::digits; + + if (sizeof(_Tp) <= sizeof(unsigned int)) + return std::__libcpp_clz(static_cast<unsigned int>(__t)) + - (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return std::__libcpp_clz(static_cast<unsigned long>(__t)) + - (numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return std::__libcpp_clz(static_cast<unsigned long long>(__t)) + - (numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits); + else + { + int __ret = 0; + int __iter = 0; + const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits; + while (true) { + __t = std::__rotr(__t, __ulldigits); + if ((__iter = std::__countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits) + break; + __ret += __iter; + } + return __ret + __iter; + } +} + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { + return std::__countl_zero(__t); +} + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { + return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_COUNTL_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/countr.h b/contrib/libs/cxxsupp/libcxx/include/__bit/countr.h new file mode 100644 index 0000000000..d3ca5b6c94 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/countr.h @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_COUNTR_H +#define _LIBCPP___BIT_COUNTR_H + +#include <__bit/rotate.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); } + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { + if (__t == 0) + return numeric_limits<_Tp>::digits; + + if (sizeof(_Tp) <= sizeof(unsigned int)) + return std::__libcpp_ctz(static_cast<unsigned int>(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return std::__libcpp_ctz(static_cast<unsigned long>(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return std::__libcpp_ctz(static_cast<unsigned long long>(__t)); + else { + int __ret = 0; + const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits; + while (static_cast<unsigned long long>(__t) == 0uLL) { + __ret += __ulldigits; + __t >>= __ulldigits; + } + return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t)); + } +} + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { + return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_COUNTR_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/endian.h b/contrib/libs/cxxsupp/libcxx/include/__bit/endian.h new file mode 100644 index 0000000000..52635f2d24 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/endian.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_ENDIAN_H +#define _LIBCPP___BIT_ENDIAN_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +enum class endian { + little = 0xDEAD, + big = 0xFACE, +# if defined(_LIBCPP_LITTLE_ENDIAN) + native = little +# elif defined(_LIBCPP_BIG_ENDIAN) + native = big +# else + native = 0xCAFE +# endif +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___BIT_ENDIAN_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/has_single_bit.h b/contrib/libs/cxxsupp/libcxx/include/__bit/has_single_bit.h new file mode 100644 index 0000000000..b89f5995b3 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/has_single_bit.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_HAS_SINGLE_BIT_H +#define _LIBCPP___BIT_HAS_SINGLE_BIT_H + +#include <__concepts/arithmetic.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { + return __t != 0 && (((__t & (__t - 1)) == 0)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_HAS_SINGLE_BIT_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/popcount.h b/contrib/libs/cxxsupp/libcxx/include/__bit/popcount.h new file mode 100644 index 0000000000..33b94cff71 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/popcount.h @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_POPCOUNT_H +#define _LIBCPP___BIT_POPCOUNT_H + +#include <__bit/rotate.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_popcount(unsigned __x) _NOEXCEPT { return __builtin_popcount(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_popcount(unsigned long __x) _NOEXCEPT { return __builtin_popcountl(__x); } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popcountll(__x); } + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { + if (sizeof(_Tp) <= sizeof(unsigned int)) + return std::__libcpp_popcount(static_cast<unsigned int>(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return std::__libcpp_popcount(static_cast<unsigned long>(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return std::__libcpp_popcount(static_cast<unsigned long long>(__t)); + else { + int __ret = 0; + while (__t != 0) { + __ret += std::__libcpp_popcount(static_cast<unsigned long long>(__t)); + __t >>= numeric_limits<unsigned long long>::digits; + } + return __ret; + } +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___BIT_POPCOUNT_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit/rotate.h b/contrib/libs/cxxsupp/libcxx/include/__bit/rotate.h new file mode 100644 index 0000000000..5aa7518b3c --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__bit/rotate.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_ROTATE_H +#define _LIBCPP___BIT_ROTATE_H + +#include <__concepts/arithmetic.h> +#include <__config> +#include <__type_traits/is_unsigned_integer.h> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 +_Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT +{ + static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type"); + const unsigned int __dig = numeric_limits<_Tp>::digits; + if ((__cnt % __dig) == 0) + return __t; + return (__t >> (__cnt % __dig)) | (__t << (__dig - (__cnt % __dig))); +} + +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { + const unsigned int __dig = numeric_limits<_Tp>::digits; + if ((__cnt % __dig) == 0) + return __t; + return (__t << (__cnt % __dig)) | (__t >> (__dig - (__cnt % __dig))); +} + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { + return std::__rotr(__t, __cnt); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_ROTATE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__bit_reference b/contrib/libs/cxxsupp/libcxx/include/__bit_reference index e104a989fa..5cfa8ecee1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__bit_reference +++ b/contrib/libs/cxxsupp/libcxx/include/__bit_reference @@ -13,7 +13,8 @@ #include <__algorithm/copy_n.h> #include <__algorithm/fill_n.h> #include <__algorithm/min.h> -#include <__bits> +#include <__bit/countr.h> +#include <__bit/popcount.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__memory/construct_at.h> @@ -54,6 +55,8 @@ class __bit_reference friend class __bit_const_reference<_Cp>; friend class __bit_iterator<_Cp, false>; public: + using __container = typename _Cp::__self; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference(const __bit_reference&) = default; @@ -88,7 +91,7 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT {*__seg_ ^= __mask_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT - {return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(__libcpp_ctz(__mask_)));} + {return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));} private: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT @@ -163,7 +166,7 @@ public: {return static_cast<bool>(*__seg_ & __mask_);} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT - {return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(__libcpp_ctz(__mask_)));} + {return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));} private: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR diff --git a/contrib/libs/cxxsupp/libcxx/include/__bits b/contrib/libs/cxxsupp/libcxx/include/__bits deleted file mode 100644 index d2c8439a6b..0000000000 --- a/contrib/libs/cxxsupp/libcxx/include/__bits +++ /dev/null @@ -1,75 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___BITS -#define _LIBCPP___BITS - -#include <__config> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - - -_LIBCPP_BEGIN_NAMESPACE_STD - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); } - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); } - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); } - - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); } - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); } - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); } - -# ifndef _LIBCPP_HAS_NO_INT128 -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_clz(__uint128_t __x) _NOEXCEPT { - // The function is written in this form due to C++ constexpr limitations. - // The algorithm: - // - Test whether any bit in the high 64-bits is set - // - No bits set: - // - The high 64-bits contain 64 leading zeros, - // - Add the result of the low 64-bits. - // - Any bits set: - // - The number of leading zeros of the input is the number of leading - // zeros in the high 64-bits. - return ((__x >> 64) == 0) - ? (64 + __builtin_clzll(static_cast<unsigned long long>(__x))) - : __builtin_clzll(static_cast<unsigned long long>(__x >> 64)); -} -# endif - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_popcount(unsigned __x) _NOEXCEPT { return __builtin_popcount(__x); } - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_popcount(unsigned long __x) _NOEXCEPT { return __builtin_popcountl(__x); } - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popcountll(__x); } - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___BITS diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/convert_to_tm.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/convert_to_tm.h index dea9758efb..36846b3f71 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/convert_to_tm.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/convert_to_tm.h @@ -12,12 +12,23 @@ #include <__chrono/day.h> #include <__chrono/duration.h> +#include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> +#include <__chrono/statically_widen.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> #include <__chrono/weekday.h> #include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> #include <__concepts/same_as.h> #include <__config> +#include <__memory/addressof.h> #include <cstdint> +#include <ctime> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -27,6 +38,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 +// Conerts a chrono date and weekday to a given _Tm type. +// +// This is an implementation detail for the function +// template <class _Tm, class _ChronoT> +// _Tm __convert_to_tm(const _ChronoT& __value) +// +// This manually converts the two values to the proper type. It is possible to +// convert from sys_days to time_t and then to _Tm. But this leads to the Y2K +// bug when time_t is a 32-bit signed integer. Chrono considers years beyond +// the year 2038 valid, so instead do the transformation manually. +template <class _Tm, class _Date> + requires(same_as<_Date, chrono::year_month_day> || same_as<_Date, chrono::year_month_day_last>) +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _Date& __date, chrono::weekday __weekday) { + _Tm __result = {}; +# ifdef __GLIBC__ + __result.tm_zone = "UTC"; +# endif + __result.tm_year = static_cast<int>(__date.year()) - 1900; + __result.tm_mon = static_cast<unsigned>(__date.month()) - 1; + __result.tm_mday = static_cast<unsigned>(__date.day()); + __result.tm_wday = static_cast<unsigned>(__weekday.c_encoding()); + __result.tm_yday = + (static_cast<chrono::sys_days>(__date) - + static_cast<chrono::sys_days>(chrono::year_month_day{__date.year(), chrono::January, chrono::day{1}})) + .count(); + + return __result; +} + // Convert a chrono (calendar) time point, or dururation to the given _Tm type, // which must have the same properties as std::tm. template <class _Tm, class _ChronoT> @@ -55,7 +95,26 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { __result.tm_year = static_cast<int>(__value) - 1900; else if constexpr (same_as<_ChronoT, chrono::weekday>) __result.tm_wday = __value.c_encoding(); - else + else if constexpr (same_as<_ChronoT, chrono::weekday_indexed> || same_as<_ChronoT, chrono::weekday_last>) + __result.tm_wday = __value.weekday().c_encoding(); + else if constexpr (same_as<_ChronoT, chrono::month_day>) { + __result.tm_mday = static_cast<unsigned>(__value.day()); + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::month_day_last>) { + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::month_weekday> || same_as<_ChronoT, chrono::month_weekday_last>) { + __result.tm_wday = __value.weekday_indexed().weekday().c_encoding(); + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month>) { + __result.tm_year = static_cast<int>(__value.year()) - 1900; + __result.tm_mon = static_cast<unsigned>(__value.month()) - 1; + } else if constexpr (same_as<_ChronoT, chrono::year_month_day> || same_as<_ChronoT, chrono::year_month_day_last>) { + return std::__convert_to_tm<_Tm>( + chrono::year_month_day{__value}, chrono::weekday{static_cast<chrono::sys_days>(__value)}); + } else if constexpr (same_as<_ChronoT, chrono::year_month_weekday> || + same_as<_ChronoT, chrono::year_month_weekday_last>) { + return std::__convert_to_tm<_Tm>(chrono::year_month_day{static_cast<chrono::sys_days>(__value)}, __value.weekday()); + } else static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); return __result; diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/duration.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/duration.h index 4ad6467b2a..afcc38b5cf 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/duration.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/duration.h @@ -11,9 +11,12 @@ #define _LIBCPP___CHRONO_DURATION_H #include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_floating_point.h> #include <limits> #include <ratio> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -151,7 +154,7 @@ typename enable_if >::type floor(const duration<_Rep, _Period>& __d) { - _ToDuration __t = duration_cast<_ToDuration>(__d); + _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); if (__t > __d) __t = __t - _ToDuration{1}; return __t; @@ -166,7 +169,7 @@ typename enable_if >::type ceil(const duration<_Rep, _Period>& __d) { - _ToDuration __t = duration_cast<_ToDuration>(__d); + _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); if (__t < __d) __t = __t + _ToDuration{1}; return __t; @@ -181,7 +184,7 @@ typename enable_if >::type round(const duration<_Rep, _Period>& __d) { - _ToDuration __lower = floor<_ToDuration>(__d); + _ToDuration __lower = chrono::floor<_ToDuration>(__d); _ToDuration __upper = __lower + _ToDuration{1}; auto __lowerDiff = __d - __lower; auto __upperDiff = __upper - __d; @@ -612,4 +615,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP___CHRONO_DURATION_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/formatter.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/formatter.h index 89c1e82f42..2015783acb 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/formatter.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/formatter.h @@ -10,17 +10,23 @@ #ifndef _LIBCPP___CHRONO_FORMATTER_H #define _LIBCPP___CHRONO_FORMATTER_H +#include <__chrono/calendar.h> #include <__chrono/convert_to_tm.h> #include <__chrono/day.h> #include <__chrono/duration.h> #include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> #include <__chrono/ostream.h> #include <__chrono/parser_std_format_spec.h> #include <__chrono/statically_widen.h> #include <__chrono/time_point.h> #include <__chrono/weekday.h> #include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> @@ -195,7 +201,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // FMT honours precision and has a bug for separator // https://godbolt.org/z/78b7sMxns if constexpr (chrono::__is_duration<_Tp>::value) { - __sstr << format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{}"), __value.count()); + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{}"), __value.count()); break; } __builtin_unreachable(); @@ -249,6 +255,15 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); } break; + case _CharT('F'): { + int __year = __t.tm_year + 1900; + if (__year < 1000) { + __formatter::__format_year(__year, __sstr); + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); + } else + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + } break; + case _CharT('O'): if constexpr (__use_fraction<_Tp>()) { // Handle OS using the normal representation for the non-fractional @@ -276,7 +291,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( } template <class _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { +_LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) @@ -285,6 +300,28 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { return true; else if constexpr (same_as<_Tp, chrono::weekday>) return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.weekday().ok(); else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -299,6 +336,100 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { return true; else if constexpr (same_as<_Tp, chrono::weekday>) return __value.ok(); + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return __value.weekday_indexed().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return __value.weekday_indexed().ok(); + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.weekday().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.weekday().ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month>) + return true; + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.ok(); + else + static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { + if constexpr (same_as<_Tp, chrono::day>) + return true; + else if constexpr (same_as<_Tp, chrono::month>) + return __value.ok(); + else if constexpr (same_as<_Tp, chrono::year>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_indexed>) + return true; + else if constexpr (same_as<_Tp, chrono::weekday_last>) + return true; + else if constexpr (same_as<_Tp, chrono::month_day>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_day_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::month_weekday_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_day_last>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday>) + return __value.month().ok(); + else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) + return __value.month().ok(); else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -331,9 +462,19 @@ __format_chrono(const _Tp& __value, // Note that the behaviour what the precision does isn't specified. __specs.__precision_ = -1; } else { + // Test __weekday_name_ before __weekday_ to give a better error. if (__specs.__chrono_.__weekday_name_ && !__formatter::__weekday_name_ok(__value)) std::__throw_format_error("formatting a weekday name needs a valid weekday"); + if (__specs.__chrono_.__weekday_ && !__formatter::__weekday_ok(__value)) + std::__throw_format_error("formatting a weekday needs a valid weekday"); + + if (__specs.__chrono_.__day_of_year_ && !__formatter::__date_ok(__value)) + std::__throw_format_error("formatting a day of year needs a valid date"); + + if (__specs.__chrono_.__week_of_year_ && !__formatter::__date_ok(__value)) + std::__throw_format_error("formatting a week of year needs a valid date"); + if (__specs.__chrono_.__month_name_ && !__formatter::__month_name_ok(__value)) std::__throw_format_error("formatting a month name from an invalid month number"); @@ -436,6 +577,138 @@ public: } }; +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_indexed, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday_last, _CharT> + : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + } +}; + #endif // if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/hh_mm_ss.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/hh_mm_ss.h index fde005d097..fd61cbe8f8 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/hh_mm_ss.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/hh_mm_ss.h @@ -58,10 +58,10 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr explicit hh_mm_ss(_Duration __d) noexcept : __is_neg_(__d < _Duration(0)), - __h_(duration_cast<chrono::hours> (abs(__d))), - __m_(duration_cast<chrono::minutes>(abs(__d) - hours())), - __s_(duration_cast<chrono::seconds>(abs(__d) - hours() - minutes())), - __f_(duration_cast<precision> (abs(__d) - hours() - minutes() - seconds())) + __h_(chrono::duration_cast<chrono::hours> (chrono::abs(__d))), + __m_(chrono::duration_cast<chrono::minutes>(chrono::abs(__d) - hours())), + __s_(chrono::duration_cast<chrono::seconds>(chrono::abs(__d) - hours() - minutes())), + __f_(chrono::duration_cast<precision> (chrono::abs(__d) - hours() - minutes() - seconds())) {} _LIBCPP_HIDE_FROM_ABI constexpr bool is_negative() const noexcept { return __is_neg_; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/ostream.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/ostream.h index c48bd6a8b3..30a04bd265 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/ostream.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/ostream.h @@ -13,9 +13,14 @@ #include <__chrono/day.h> #include <__chrono/duration.h> #include <__chrono/month.h> +#include <__chrono/month_weekday.h> +#include <__chrono/monthday.h> #include <__chrono/statically_widen.h> #include <__chrono/weekday.h> #include <__chrono/year.h> +#include <__chrono/year_month.h> +#include <__chrono/year_month_day.h> +#include <__chrono/year_month_weekday.h> #include <__concepts/same_as.h> #include <__config> #include <__format/format_functions.h> @@ -136,6 +141,94 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { static_cast<unsigned>(__wd.c_encoding()))); } +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { + auto __i = __wdi.index(); + return __os << (__i >= 1 && __i <= 5 + ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{}]"), __wdi.weekday(), __i) + : std::format(__os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{} is not a valid index]"), + __wdi.weekday(), + __i)); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_last& __wdl) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[last]"), __wdl.weekday()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { + // TODO FMT The Standard allows 30th of February to be printed. + // It would be nice to show an error message instead. + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{}"), __md.month(), __md.day()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day_last& __mdl) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/last"), __mdl.month()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday& __mwd) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwd.month(), __mwd.weekday_indexed()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday_last& __mwdl) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwdl.month(), __mwdl.weekday_last()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ym.year(), __ym.month()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day& __ymd) { + return __os << (__ymd.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F}"), __ymd) + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F} is not a valid date"), __ymd)); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day_last& __ymdl) { + return __os << std::format( + __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ymdl.year(), __ymdl.month_day_last()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday& __ymwd) { + return __os << std::format( + __os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), + __ymwd.year(), + __ymwd.month(), + __ymwd.weekday_indexed()); +} + +template <class _CharT, class _Traits> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl) { + return __os << std::format( + __os.getloc(), + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), + __ymwdl.year(), + __ymwdl.month(), + __ymwdl.weekday_last()); +} + } // namespace chrono #endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/parser_std_format_spec.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/parser_std_format_spec.h index cdf7b9b15f..dbcfe6da60 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/parser_std_format_spec.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/parser_std_format_spec.h @@ -243,17 +243,20 @@ private: break; case _CharT('j'): + __parser_.__day_of_year_ = true; __format_spec::__validate_date_or_duration(__flags); break; case _CharT('g'): - case _CharT('x'): - case _CharT('D'): - case _CharT('F'): case _CharT('G'): case _CharT('U'): case _CharT('V'): case _CharT('W'): + __parser_.__week_of_year_ = true; + [[fallthrough]]; + case _CharT('x'): + case _CharT('D'): + case _CharT('F'): __format_spec::__validate_date(__flags); break; @@ -267,6 +270,8 @@ private: [[fallthrough]]; case _CharT('u'): case _CharT('w'): + __parser_.__weekday_ = true; + __validate_weekday(__flags); __format_spec::__validate_weekday(__flags); break; @@ -373,11 +378,13 @@ private: case _CharT('U'): case _CharT('V'): case _CharT('W'): + __parser_.__week_of_year_ = true; __format_spec::__validate_date(__flags); break; case _CharT('u'): case _CharT('w'): + __parser_.__weekday_ = true; __format_spec::__validate_weekday(__flags); break; diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/statically_widen.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/statically_widen.h index dd12c3f502..360b6c2c7d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/statically_widen.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/statically_widen.h @@ -26,26 +26,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <__fmt_char_type _CharT> -consteval const _CharT* __statically_widen(const char* __str, const wchar_t* __wstr) { +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __str, const wchar_t* __wstr) { if constexpr (same_as<_CharT, char>) return __str; else return __wstr; } # define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str, L##__str) -# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS // Without this indirection the unit test test/libcxx/modules_include.sh.cpp // fails for the CI build "No wide characters". This seems like a bug. // TODO FMT investigate why this is needed. template <__fmt_char_type _CharT> -consteval const _CharT* __statically_widen(const char* __str) { +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __str) { return __str; } # define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str) # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS -#endif //if _LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__chrono/time_point.h b/contrib/libs/cxxsupp/libcxx/include/__chrono/time_point.h index cc9c462c9d..8a8fa2176d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__chrono/time_point.h +++ b/contrib/libs/cxxsupp/libcxx/include/__chrono/time_point.h @@ -12,8 +12,10 @@ #include <__chrono/duration.h> #include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -98,7 +100,7 @@ typename enable_if >::type floor(const time_point<_Clock, _Duration>& __t) { - return time_point<_Clock, _ToDuration>{floor<_ToDuration>(__t.time_since_epoch())}; + return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())}; } template <class _ToDuration, class _Clock, class _Duration> @@ -110,7 +112,7 @@ typename enable_if >::type ceil(const time_point<_Clock, _Duration>& __t) { - return time_point<_Clock, _ToDuration>{ceil<_ToDuration>(__t.time_since_epoch())}; + return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())}; } template <class _ToDuration, class _Clock, class _Duration> @@ -122,7 +124,7 @@ typename enable_if >::type round(const time_point<_Clock, _Duration>& __t) { - return time_point<_Clock, _ToDuration>{round<_ToDuration>(__t.time_since_epoch())}; + return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())}; } template <class _Rep, class _Period> diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/common_comparison_category.h b/contrib/libs/cxxsupp/libcxx/include/__compare/common_comparison_category.h index deab171846..06c4b28491 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/common_comparison_category.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/common_comparison_category.h @@ -11,7 +11,8 @@ #include <__compare/ordering.h> #include <__config> -#include <type_traits> +#include <__type_traits/is_same.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -64,7 +65,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __get_comp_type() { using _CCC = _ClassifyCompCategory; constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; - constexpr _CCC _Cat = __compute_comp_type(__type_kinds); + constexpr _CCC _Cat = __comp_detail::__compute_comp_type(__type_kinds); if constexpr (_Cat == _None) return void(); else if constexpr (_Cat == _PartialOrd) diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_partial_order_fallback.h b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_partial_order_fallback.h index ba746d6c7d..06f03fe7ad 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_partial_order_fallback.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_partial_order_fallback.h @@ -12,9 +12,10 @@ #include <__compare/ordering.h> #include <__compare/partial_order.h> #include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> #include <__utility/forward.h> #include <__utility/priority_tag.h> -#include <type_traits> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_strong_order_fallback.h b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_strong_order_fallback.h index 312a08ef7e..869386817a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_strong_order_fallback.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_strong_order_fallback.h @@ -12,9 +12,10 @@ #include <__compare/ordering.h> #include <__compare/strong_order.h> #include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> #include <__utility/forward.h> #include <__utility/priority_tag.h> -#include <type_traits> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_three_way_result.h b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_three_way_result.h index 3047f5bd2a..8885d7effa 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_three_way_result.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_three_way_result.h @@ -11,7 +11,7 @@ #include <__config> #include <__type_traits/make_const_lvalue_ref.h> -#include <type_traits> +#include <__utility/declval.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,9 +26,9 @@ struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result { }; template<class _Tp, class _Up> struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result<_Tp, _Up, decltype( - declval<__make_const_lvalue_ref<_Tp>>() <=> declval<__make_const_lvalue_ref<_Up>>(), void() + std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>(), void() )> { - using type = decltype(declval<__make_const_lvalue_ref<_Tp>>() <=> declval<__make_const_lvalue_ref<_Up>>()); + using type = decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>()); }; template<class _Tp, class _Up = _Tp> diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_weak_order_fallback.h b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_weak_order_fallback.h index 844d676087..f434dcb4a3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/compare_weak_order_fallback.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/compare_weak_order_fallback.h @@ -12,9 +12,10 @@ #include <__compare/ordering.h> #include <__compare/weak_order.h> #include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> #include <__utility/forward.h> #include <__utility/priority_tag.h> -#include <type_traits> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/ordering.h b/contrib/libs/cxxsupp/libcxx/include/__compare/ordering.h index ab35a598a8..ff148abf23 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/ordering.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/ordering.h @@ -10,7 +10,8 @@ #define _LIBCPP___COMPARE_ORDERING_H #include <__config> -#include <type_traits> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_same.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/partial_order.h b/contrib/libs/cxxsupp/libcxx/include/__compare/partial_order.h index 970f01b3f1..aee07ebb42 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/partial_order.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/partial_order.h @@ -13,9 +13,10 @@ #include <__compare/ordering.h> #include <__compare/weak_order.h> #include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/is_same.h> #include <__utility/forward.h> #include <__utility/priority_tag.h> -#include <type_traits> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header @@ -28,6 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [cmp.alg] namespace __partial_order { struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) partial_order should use ADL, but only here template<class _Tp, class _Up> requires is_same_v<decay_t<_Tp>, decay_t<_Up>> _LIBCPP_HIDE_FROM_ABI static constexpr auto @@ -35,6 +37,7 @@ namespace __partial_order { noexcept(noexcept(partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) -> decltype( partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) { return partial_ordering(partial_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + // NOLINTEND(libcpp-robust-against-adl) template<class _Tp, class _Up> requires is_same_v<decay_t<_Tp>, decay_t<_Up>> diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/strong_order.h b/contrib/libs/cxxsupp/libcxx/include/__compare/strong_order.h index 67c7b2910b..05856c2093 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/strong_order.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/strong_order.h @@ -13,12 +13,13 @@ #include <__compare/compare_three_way.h> #include <__compare/ordering.h> #include <__config> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> #include <__utility/forward.h> #include <__utility/priority_tag.h> #include <cmath> #include <cstdint> #include <limits> -#include <type_traits> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header @@ -34,6 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [cmp.alg] namespace __strong_order { struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) strong_order should use ADL, but only here template<class _Tp, class _Up> requires is_same_v<decay_t<_Tp>, decay_t<_Up>> _LIBCPP_HIDE_FROM_ABI static constexpr auto @@ -41,6 +43,7 @@ namespace __strong_order { noexcept(noexcept(strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) -> decltype( strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) { return strong_ordering(strong_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + // NOLINTEND(libcpp-robust-against-adl) template<class _Tp, class _Up, class _Dp = decay_t<_Tp>> requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/synth_three_way.h b/contrib/libs/cxxsupp/libcxx/include/__compare/synth_three_way.h index fa8cbda79b..7d338987e0 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/synth_three_way.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/synth_three_way.h @@ -42,7 +42,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = }; template <class _Tp, class _Up = _Tp> -using __synth_three_way_result = decltype(std::__synth_three_way(declval<_Tp&>(), declval<_Up&>())); +using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); #endif // _LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/three_way_comparable.h b/contrib/libs/cxxsupp/libcxx/include/__compare/three_way_comparable.h index cab2cb2896..6c98916d85 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/three_way_comparable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/three_way_comparable.h @@ -16,8 +16,8 @@ #include <__concepts/same_as.h> #include <__concepts/totally_ordered.h> #include <__config> +#include <__type_traits/common_reference.h> #include <__type_traits/make_const_lvalue_ref.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__compare/weak_order.h b/contrib/libs/cxxsupp/libcxx/include/__compare/weak_order.h index c2fae1a98d..abb24e3665 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__compare/weak_order.h +++ b/contrib/libs/cxxsupp/libcxx/include/__compare/weak_order.h @@ -13,10 +13,10 @@ #include <__compare/ordering.h> #include <__compare/strong_order.h> #include <__config> +#include <__type_traits/decay.h> #include <__utility/forward.h> #include <__utility/priority_tag.h> #include <cmath> -#include <type_traits> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header @@ -29,6 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [cmp.alg] namespace __weak_order { struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) weak_order should use ADL, but only here template<class _Tp, class _Up> requires is_same_v<decay_t<_Tp>, decay_t<_Up>> _LIBCPP_HIDE_FROM_ABI static constexpr auto @@ -36,6 +37,7 @@ namespace __weak_order { noexcept(noexcept(weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))) -> decltype( weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) { return weak_ordering(weak_order(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))); } + // NOLINTEND(libcpp-robust-against-adl) template<class _Tp, class _Up, class _Dp = decay_t<_Tp>> requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/arithmetic.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/arithmetic.h index d91570f02b..215b52aa02 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/arithmetic.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/arithmetic.h @@ -10,9 +10,11 @@ #define _LIBCPP___CONCEPTS_ARITHMETIC_H #include <__config> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_signed.h> #include <__type_traits/is_signed_integer.h> #include <__type_traits/is_unsigned_integer.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/assignable.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/assignable.h index db09e5a0a5..91edd400ad 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/assignable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/assignable.h @@ -12,9 +12,9 @@ #include <__concepts/common_reference_with.h> #include <__concepts/same_as.h> #include <__config> +#include <__type_traits/is_reference.h> #include <__type_traits/make_const_lvalue_ref.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/class_or_enum.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/class_or_enum.h index 6287c52992..c4d2f98952 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/class_or_enum.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/class_or_enum.h @@ -10,7 +10,10 @@ #define _LIBCPP___CONCEPTS_CLASS_OR_ENUM_H #include <__config> -#include <type_traits> +#include <__type_traits/is_class.h> +#include <__type_traits/is_enum.h> +#include <__type_traits/is_union.h> +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/common_reference_with.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/common_reference_with.h index cae2f5bccc..cc92762d31 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/common_reference_with.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/common_reference_with.h @@ -12,7 +12,7 @@ #include <__concepts/convertible_to.h> #include <__concepts/same_as.h> #include <__config> -#include <type_traits> +#include <__type_traits/common_reference.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/common_with.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/common_with.h index 1b5f4da4af..569a0ee3b7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/common_with.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/common_with.h @@ -12,7 +12,10 @@ #include <__concepts/common_reference_with.h> #include <__concepts/same_as.h> #include <__config> -#include <type_traits> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/common_type.h> +#include <__utility/declval.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -28,8 +31,8 @@ template<class _Tp, class _Up> concept common_with = same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> && requires { - static_cast<common_type_t<_Tp, _Up>>(declval<_Tp>()); - static_cast<common_type_t<_Tp, _Up>>(declval<_Up>()); + static_cast<common_type_t<_Tp, _Up>>(std::declval<_Tp>()); + static_cast<common_type_t<_Tp, _Up>>(std::declval<_Up>()); } && common_reference_with< add_lvalue_reference_t<const _Tp>, diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/constructible.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/constructible.h index aaf515417e..1d78eb5fd1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/constructible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/constructible.h @@ -12,7 +12,7 @@ #include <__concepts/convertible_to.h> #include <__concepts/destructible.h> #include <__config> -#include <type_traits> +#include <__type_traits/is_constructible.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/convertible_to.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/convertible_to.h index 5d9d437104..2c1d267410 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/convertible_to.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/convertible_to.h @@ -10,8 +10,8 @@ #define _LIBCPP___CONCEPTS_CONVERTIBLE_TO_H #include <__config> +#include <__type_traits/is_convertible.h> #include <__utility/declval.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -27,7 +27,7 @@ template<class _From, class _To> concept convertible_to = is_convertible_v<_From, _To> && requires { - static_cast<_To>(declval<_From>()); + static_cast<_To>(std::declval<_From>()); }; #endif // _LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/derived_from.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/derived_from.h index 4b29147947..0d3462df6a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/derived_from.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/derived_from.h @@ -10,7 +10,8 @@ #define _LIBCPP___CONCEPTS_DERIVED_FROM_H #include <__config> -#include <type_traits> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_convertible.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/destructible.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/destructible.h index 90a043d314..ad3819d5dc 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/destructible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/destructible.h @@ -10,7 +10,7 @@ #define _LIBCPP___CONCEPTS_DESTRUCTIBLE_H #include <__config> -#include <type_traits> +#include <__type_traits/is_nothrow_destructible.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/different_from.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/different_from.h index 3066372e86..15fd8f0551 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/different_from.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/different_from.h @@ -11,7 +11,7 @@ #include <__concepts/same_as.h> #include <__config> -#include <type_traits> +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/equality_comparable.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/equality_comparable.h index c2293d5cd0..b865141705 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/equality_comparable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/equality_comparable.h @@ -12,8 +12,8 @@ #include <__concepts/boolean_testable.h> #include <__concepts/common_reference_with.h> #include <__config> +#include <__type_traits/common_reference.h> #include <__type_traits/make_const_lvalue_ref.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/invocable.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/invocable.h index d90389e97f..ec39b7b817 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/invocable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/invocable.h @@ -12,7 +12,6 @@ #include <__config> #include <__functional/invoke.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/movable.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/movable.h index 639219ed6b..749b78ad10 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/movable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/movable.h @@ -13,7 +13,7 @@ #include <__concepts/constructible.h> #include <__concepts/swappable.h> #include <__config> -#include <type_traits> +#include <__type_traits/is_object.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/predicate.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/predicate.h index cb23975230..7ae9783264 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/predicate.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/predicate.h @@ -12,7 +12,7 @@ #include <__concepts/boolean_testable.h> #include <__concepts/invocable.h> #include <__config> -#include <type_traits> +#include <__functional/invoke.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/same_as.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/same_as.h index 7654906611..554ebc3b07 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/same_as.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/same_as.h @@ -10,7 +10,7 @@ #define _LIBCPP___CONCEPTS_SAME_AS_H #include <__config> -#include <type_traits> +#include <__type_traits/is_same.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/swappable.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/swappable.h index dbb4283645..d91a7a1dc3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/swappable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/swappable.h @@ -14,11 +14,15 @@ #include <__concepts/common_reference_with.h> #include <__concepts/constructible.h> #include <__config> +#include <__type_traits/extent.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/remove_cvref.h> #include <__utility/exchange.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__concepts/totally_ordered.h b/contrib/libs/cxxsupp/libcxx/include/__concepts/totally_ordered.h index 25347790de..f12d26b108 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__concepts/totally_ordered.h +++ b/contrib/libs/cxxsupp/libcxx/include/__concepts/totally_ordered.h @@ -12,7 +12,8 @@ #include <__concepts/boolean_testable.h> #include <__concepts/equality_comparable.h> #include <__config> -#include <type_traits> +#include <__type_traits/common_reference.h> +#include <__type_traits/make_const_lvalue_ref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__config b/contrib/libs/cxxsupp/libcxx/include/__config index b5dd7efc5a..343a284b1a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__config +++ b/contrib/libs/cxxsupp/libcxx/include/__config @@ -23,6 +23,7 @@ #endif #if defined(__apple_build_version__) +// Given AppleClang XX.Y.Z, _LIBCPP_APPLE_CLANG_VER is XXYZ (e.g. AppleClang 14.0.3 => 1403) # define _LIBCPP_COMPILER_CLANG_BASED # define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) #elif defined(__clang__) @@ -59,7 +60,7 @@ // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. // Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 16.0.1 == 16.00.01), _LIBCPP_VERSION is // defined to XXYYZZ. -# define _LIBCPP_VERSION 160000 +# define _LIBCPP_VERSION 160005 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) @@ -161,6 +162,15 @@ # define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON // According to the Standard, `bitset::operator[] const` returns bool # define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL +// Fix the implementation of CityHash used for std::hash<fundamental-type>. +// This is an ABI break because `std::hash` will return a different result, +// which means that hashing the same object in translation units built against +// different versions of libc++ can return inconsistent results. This is especially +// tricky since std::hash is used in the implementation of unordered containers. +// +// The incorrect implementation of CityHash has the problem that it drops some +// bits on the floor. +# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION // Remove the base 10 implementation of std::to_chars from the dylib. // The implementation moved to the header, but we still export the symbols from // the dylib for backwards compatibility. @@ -223,6 +233,10 @@ # define __has_cpp_attribute(__x) 0 # endif +# ifndef __has_constexpr_builtin +# define __has_constexpr_builtin(x) 0 +# endif + // '__is_identifier' returns '0' if '__x' is a reserved identifier provided by // the compiler and '1' otherwise. # ifndef __is_identifier @@ -633,6 +647,15 @@ typedef __char32_t char32_t; // Note that we use _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION to ensure that we don't depend // on _LIBCPP_HIDE_FROM_ABI methods of classes explicitly instantiated in the dynamic library. // +// Also note that the _LIBCPP_HIDE_FROM_ABI_VIRTUAL macro should be used on virtual functions +// instead of _LIBCPP_HIDE_FROM_ABI. That macro does not use an ABI tag. Indeed, the mangled +// name of a virtual function is part of its ABI, since some architectures like arm64e can sign +// the virtual function pointer in the vtable based on the mangled name of the function. Since +// we use an ABI tag that changes with each released version, the mangled name of the virtual +// function would change, which is incorrect. Note that it doesn't make much sense to change +// the implementation of a virtual function in an ABI-incompatible way in the first place, +// since that would be an ABI break anyway. Hence, the lack of ABI tag should not be noticeable. +// // TODO: We provide a escape hatch with _LIBCPP_NO_ABI_TAG for folks who want to avoid increasing // the length of symbols with an ABI tag. In practice, we should remove the escape hatch and // use compression mangling instead, see https://github.com/itanium-cxx-abi/cxx-abi/issues/70. @@ -643,6 +666,11 @@ typedef __char32_t char32_t; # else # define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # endif +# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION + +// This macro provides a HIDE_FROM_ABI equivalent that can be applied to extern +// "C" function, as those lack mangling. +# define _LIBCPP_HIDE_FROM_ABI_C _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # ifdef _LIBCPP_BUILDING_LIBRARY # if _LIBCPP_ABI_VERSION > 1 @@ -747,6 +775,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION # endif +// It is not yet possible to use aligned_alloc() on all Apple platforms since +// 10.15 was the first version to ship an implementation of aligned_alloc(). +# if defined(__APPLE__) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) +# define _LIBCPP_HAS_NO_C11_ALIGNED_ALLOC +# endif +# elif defined(__ANDROID__) && __ANDROID_API__ < 28 +// Android only provides aligned_alloc when targeting API 28 or higher. +# define _LIBCPP_HAS_NO_C11_ALIGNED_ALLOC +# endif + # if defined(__APPLE__) || defined(__FreeBSD__) # define _LIBCPP_HAS_DEFAULTRUNELOCALE # endif @@ -803,6 +843,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_DEPRECATED_IN_CXX20 # endif +#if _LIBCPP_STD_VER >= 23 +# define _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_DEPRECATED +#else +# define _LIBCPP_DEPRECATED_IN_CXX23 +#endif + # if !defined(_LIBCPP_HAS_NO_CHAR8_T) # define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED # else @@ -886,7 +932,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // Try to find out if RTTI is disabled. # if !defined(__cpp_rtti) || __cpp_rtti < 199711L -# define _LIBCPP_NO_RTTI +# define _LIBCPP_HAS_NO_RTTI # endif # ifndef _LIBCPP_WEAK @@ -1061,6 +1107,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_FALLTHROUGH() ((void)0) # endif +# if __has_cpp_attribute(_Clang::__lifetimebound__) +# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]] +# else +# define _LIBCPP_LIFETIMEBOUND +# endif + # if defined(_LIBCPP_COMPILER_CLANG_BASED) # define _LIBCPP_REINITIALIZES_OBJECT [[clang::reinitializes]] # else @@ -1227,12 +1279,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // functions are declared by the C library. # define _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 // GNU libc 2.36 and newer declare c8rtomb() and mbrtoc8() in C++ modes if -// __cpp_char8_t is defined or if C2X extensions are enabled. Unfortunately, -// determining the latter depends on internal GNU libc details. If the -// __cpp_char8_t feature test macro is not defined, then a char8_t typedef -// will be declared as well. -# if defined(_LIBCPP_GLIBC_PREREQ) && defined(__GLIBC_USE) -# if _LIBCPP_GLIBC_PREREQ(2, 36) && (defined(__cpp_char8_t) || __GLIBC_USE(ISOC2X)) +// __cpp_char8_t is defined or if C2X extensions are enabled. Determining +// the latter depends on internal GNU libc details that are not appropriate +// to depend on here, so any declarations present when __cpp_char8_t is not +// defined are ignored. +# if defined(_LIBCPP_GLIBC_PREREQ) +# if _LIBCPP_GLIBC_PREREQ(2, 36) && defined(__cpp_char8_t) # undef _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 # endif # endif @@ -1250,6 +1302,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") #endif +// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use +// compiler intrinsics in the Objective-C++ mode. +# ifdef __OBJC__ +# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS +# endif + #endif // __cplusplus #endif // _LIBCPP___CONFIG diff --git a/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_handle.h b/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_handle.h index 8f7ed2ee48..0a6cc1cab6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_handle.h +++ b/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_handle.h @@ -13,8 +13,9 @@ #include <__config> #include <__functional/hash.h> #include <__memory/addressof.h> +#include <__type_traits/remove_cv.h> #include <compare> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_traits.h b/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_traits.h index 87eb21830a..d513075098 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_traits.h +++ b/contrib/libs/cxxsupp/libcxx/include/__coroutine/coroutine_traits.h @@ -10,7 +10,7 @@ #define _LIBCPP___COROUTINE_COROUTINE_TRAITS_H #include <__config> -#include <type_traits> +#include <__type_traits/void_t.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__debug b/contrib/libs/cxxsupp/libcxx/include/__debug index ae0c1a5af0..140cc9142a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__debug +++ b/contrib/libs/cxxsupp/libcxx/include/__debug @@ -12,8 +12,8 @@ #include <__assert> #include <__config> +#include <__type_traits/is_constant_evaluated.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__filesystem/filesystem_error.h b/contrib/libs/cxxsupp/libcxx/include/__filesystem/filesystem_error.h index eb5c38ad12..effe699833 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__filesystem/filesystem_error.h +++ b/contrib/libs/cxxsupp/libcxx/include/__filesystem/filesystem_error.h @@ -61,7 +61,7 @@ public: filesystem_error(const filesystem_error&) = default; ~filesystem_error() override; // key function - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const char* what() const noexcept override { return __storage_->__what_.c_str(); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__filesystem/path.h b/contrib/libs/cxxsupp/libcxx/include/__filesystem/path.h index 7d1a784403..4e6912fcf3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__filesystem/path.h +++ b/contrib/libs/cxxsupp/libcxx/include/__filesystem/path.h @@ -619,7 +619,7 @@ public: _EnableIfPathable<_Source> append(const _Source& __src) { using _Traits = __is_pathable<_Source>; using _CVT = _PathCVT<_SourceChar<_Source> >; - bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src)); + bool __source_is_absolute = _VSTD_FS::__is_separator(_Traits::__first_or_null(__src)); if (__source_is_absolute) __pn_.clear(); else if (has_filename()) @@ -634,7 +634,7 @@ public: typedef typename iterator_traits<_InputIt>::value_type _ItVal; static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); using _CVT = _PathCVT<_ItVal>; - if (__first != __last && __is_separator(*__first)) + if (__first != __last && _VSTD_FS::__is_separator(*__first)) __pn_.clear(); else if (has_filename()) __pn_ += preferred_separator; @@ -866,7 +866,7 @@ public: using _Str = basic_string<_ECharT, _Traits, _Allocator>; _Str __s(__a); __s.reserve(__pn_.size()); - _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); + _CVT()(std::back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); return __s; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/buffer.h b/contrib/libs/cxxsupp/libcxx/include/__format/buffer.h index 60c1f8093c..ddfe76728e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/buffer.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/buffer.h @@ -31,6 +31,7 @@ #include <cstddef> #include <string_view> #include <type_traits> +#include <vector> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -493,6 +494,74 @@ public: return {_VSTD::move(this->__writer_).__out_it(), this->__size_}; } }; + +// A dynamically growing buffer intended to be used for retargeting a context. +// +// P2286 Formatting ranges adds range formatting support. It allows the user to +// specify the minimum width for the entire formatted range. The width of the +// range is not known until the range is formatted. Formatting is done to an +// output_iterator so there's no guarantee it would be possible to add the fill +// to the front of the output. Instead the range is formatted to a temporary +// buffer and that buffer is formatted as a string. +// +// There is an issue with that approach, the format context used in +// std::formatter<T>::format contains the output iterator used as part of its +// type. So using this output iterator means there needs to be a new format +// context and the format arguments need to be retargeted to the new context. +// This retargeting is done by a basic_format_context specialized for the +// __iterator of this container. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __retarget_buffer { +public: + using value_type = _CharT; + + struct __iterator { + using difference_type = ptrdiff_t; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer) + : __buffer_(std::addressof(__buffer)) {} + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(const _CharT& __c) { + __buffer_->push_back(__c); + return *this; + } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator=(_CharT&& __c) { + __buffer_->push_back(__c); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator*() { return *this; } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { return *this; } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { return *this; } + __retarget_buffer* __buffer_; + }; + + _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { __buffer_.reserve(__size_hint); } + + _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; } + + _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { __buffer_.push_back(__c); } + + template <__fmt_char_type _InCharT> + _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { + __buffer_.insert(__buffer_.end(), __str.begin(), __str.end()); + } + + template <__fmt_char_type _InCharT, class _UnaryOperation> + _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { + _LIBCPP_ASSERT(__first <= __last, "not a valid range"); + std::transform(__first, __last, std::back_inserter(__buffer_), std::move(__operation)); + } + + _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __buffer_.insert(__buffer_.end(), __n, __value); } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__buffer_.data(), __buffer_.size()}; } + +private: + // Use vector instead of string to avoid adding zeros after every append + // operation. The buffer is exposed as a string_view and not as a c-string. + vector<_CharT> __buffer_; +}; + } // namespace __format #endif //_LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/concepts.h b/contrib/libs/cxxsupp/libcxx/include/__format/concepts.h index 5407feebf7..ba8d8e3162 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/concepts.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/concepts.h @@ -15,6 +15,9 @@ #include <__config> #include <__format/format_fwd.h> #include <__format/format_parse_context.h> +#include <__type_traits/is_specialization.h> +#include <__utility/pair.h> +#include <tuple> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -56,6 +59,16 @@ concept __formattable = # if _LIBCPP_STD_VER > 20 template <class _Tp, class _CharT> concept formattable = __formattable<_Tp, _CharT>; + +// [tuple.like] defines a tuple-like exposition only concept. This concept is +// not related to that. Therefore it uses a different name for the concept. +// +// TODO FMT Add a test to validate we fail when using that concept after P2165 +// has been implemented. +template <class _Tp> +concept __fmt_pair_like = + __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); + # endif //_LIBCPP_STD_VER > 20 #endif //_LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/container_adaptor.h b/contrib/libs/cxxsupp/libcxx/include/__format/container_adaptor.h new file mode 100644 index 0000000000..62b698186e --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__format/container_adaptor.h @@ -0,0 +1,70 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H +#define _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__availability> +#include <__config> +#include <__format/concepts.h> +#include <__format/formatter.h> +#include <__format/range_default_formatter.h> +#include <queue> +#include <stack> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +// [container.adaptors.format] only specifies the library should provide the +// formatter specializations, not which header should provide them. +// Since <format> includes a lot of headers, add these headers here instead of +// adding more dependencies like, locale, optinal, string, tuple, etc. to the +// adaptor headers. To use the format functions users already include <format>. + +template <class _Adaptor, class _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_container_adaptor { +private: + using __maybe_const_adaptor = __fmt_maybe_const<_Adaptor, _CharT>; + formatter<typename _Adaptor::container_type, _CharT> __underlying_; + +public: + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_adaptor& __adaptor, _FormatContext& __ctx) const { + return __underlying_.format(__adaptor.__get_container(), __ctx); + } +}; + +template <class _CharT, class _Tp, formattable<_CharT> _Container> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<queue<_Tp, _Container>, _CharT> + : public __formatter_container_adaptor<queue<_Tp, _Container>, _CharT> {}; + +template <class _CharT, class _Tp, class _Container, class _Compare> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<priority_queue<_Tp, _Container, _Compare>, _CharT> + : public __formatter_container_adaptor<priority_queue<_Tp, _Container, _Compare>, _CharT> {}; + +template <class _CharT, class _Tp, formattable<_CharT> _Container> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<stack<_Tp, _Container>, _CharT> + : public __formatter_container_adaptor<stack<_Tp, _Container>, _CharT> {}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/extended_grapheme_cluster_table.h b/contrib/libs/cxxsupp/libcxx/include/__format/extended_grapheme_cluster_table.h index 0e00670df7..1ffcfeb549 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/extended_grapheme_cluster_table.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -111,7 +111,7 @@ enum class __property : uint8_t { /// - https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt /// /// The data has 3 values -/// - bits [0, 3] The property. One of the values generated form the datafiles +/// - bits [0, 3] The property. One of the values generated from the datafiles /// of \ref __property /// - bits [4, 10] The size of the range. /// - bits [11, 31] The lower bound code point of the range. The upper bound of diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h index 33d931ad79..771a03ff2f 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg.h @@ -161,7 +161,7 @@ public: using _Dp = remove_cvref_t<_Tp>; using _Formatter = typename _Context::template formatter_type<_Dp>; constexpr bool __const_formattable = - requires { _Formatter().format(declval<const _Dp&>(), declval<_Context&>()); }; + requires { _Formatter().format(std::declval<const _Dp&>(), std::declval<_Context&>()); }; using _Qp = conditional_t<__const_formattable, const _Dp, _Dp>; static_assert(__const_formattable || !is_const_v<remove_reference_t<_Tp>>, "Mandated by [format.arg]/18"); diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h index 1820c0387c..6f4f4c3617 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_arg_store.h @@ -198,7 +198,7 @@ _LIBCPP_HIDE_FROM_ABI void __create_packed_storage(uint64_t& __types, __basic_fo int __shift = 0; ( [&] { - basic_format_arg<_Context> __arg = __create_format_arg<_Context>(__args); + basic_format_arg<_Context> __arg = __format::__create_format_arg<_Context>(__args); if (__shift != 0) __types |= static_cast<uint64_t>(__arg.__type_) << __shift; else @@ -212,7 +212,7 @@ _LIBCPP_HIDE_FROM_ABI void __create_packed_storage(uint64_t& __types, __basic_fo template <class _Context, class... _Args> _LIBCPP_HIDE_FROM_ABI void __store_basic_format_arg(basic_format_arg<_Context>* __data, _Args&&... __args) noexcept { - ([&] { *__data++ = __create_format_arg<_Context>(__args); }(), ...); + ([&] { *__data++ = __format::__create_format_arg<_Context>(__args); }(), ...); } template <class _Context, size_t N> diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_context.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_context.h index 882a6049bb..85e00eb222 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_context.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_context.h @@ -11,13 +11,19 @@ #define _LIBCPP___FORMAT_FORMAT_CONTEXT_H #include <__availability> +#include <__concepts/same_as.h> #include <__config> #include <__format/buffer.h> +#include <__format/format_arg.h> +#include <__format/format_arg_store.h> #include <__format/format_args.h> +#include <__format/format_error.h> #include <__format/format_fwd.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/concepts.h> +#include <__memory/addressof.h> #include <__utility/move.h> +#include <__variant/monostate.h> #include <cstddef> #ifndef _LIBCPP_HAS_NO_LOCALIZATION @@ -138,8 +144,78 @@ private: : __out_it_(_VSTD::move(__out_it)), __args_(__args) {} #endif }; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context); +// A specialization for __retarget_buffer +// +// See __retarget_buffer for the motivation for this specialization. +// +// This context holds a reference to the instance of the basic_format_context +// that is retargeted. It converts a formatting argument when it is requested +// during formatting. It is expected that the usage of the arguments is rare so +// the lookups are not expected to be used often. An alternative would be to +// convert all elements during construction. +// +// The elements of the retargets context are only used when an underlying +// formatter uses a locale specific formatting or an formatting argument is +// part for the format spec. For example +// format("{:256:{}}", input, 8); +// Here the width of an element in input is determined dynamically. +// Note when the top-level element has no width the retargeting is not needed. +template <class _CharT> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT + basic_format_context<typename __format::__retarget_buffer<_CharT>::__iterator, _CharT> { +public: + using iterator = typename __format::__retarget_buffer<_CharT>::__iterator; + using char_type = _CharT; + template <class _Tp> + using formatter_type = formatter<_Tp, _CharT>; + + template <class _Context> + _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(iterator __out_it, _Context& __ctx) + : __out_it_(std::move(__out_it)), +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + __loc_([](void* __c) { return static_cast<_Context*>(__c)->locale(); }), +# endif + __ctx_(std::addressof(__ctx)), + __arg_([](void* __c, size_t __id) { + return std::visit_format_arg( + [&](auto __arg) -> basic_format_arg<basic_format_context> { + if constexpr (same_as<decltype(__arg), monostate>) + return {}; + else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Context>::handle>) + // At the moment it's not possible for formatting to use a re-targeted handle. + // TODO FMT add this when support is needed. + std::__throw_format_error("Re-targeting handle not supported"); + else + return basic_format_arg<basic_format_context>{ + __format::__determine_arg_t<basic_format_context, decltype(__arg)>(), + __basic_format_arg_value<basic_format_context>(__arg)}; + }, + static_cast<_Context*>(__c)->arg(__id)); + }) { + } + + _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept { + return __arg_(__ctx_, __id); + } +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() { return __loc_(__ctx_); } +# endif + _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); } + _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = std::move(__it); } + +private: + iterator __out_it_; + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + std::locale (*__loc_)(void* __ctx); +# endif + + void* __ctx_; + basic_format_arg<basic_format_context> (*__arg_)(void* __ctx, size_t __id); +}; + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context); #endif //_LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_functions.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_functions.h index 8c8b54e808..0f0001272d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_functions.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_functions.h @@ -101,7 +101,7 @@ public: // Before calling __parse the proper handler needs to be set with __enable. // The default handler isn't a core constant expression. _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle() - : __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {} + : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {} private: void (*__parse_)(basic_format_parse_context<_CharT>&); @@ -128,13 +128,13 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { if (__id >= __size_) - __throw_format_error("Argument index out of bounds"); + std::__throw_format_error("Argument index out of bounds"); return __args_[__id]; } _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { if (__id >= __size_) - __throw_format_error("Argument index out of bounds"); + std::__throw_format_error("Argument index out of bounds"); return __handles_[__id]; } @@ -159,7 +159,7 @@ constexpr void __compile_time_validate_integral(__arg_t __type) { return; default: - __throw_format_error("Argument isn't an integral type"); + std::__throw_format_error("Argument isn't an integral type"); } } @@ -191,7 +191,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_forma __arg_t __type) { switch (__type) { case __arg_t::__none: - __throw_format_error("Invalid argument"); + std::__throw_format_error("Invalid argument"); case __arg_t::__boolean: return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx); case __arg_t::__char_type: @@ -204,7 +204,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_forma # ifndef _LIBCPP_HAS_NO_INT128 return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); # else - __throw_format_error("Invalid argument"); + std::__throw_format_error("Invalid argument"); # endif return; case __arg_t::__unsigned: @@ -215,7 +215,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_forma # ifndef _LIBCPP_HAS_NO_INT128 return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); # else - __throw_format_error("Invalid argument"); + std::__throw_format_error("Invalid argument"); # endif return; case __arg_t::__float: @@ -231,9 +231,9 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_forma case __arg_t::__ptr: return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx); case __arg_t::__handle: - __throw_format_error("Handle should use __compile_time_validate_handle_argument"); + std::__throw_format_error("Handle should use __compile_time_validate_handle_argument"); } - __throw_format_error("Invalid argument"); + std::__throw_format_error("Invalid argument"); } template <class _CharT, class _ParseCtx, class _Ctx> @@ -253,21 +253,22 @@ __handle_replacement_field(const _CharT* __begin, const _CharT* __end, __parse_ctx.advance_to(__r.__ptr); break; default: - __throw_format_error( - "The replacement field arg-id should terminate at a ':' or '}'"); + std::__throw_format_error("The replacement field arg-id should terminate at a ':' or '}'"); } if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { __arg_t __type = __ctx.arg(__r.__value); - if (__type == __arg_t::__handle) + if (__type == __arg_t::__none) + std::__throw_format_error("Argument index out of bounds"); + else if (__type == __arg_t::__handle) __ctx.__handle(__r.__value).__parse(__parse_ctx); - else - __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); + else if (__parse) + __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); } else _VSTD::__visit_format_arg( [&](auto __arg) { if constexpr (same_as<decltype(__arg), monostate>) - __throw_format_error("Argument index out of bounds"); + std::__throw_format_error("Argument index out of bounds"); else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) __arg.format(__parse_ctx, __ctx); else { @@ -281,7 +282,7 @@ __handle_replacement_field(const _CharT* __begin, const _CharT* __end, __begin = __parse_ctx.begin(); if (__begin == __end || *__begin != _CharT('}')) - __throw_format_error("The replacement field misses a terminating '}'"); + std::__throw_format_error("The replacement field misses a terminating '}'"); return ++__begin; } @@ -300,12 +301,12 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { case _CharT('{'): ++__begin; if (__begin == __end) - __throw_format_error("The format string terminates at a '{'"); + std::__throw_format_error("The format string terminates at a '{'"); if (*__begin != _CharT('{')) [[likely]] { __ctx.advance_to(_VSTD::move(__out_it)); __begin = - __handle_replacement_field(__begin, __end, __parse_ctx, __ctx); + __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx); __out_it = __ctx.out(); // The output is written and __begin points to the next character. So @@ -318,8 +319,7 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { case _CharT('}'): ++__begin; if (__begin == __end || *__begin != _CharT('}')) - __throw_format_error( - "The format string contains an invalid escape sequence"); + std::__throw_format_error("The format string contains an invalid escape sequence"); break; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_parse_context.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_parse_context.h index 4bcfda1138..30e3a7dfda 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_parse_context.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_parse_context.h @@ -54,8 +54,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr size_t next_arg_id() { if (__indexing_ == __manual) - __throw_format_error("Using automatic argument numbering in manual " - "argument numbering mode"); + std::__throw_format_error("Using automatic argument numbering in manual argument numbering mode"); if (__indexing_ == __unknown) __indexing_ = __automatic; @@ -63,8 +62,7 @@ public: } _LIBCPP_HIDE_FROM_ABI constexpr void check_arg_id(size_t __id) { if (__indexing_ == __automatic) - __throw_format_error("Using manual argument numbering in automatic " - "argument numbering mode"); + std::__throw_format_error("Using manual argument numbering in automatic argument numbering mode"); if (__indexing_ == __unknown) __indexing_ = __manual; @@ -77,7 +75,7 @@ public: // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the // behavior when id >= num_args_. if (is_constant_evaluated() && __id >= __num_args_) - __throw_format_error("Argument index outside the valid range"); + std::__throw_format_error("Argument index outside the valid range"); } private: diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/format_string.h b/contrib/libs/cxxsupp/libcxx/include/__format/format_string.h index 6033180d97..d9caf866a1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/format_string.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/format_string.h @@ -73,7 +73,7 @@ __parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { template <class _CharT> _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> __parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { - __parse_number_result<_CharT> __r = __parse_number(__begin, __end); + __parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end); __parse_ctx.check_arg_id(__r.__value); return __r; } @@ -120,7 +120,7 @@ __parse_number(const _CharT* __begin, const _CharT* __end_input) { if (__v > __number_max || (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9'))) - __throw_format_error("The numeric value of the format-spec is too large"); + std::__throw_format_error("The numeric value of the format-spec is too large"); __value = __v; } @@ -149,8 +149,7 @@ __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { return __detail::__parse_automatic(__begin, __end, __parse_ctx); } if (*__begin < _CharT('0') || *__begin > _CharT('9')) - __throw_format_error( - "The arg-id of the format-spec starts with an invalid character"); + std::__throw_format_error("The arg-id of the format-spec starts with an invalid character"); return __detail::__parse_manual(__begin, __end, __parse_ctx); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h index 154f8a5262..900a09af4e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter.h @@ -38,7 +38,16 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { formatter& operator=(const formatter&) = delete; }; -#endif //_LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER > 20 + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) { + if constexpr (requires { __formatter.set_debug_format(); }) + __formatter.set_debug_format(); +} + +# endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h index 29b3711ef9..ca065723e1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_floating_point.h @@ -404,7 +404,6 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_ // In fixed mode the algorithm truncates trailing spaces and possibly the // radix point. There's no good guess for the position of the radix point // therefore scan the output after the first digit. - __result.__radix_point = _VSTD::find(__first, __result.__last, '.'); } } @@ -498,7 +497,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form( const __float_result& __result, _VSTD::locale __loc, __format_spec::__parsed_specifications<_CharT> __specs) { - const auto& __np = use_facet<numpunct<_CharT>>(__loc); + const auto& __np = std::use_facet<numpunct<_CharT>>(__loc); string __grouping = __np.grouping(); char* __first = __result.__integral; // When no radix point or exponent are present __last will be __result.__last. @@ -665,7 +664,7 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif if (__result.__exponent == __result.__last) // if P > X >= -4, the conversion is with style f or F and precision P - 1 - X. // By including the radix point it calculates P - (1 + X) - __p -= __result.__radix_point - __buffer.begin(); + __p -= __result.__radix_point - __result.__integral; else // otherwise, the conversion is with style e or E and precision P - 1. --__p; diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h index 87c6d559b0..fe3a06311b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_integral.h @@ -217,7 +217,7 @@ _LIBCPP_HIDE_FROM_ABI auto __format_integer( # ifndef _LIBCPP_HAS_NO_LOCALIZATION if (__specs.__std_.__locale_specific_form_) { - const auto& __np = use_facet<numpunct<_CharT>>(__ctx.locale()); + const auto& __np = std::use_facet<numpunct<_CharT>>(__ctx.locale()); string __grouping = __np.grouping(); ptrdiff_t __size = __last - __first; // Writing the grouped form has more overhead than the normal output @@ -310,7 +310,7 @@ __format_integer(_Tp __value, auto& __ctx, __format_spec::__parsed_specification auto __r = std::__to_unsigned_like(__value); bool __negative = __value < 0; if (__negative) - __r = __complement(__r); + __r = std::__complement(__r); return __formatter::__format_integer(__r, __ctx, __specs, __negative); } @@ -342,7 +342,7 @@ __format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications< -> decltype(__ctx.out()) { # ifndef _LIBCPP_HAS_NO_LOCALIZATION if (__specs.__std_.__locale_specific_form_) { - const auto& __np = use_facet<numpunct<_CharT>>(__ctx.locale()); + const auto& __np = std::use_facet<numpunct<_CharT>>(__ctx.locale()); basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename(); return __formatter::__write_string_no_precision(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_output.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_output.h index 4f2c0445c0..467692559c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_output.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_output.h @@ -102,6 +102,10 @@ _LIBCPP_HIDE_FROM_ABI auto __copy(basic_string_view<_CharT> __str, output_iterat if constexpr (_VSTD::same_as<decltype(__out_it), _VSTD::back_insert_iterator<__format::__output_buffer<_OutCharT>>>) { __out_it.__get_container()->__copy(__str); return __out_it; + } else if constexpr (_VSTD::same_as<decltype(__out_it), + typename __format::__retarget_buffer<_OutCharT>::__iterator>) { + __out_it.__buffer_->__copy(__str); + return __out_it; } else { return std::ranges::copy(__str, _VSTD::move(__out_it)).out; } @@ -132,6 +136,10 @@ __transform(const _CharT* __first, if constexpr (_VSTD::same_as<decltype(__out_it), _VSTD::back_insert_iterator<__format::__output_buffer<_OutCharT>>>) { __out_it.__get_container()->__transform(__first, __last, _VSTD::move(__operation)); return __out_it; + } else if constexpr (_VSTD::same_as<decltype(__out_it), + typename __format::__retarget_buffer<_OutCharT>::__iterator>) { + __out_it.__buffer_->__transform(__first, __last, _VSTD::move(__operation)); + return __out_it; } else { return std::ranges::transform(__first, __last, _VSTD::move(__out_it), __operation).out; } @@ -145,6 +153,9 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, _CharT __value) if constexpr (_VSTD::same_as<decltype(__out_it), _VSTD::back_insert_iterator<__format::__output_buffer<_CharT>>>) { __out_it.__get_container()->__fill(__n, __value); return __out_it; + } else if constexpr (_VSTD::same_as<decltype(__out_it), typename __format::__retarget_buffer<_CharT>::__iterator>) { + __out_it.__buffer_->__fill(__n, __value); + return __out_it; } else { return std::ranges::fill_n(_VSTD::move(__out_it), __n, __value); } @@ -171,7 +182,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, c } else { if (__specs.__width_ > __size) { // Determine padding and write padding. - __padding = __padding_size(__size, __specs.__width_, __specs.__alignment_); + __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); } @@ -285,7 +296,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _Cha if (__size >= __specs.__width_) return __formatter::__transform(__first, __last, _VSTD::move(__out_it), __op); - __padding_size_result __padding = __padding_size(__size, __specs.__width_, __specs.__alignment_); + __padding_size_result __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); __out_it = __formatter::__transform(__first, __last, _VSTD::move(__out_it), __op); return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); @@ -312,7 +323,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros( _LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used"); __padding_size_result __padding = - __padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_); + __formatter::__padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_); __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); __out_it = __formatter::__copy(__first, __exponent, _VSTD::move(__out_it)); __out_it = __formatter::__fill(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0')); @@ -368,15 +379,15 @@ _LIBCPP_HIDE_FROM_ABI auto __write_string( int __size = __formatter::__truncate(__str, __specs.__precision_); - return __write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); + return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); } # if _LIBCPP_STD_VER > 20 -struct __null_sentinel {}; +struct __nul_terminator {}; template <class _CharT> -_LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __null_sentinel) { +_LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __nul_terminator) { return *__cstr == _CharT('\0'); } @@ -384,7 +395,7 @@ template <class _CharT> _LIBCPP_HIDE_FROM_ABI void __write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _CharT* __prefix) { back_insert_iterator __out_it{__str}; - std::ranges::copy(__prefix, __null_sentinel{}, __out_it); + std::ranges::copy(__prefix, __nul_terminator{}, __out_it); char __buffer[8]; to_chars_result __r = std::to_chars(std::begin(__buffer), std::end(__buffer), __value, 16); @@ -401,7 +412,7 @@ __write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _ // lower-case hexadecimal digits. template <class _CharT> _LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value) { - __write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{")); + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{")); } // [format.string.escaped]/2.2.3 @@ -411,7 +422,7 @@ _LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_C // lower-case hexadecimal digits. template <class _CharT> _LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_CharT>& __str, char32_t __value) { - __write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{")); + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{")); } template <class _CharT> diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h index d1d1379146..606fb79249 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_string.h @@ -65,6 +65,12 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const _CharT*, _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have " "prevented an invalid pointer."); + __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); +# if _LIBCPP_STD_VER > 20 + if (_Base::__parser_.__type_ == __format_spec::__type::__debug) + return __formatter::__format_escaped_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); +# endif + // When using a center or right alignment and the width option the length // of __str must be known to add the padding upfront. This case is handled // by the base class by converting the argument to a basic_string_view. @@ -76,7 +82,6 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const _CharT*, // now these optimizations aren't implemented. Instead the base class // handles these options. // TODO FMT Implement these improvements. - __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); if (__specs.__has_width() || __specs.__has_precision()) return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/formatter_tuple.h b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_tuple.h new file mode 100644 index 0000000000..82f5ada6e0 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__format/formatter_tuple.h @@ -0,0 +1,178 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_TUPLE_H +#define _LIBCPP___FORMAT_FORMATTER_TUPLE_H + +#include <__algorithm/ranges_copy.h> +#include <__availability> +#include <__chrono/statically_widen.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_args.h> +#include <__format/format_context.h> +#include <__format/format_error.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__iterator/back_insert_iterator.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/integer_sequence.h> +#include <__utility/pair.h> +#include <string_view> +#include <tuple> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +template <__fmt_char_type _CharT, class _Tuple, formattable<_CharT>... _Args> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + __separator_ = __separator; + } + _LIBCPP_HIDE_FROM_ABI constexpr void + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + __opening_bracket_ = __opening_bracket; + __closing_bracket_ = __closing_bracket; + } + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { + const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_tuple); + + // [format.tuple]/7 + // ... For each element e in underlying_, if e.set_debug_format() + // is a valid expression, calls e.set_debug_format(). + // TODO FMT this can be removed when P2733 is accepted. + std::__for_each_index_sequence(make_index_sequence<sizeof...(_Args)>(), [&]<size_t _Index> { + std::__set_debug_format(std::get<_Index>(__underlying_)); + }); + + const _CharT* __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + if (*__begin == _CharT('m')) { + if constexpr (sizeof...(_Args) == 2) { + set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); + set_brackets({}, {}); + ++__begin; + } else + std::__throw_format_error("The format specifier m requires a pair or a two-element tuple"); + } else if (*__begin == _CharT('n')) { + set_brackets({}, {}); + ++__begin; + } + + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + template <class _FormatContext> + typename _FormatContext::iterator _LIBCPP_HIDE_FROM_ABI + format(conditional_t<(formattable<const _Args, _CharT> && ...), const _Tuple&, _Tuple&> __tuple, + _FormatContext& __ctx) const { + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + + if (!__specs.__has_width()) + return __format_tuple(__tuple, __ctx); + + basic_string<_CharT> __str; + + // Since the output is written to a different iterator a new context is + // created. Since the underlying formatter uses the default formatting it + // doesn't need a locale or the formatting arguments. So creating a new + // context works. + // + // This solution works for this formatter, but it will not work for the + // range_formatter. In that patch a generic solution is work in progress. + // Once that is finished it can be used here. (The range_formatter will use + // these features so it's easier to add it there and then port it.) + // + // TODO FMT Use formatting wrapping used in the range_formatter. + basic_format_context __c = std::__format_context_create( + back_insert_iterator{__str}, + basic_format_args<basic_format_context<back_insert_iterator<basic_string<_CharT>>, _CharT>>{}); + + __format_tuple(__tuple, __c); + + return __formatter::__write_string_no_precision(basic_string_view{__str}, __ctx.out(), __specs); + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_tuple(auto&& __tuple, _FormatContext& __ctx) const { + __ctx.advance_to(std::ranges::copy(__opening_bracket_, __ctx.out()).out); + + std::__for_each_index_sequence(make_index_sequence<sizeof...(_Args)>(), [&]<size_t _Index> { + if constexpr (_Index) + __ctx.advance_to(std::ranges::copy(__separator_, __ctx.out()).out); + + // During review Victor suggested to make the exposition only + // __underlying_ member a local variable. Currently the Standard + // requires nested debug-enabled formatter specializations not to + // output escaped output. P2733 fixes that bug, once accepted the + // code below can be used. + // (Note when a paper allows parsing a tuple-underlying-spec the + // exposition only member needs to be a class member. Earlier + // revisions of P2286 proposed that, but this was not pursued, + // due to time constrains and complexity of the matter.) + // TODO FMT This can be updated after P2733 is accepted. +# if 0 + // P2286 uses an exposition only member in the formatter + // tuple<formatter<remove_cvref_t<_Args>, _CharT>...> __underlying_; + // This was used in earlier versions of the paper since + // __underlying_.parse(...) was called. This is no longer the case + // so we can reduce the scope of the formatter. + // + // It does require the underlying's parse effect to be moved here too. + using _Arg = tuple_element<_Index, decltype(__tuple)>; + formatter<remove_cvref_t<_Args>, _CharT> __underlying; + + // [format.tuple]/7 + // ... For each element e in underlying_, if e.set_debug_format() + // is a valid expression, calls e.set_debug_format(). + std::__set_debug_format(__underlying); +# else + __ctx.advance_to(std::get<_Index>(__underlying_).format(std::get<_Index>(__tuple), __ctx)); +# endif + }); + + return std::ranges::copy(__closing_bracket_, __ctx.out()).out; + } + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; + +private: + tuple<formatter<remove_cvref_t<_Args>, _CharT>...> __underlying_; + basic_string_view<_CharT> __separator_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ", "); + basic_string_view<_CharT> __opening_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "("); + basic_string_view<_CharT> __closing_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ")"); +}; + +template <__fmt_char_type _CharT, formattable<_CharT>... _Args> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<pair<_Args...>, _CharT> + : public __formatter_tuple<_CharT, pair<_Args...>, _Args...> {}; + +template <__fmt_char_type _CharT, formattable<_CharT>... _Args> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<tuple<_Args...>, _CharT> + : public __formatter_tuple<_CharT, tuple<_Args...>, _Args...> {}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_TUPLE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h b/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h index 90c0cd184c..c03cec9796 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/parser_std_format_spec.h @@ -19,6 +19,7 @@ #include <__algorithm/find_if.h> #include <__algorithm/min.h> #include <__assert> +#include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> #include <__debug> @@ -52,12 +53,12 @@ __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { // This function is a wrapper to call the real parser. But it does the // validation for the pre-conditions and post-conditions. if (__begin == __end) - __throw_format_error("End of input while parsing format-spec arg-id"); + std::__throw_format_error("End of input while parsing format-spec arg-id"); __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); if (__r.__ptr == __end || *__r.__ptr != _CharT('}')) - __throw_format_error("Invalid arg-id"); + std::__throw_format_error("Invalid arg-id"); ++__r.__ptr; return __r; @@ -80,22 +81,19 @@ __substitute_arg_id(basic_format_arg<_Context> __format_arg) { if constexpr (integral<_Type>) { if constexpr (signed_integral<_Type>) { if (__arg < 0) - __throw_format_error("A format-spec arg-id replacement shouldn't " - "have a negative value"); + std::__throw_format_error("A format-spec arg-id replacement shouldn't have a negative value"); } using _CT = common_type_t<_Type, decltype(__format::__number_max)>; if (static_cast<_CT>(__arg) > static_cast<_CT>(__format::__number_max)) - __throw_format_error("A format-spec arg-id replacement exceeds " - "the maximum supported value"); + std::__throw_format_error("A format-spec arg-id replacement exceeds the maximum supported value"); return __arg; } else if constexpr (same_as<_Type, monostate>) - __throw_format_error("Argument index out of bounds"); + std::__throw_format_error("Argument index out of bounds"); else - __throw_format_error("A format-spec arg-id replacement argument " - "isn't an integral type"); + std::__throw_format_error("A format-spec arg-id replacement argument isn't an integral type"); }, __format_arg); } @@ -104,6 +102,7 @@ __substitute_arg_id(basic_format_arg<_Context> __format_arg) { /// /// They default to false so when a new field is added it needs to be opted in /// explicitly. +// TODO FMT Use an ABI tag for this struct. struct __fields { uint8_t __sign_ : 1 {false}; uint8_t __alternate_form_ : 1 {false}; @@ -111,6 +110,13 @@ struct __fields { uint8_t __precision_ : 1 {false}; uint8_t __locale_specific_form_ : 1 {false}; uint8_t __type_ : 1 {false}; + // Determines the valid values for fill. + // + // Originally the fill could be any character except { and }. Range-based + // formatters use the colon to mark the beginning of the + // underlying-format-spec. To avoid parsing ambiguities these formatter + // specializations prohibit the use of the colon as a fill character. + uint8_t __allow_colon_in_fill_ : 1 {false}; }; // By not placing this constant in the formatter class it's not duplicated for @@ -131,6 +137,11 @@ inline constexpr __fields __fields_floating_point{ inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true}; inline constexpr __fields __fields_pointer{.__type_ = true}; +# if _LIBCPP_STD_VER > 20 +inline constexpr __fields __fields_tuple{.__type_ = false, .__allow_colon_in_fill_ = true}; +inline constexpr __fields __fields_range{.__type_ = false, .__allow_colon_in_fill_ = true}; +# endif + enum class _LIBCPP_ENUM_VIS __alignment : uint8_t { /// No alignment is set in the format string. __default, @@ -186,6 +197,9 @@ struct __chrono { __alignment __alignment_ : 3; bool __locale_specific_form_ : 1; bool __weekday_name_ : 1; + bool __weekday_ : 1; + bool __day_of_year_ : 1; + bool __week_of_year_ : 1; bool __month_name_ : 1; }; @@ -259,7 +273,7 @@ public: if (__begin == __end) return __begin; - if (__parse_fill_align(__begin, __end) && __begin == __end) + if (__parse_fill_align(__begin, __end, __fields.__allow_colon_in_fill_) && __begin == __end) return __begin; if (__fields.__sign_ && __parse_sign(__begin) && __begin == __end) @@ -287,7 +301,7 @@ public: // parsing. In that case that parser should do the end of format string // validation. if (__begin != __end && *__begin != _CharT('}')) - __throw_format_error("The format-spec should consume the input or end with a '}'"); + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); } return __begin; @@ -309,10 +323,14 @@ public: _LIBCPP_HIDE_FROM_ABI __parsed_specifications<_CharT> __get_parsed_chrono_specifications(auto& __ctx) const { return __parsed_specifications<_CharT>{ - .__chrono_ = __chrono{.__alignment_ = __alignment_, - .__locale_specific_form_ = __locale_specific_form_, - .__weekday_name_ = __weekday_name_, - .__month_name_ = __month_name_}, + .__chrono_ = + __chrono{.__alignment_ = __alignment_, + .__locale_specific_form_ = __locale_specific_form_, + .__weekday_name_ = __weekday_name_, + .__weekday_ = __weekday_, + .__day_of_year_ = __day_of_year_, + .__week_of_year_ = __week_of_year_, + .__month_name_ = __month_name_}, .__width_{__get_width(__ctx)}, .__precision_{__get_precision(__ctx)}, .__fill_{__fill_}}; @@ -325,12 +343,17 @@ public: bool __reserved_0_ : 1 {false}; __type __type_{__type::__default}; - // These two flags are used for formatting chrono. Since the struct has + // These flags are only used for formatting chrono. Since the struct has // padding space left it's added to this structure. bool __weekday_name_ : 1 {false}; + bool __weekday_ : 1 {false}; + + bool __day_of_year_ : 1 {false}; + bool __week_of_year_ : 1 {false}; + bool __month_name_ : 1 {false}; - uint8_t __reserved_1_ : 6 {0}; + uint8_t __reserved_1_ : 3 {0}; uint8_t __reserved_2_ : 6 {0}; // These two flags are only used internally and not part of the // __parsed_specifications. Therefore put them at the end. @@ -367,13 +390,17 @@ private: return false; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(const _CharT*& __begin, const _CharT* __end) { + // range-fill and tuple-fill are identical + _LIBCPP_HIDE_FROM_ABI constexpr bool + __parse_fill_align(const _CharT*& __begin, const _CharT* __end, bool __use_range_fill) { _LIBCPP_ASSERT(__begin != __end, "when called with an empty input the function will cause " "undefined behavior by evaluating data not in the input"); if (__begin + 1 != __end) { if (__parse_alignment(*(__begin + 1))) { - if (*__begin == _CharT('{') || *__begin == _CharT('}')) - __throw_format_error("The format-spec fill field contains an invalid character"); + if (__use_range_fill && (*__begin == _CharT('{') || *__begin == _CharT('}') || *__begin == _CharT(':'))) + std::__throw_format_error("The format-spec range-fill field contains an invalid character"); + else if (*__begin == _CharT('{') || *__begin == _CharT('}')) + std::__throw_format_error("The format-spec fill field contains an invalid character"); __fill_ = *__begin; __begin += 2; @@ -427,7 +454,7 @@ private: _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(const _CharT*& __begin, const _CharT* __end, auto& __parse_ctx) { if (*__begin == _CharT('0')) - __throw_format_error("A format-spec width field shouldn't have a leading zero"); + std::__throw_format_error("A format-spec width field shouldn't have a leading zero"); if (*__begin == _CharT('{')) { __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); @@ -455,7 +482,7 @@ private: ++__begin; if (__begin == __end) - __throw_format_error("End of input while parsing format-spec precision"); + std::__throw_format_error("End of input while parsing format-spec precision"); if (*__begin == _CharT('{')) { __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); @@ -466,7 +493,7 @@ private: } if (*__begin < _CharT('0') || *__begin > _CharT('9')) - __throw_format_error("The format-spec precision field doesn't contain a value or arg-id"); + std::__throw_format_error("The format-spec precision field doesn't contain a value or arg-id"); __format::__parse_number_result __r = __format::__parse_number(__begin, __end); __precision_ = __r.__value; @@ -878,7 +905,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_ // unit is non-ASCII we omit the current code unit and let the Grapheme // clustering algorithm do its work. const _CharT* __it = __str.begin(); - if (__is_ascii(*__it)) { + if (__format_spec::__is_ascii(*__it)) { do { --__maximum; ++__it; @@ -886,12 +913,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_ return {__str.size(), __str.end()}; if (__maximum == 0) { - if (__is_ascii(*__it)) + if (__format_spec::__is_ascii(*__it)) return {static_cast<size_t>(__it - __str.begin()), __it}; break; } - } while (__is_ascii(*__it)); + } while (__format_spec::__is_ascii(*__it)); --__it; ++__maximum; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/range_default_formatter.h b/contrib/libs/cxxsupp/libcxx/include/__format/range_default_formatter.h new file mode 100644 index 0000000000..774887b053 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__format/range_default_formatter.h @@ -0,0 +1,201 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H +#define _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__availability> +#include <__chrono/statically_widen.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/formatter.h> +#include <__format/range_formatter.h> +#include <__ranges/concepts.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/pair.h> +#include <string_view> +#include <tuple> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +template <class _Rp, class _CharT> +concept __const_formattable_range = + ranges::input_range<const _Rp> && formattable<ranges::range_reference_t<const _Rp>, _CharT>; + +template <class _Rp, class _CharT> +using __fmt_maybe_const = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; + +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") +_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") +// This shadows map, set, and string. +enum class range_format { disabled, map, set, sequence, string, debug_string }; +_LIBCPP_DIAGNOSTIC_POP + +// There is no definition of this struct, it's purely intended to be used to +// generate diagnostics. +template <class _Rp> +struct _LIBCPP_TEMPLATE_VIS __instantiated_the_primary_template_of_format_kind; + +template <class _Rp> +constexpr range_format format_kind = [] { + // [format.range.fmtkind]/1 + // A program that instantiates the primary template of format_kind is ill-formed. + static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); + return range_format::disabled; +}(); + +template <ranges::input_range _Rp> + requires same_as<_Rp, remove_cvref_t<_Rp>> +inline constexpr range_format format_kind<_Rp> = [] { + // [format.range.fmtkind]/2 + + // 2.1 If same_as<remove_cvref_t<ranges::range_reference_t<R>>, R> is true, + // Otherwise format_kind<R> is range_format::disabled. + if constexpr (same_as<remove_cvref_t<ranges::range_reference_t<_Rp>>, _Rp>) + return range_format::disabled; + // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: + else if constexpr (requires { typename _Rp::key_type; }) { + // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... + if constexpr (requires { typename _Rp::mapped_type; } && + // 2.2.1 ... If either U is a specialization of pair or U is a specialization + // of tuple and tuple_size_v<U> == 2 + __fmt_pair_like<remove_cvref_t<ranges::range_reference_t<_Rp>>>) + return range_format::map; + else + // 2.2.2 Otherwise format_kind<R> is range_format::set. + return range_format::set; + } else + // 2.3 Otherwise, format_kind<R> is range_format::sequence. + return range_format::sequence; +}(); + +// This is a non-standard work-around to fix instantiation of +// formatter<const _CharT[N], _CharT> +// const _CharT[N] satisfies the ranges::input_range concept. +// remove_cvref_t<const _CharT[N]> is _CharT[N] so it does not satisfy the +// requirement of the above specialization. Instead it will instantiate the +// primary template, which is ill-formed. +// +// An alternative solution is to remove the offending formatter. +// +// https://godbolt.org/z/bqjhhaexx +// +// The removal is proposed in LWG3833, but use the work-around until the issue +// has been adopted. +// TODO FMT Implement LWG3833. +template <class _CharT, size_t N> +inline constexpr range_format format_kind<const _CharT[N]> = range_format::disabled; + +template <range_format _Kp, ranges::input_range _Rp, class _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter; + +// Required specializations + +template <ranges::input_range _Rp, class _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<range_format::sequence, _Rp, _CharT> { +private: + using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>; + range_formatter<remove_cvref_t<ranges::range_reference_t<__maybe_const_r>>, _CharT> __underlying_; + +public: + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + __underlying_.set_separator(__separator); + } + _LIBCPP_HIDE_FROM_ABI constexpr void + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + __underlying_.set_brackets(__opening_bracket, __closing_bracket); + } + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template <class FormatContext> + _LIBCPP_HIDE_FROM_ABI typename FormatContext::iterator format(__maybe_const_r& __range, FormatContext& __ctx) const { + return __underlying_.format(__range, __ctx); + } +}; + +template <ranges::input_range _Rp, class _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<range_format::map, _Rp, _CharT> { +private: + using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>; + using __element_type = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>; + range_formatter<__element_type, _CharT> __underlying_; + +public: + _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() + requires(__fmt_pair_like<__element_type>) + { + __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); + __underlying_.underlying().set_brackets({}, {}); + __underlying_.underlying().set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); + } + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_map& __range, _FormatContext& __ctx) const { + return __underlying_.format(__range, __ctx); + } +}; + +template <ranges::input_range _Rp, class _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<range_format::set, _Rp, _CharT> { +private: + using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>; + using __element_type = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>; + range_formatter<__element_type, _CharT> __underlying_; + +public: + _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() { + __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); + } + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_set& __range, _FormatContext& __ctx) const { + return __underlying_.format(__range, __ctx); + } +}; + +template <range_format _Kp, ranges::input_range _Rp, class _CharT> + requires(_Kp == range_format::string || _Kp == range_format::debug_string) +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<_Kp, _Rp, _CharT> { + __range_default_formatter() = delete; // TODO FMT Implement +}; + +template <ranges::input_range _Rp, class _CharT> + requires(format_kind<_Rp> != range_format::disabled && formattable<ranges::range_reference_t<_Rp>, _CharT>) +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Rp, _CharT> + : __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/range_formatter.h b/contrib/libs/cxxsupp/libcxx/include/__format/range_formatter.h new file mode 100644 index 0000000000..9ea61a7035 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__format/range_formatter.h @@ -0,0 +1,255 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_RANGE_FORMATTER_H +#define _LIBCPP___FORMAT_RANGE_FORMATTER_H + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#include <__algorithm/ranges_copy.h> +#include <__availability> +#include <__chrono/statically_widen.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__format/buffer.h> +#include <__format/concepts.h> +#include <__format/format_args.h> +#include <__format/format_context.h> +#include <__format/format_error.h> +#include <__format/formatter.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__iterator/back_insert_iterator.h> +#include <__ranges/concepts.h> +#include <__ranges/data.h> +#include <__ranges/size.h> +#include <__type_traits/remove_cvref.h> +#include <string_view> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 + +template <class _Tp, class _CharT = char> + requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + __separator_ = __separator; + } + _LIBCPP_HIDE_FROM_ABI constexpr void + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + __opening_bracket_ = __opening_bracket; + __closing_bracket_ = __closing_bracket; + } + + _LIBCPP_HIDE_FROM_ABI constexpr formatter<_Tp, _CharT>& underlying() { return __underlying_; } + _LIBCPP_HIDE_FROM_ABI constexpr const formatter<_Tp, _CharT>& underlying() const { return __underlying_; } + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { + const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_range); + const _CharT* __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + // The n field overrides a possible m type, therefore delay applying the + // effect of n until the type has been procesed. + bool __clear_brackets = (*__begin == _CharT('n')); + if (__clear_brackets) { + ++__begin; + if (__begin == __end) { + // Since there is no more data, clear the brackets before returning. + set_brackets({}, {}); + return __begin; + } + } + + __parse_type(__begin, __end); + if (__clear_brackets) + set_brackets({}, {}); + if (__begin == __end) + return __begin; + + bool __has_range_underlying_spec = *__begin == _CharT(':'); + if (__parser_.__type_ != __format_spec::__type::__default) { + // [format.range.formatter]/6 + // If the range-type is s or ?s, then there shall be no n option and no + // range-underlying-spec. + if (__clear_brackets) { + if (__parser_.__type_ == __format_spec::__type::__string) + std::__throw_format_error("The n option and type s can't be used together"); + std::__throw_format_error("The n option and type ?s can't be used together"); + } + if (__has_range_underlying_spec) { + if (__parser_.__type_ == __format_spec::__type::__string) + std::__throw_format_error("Type s and an underlying format specification can't be used together"); + std::__throw_format_error("Type ?s and an underlying format specification can't be used together"); + } + } else if (!__has_range_underlying_spec) + std::__set_debug_format(__underlying_); + + if (__has_range_underlying_spec) { + // range-underlying-spec: + // : format-spec + ++__begin; + if (__begin == __end) + return __begin; + + __parse_ctx.advance_to(__begin); + __begin = __underlying_.parse(__parse_ctx); + } + + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + template <ranges::input_range _Rp, class _FormatContext> + requires formattable<ranges::range_reference_t<_Rp>, _CharT> && + same_as<remove_cvref_t<ranges::range_reference_t<_Rp>>, _Tp> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_Rp&& __range, _FormatContext& __ctx) const { + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + + if (!__specs.__has_width()) + return __format_range(__range, __ctx, __specs); + + // The size of the buffer needed is: + // - open bracket characters + // - close bracket character + // - n elements where every element may have a different size + // - (n -1) separators + // The size of the element is hard to predict, knowing the type helps but + // it depends on the format-spec. As an initial estimate we guess 6 + // characters. + // Typically both brackets are 1 character and the separator is 2 + // characters. Which means there will be + // (n - 1) * 2 + 1 + 1 = n * 2 character + // So estimate 8 times the range size as buffer. + std::size_t __capacity_hint = 0; + if constexpr (std::ranges::sized_range<_Rp>) + __capacity_hint = 8 * ranges::size(__range); + __format::__retarget_buffer<_CharT> __buffer{__capacity_hint}; + basic_format_context<typename __format::__retarget_buffer<_CharT>::__iterator, _CharT> __c{ + __buffer.__make_output_iterator(), __ctx}; + + __format_range(__range, __c, __specs); + + return __formatter::__write_string_no_precision(__buffer.__view(), __ctx.out(), __specs); + } + + template <ranges::input_range _Rp, class _FormatContext> + typename _FormatContext::iterator _LIBCPP_HIDE_FROM_ABI + __format_range(_Rp&& __range, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) const { + if constexpr (same_as<_Tp, _CharT>) { + switch (__specs.__std_.__type_) { + case __format_spec::__type::__string: + case __format_spec::__type::__debug: + return __format_as_string(__range, __ctx, __specs.__std_.__type_ == __format_spec::__type::__debug); + default: + return __format_as_sequence(__range, __ctx); + } + } else + return __format_as_sequence(__range, __ctx); + } + + template <ranges::input_range _Rp, class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + __format_as_string(_Rp&& __range, _FormatContext& __ctx, bool __debug_format) const { + // When the range is contiguous use a basic_string_view instead to avoid a + // copy of the underlying data. The basic_string_view formatter + // specialization is the "basic" string formatter in libc++. + if constexpr (ranges::contiguous_range<_Rp> && std::ranges::sized_range<_Rp>) { + std::formatter<basic_string_view<_CharT>, _CharT> __formatter; + if (__debug_format) + __formatter.set_debug_format(); + return __formatter.format( + basic_string_view<_CharT>{ + ranges::data(__range), + ranges::size(__range), + }, + __ctx); + } else { + std::formatter<basic_string<_CharT>, _CharT> __formatter; + if (__debug_format) + __formatter.set_debug_format(); + // P2106's from_range has not been implemented yet. Instead use a simple + // copy operation. + // TODO FMT use basic_string's "from_range" constructor. + // return std::formatter<basic_string<_CharT>, _CharT>{}.format(basic_string<_CharT>{from_range, __range}, __ctx); + basic_string<_CharT> __str; + ranges::copy(__range, back_insert_iterator{__str}); + return __formatter.format(__str, __ctx); + } + } + + template <ranges::input_range _Rp, class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + __format_as_sequence(_Rp&& __range, _FormatContext& __ctx) const { + __ctx.advance_to(ranges::copy(__opening_bracket_, __ctx.out()).out); + bool __use_separator = false; + for (auto&& __e : __range) { + if (__use_separator) + __ctx.advance_to(ranges::copy(__separator_, __ctx.out()).out); + else + __use_separator = true; + + __ctx.advance_to(__underlying_.format(__e, __ctx)); + } + + return ranges::copy(__closing_bracket_, __ctx.out()).out; + } + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; + +private: + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin, const _CharT* __end) { + switch (*__begin) { + case _CharT('m'): + if constexpr (__fmt_pair_like<_Tp>) { + set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); + set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ", ")); + ++__begin; + } else + std::__throw_format_error("The range-format-spec type m requires two elements for a pair or tuple"); + break; + + case _CharT('s'): + if constexpr (same_as<_Tp, _CharT>) { + __parser_.__type_ = __format_spec::__type::__string; + ++__begin; + } else + std::__throw_format_error("The range-format-spec type s requires formatting a character type"); + break; + + case _CharT('?'): + ++__begin; + if (__begin == __end || *__begin != _CharT('s')) + std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + if constexpr (same_as<_Tp, _CharT>) { + __parser_.__type_ = __format_spec::__type::__debug; + ++__begin; + } else + std::__throw_format_error("The range-format-spec type ?s requires formatting a character type"); + } + } + + formatter<_Tp, _CharT> __underlying_; + basic_string_view<_CharT> __separator_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ", "); + basic_string_view<_CharT> __opening_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "["); + basic_string_view<_CharT> __closing_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "]"); +}; + +#endif //_LIBCPP_STD_VER > 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_RANGE_FORMATTER_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__format/unicode.h b/contrib/libs/cxxsupp/libcxx/include/__format/unicode.h index fdcaff8407..4327258760 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__format/unicode.h +++ b/contrib/libs/cxxsupp/libcxx/include/__format/unicode.h @@ -13,6 +13,7 @@ #include <__assert> #include <__config> #include <__format/extended_grapheme_cluster_table.h> +#include <__type_traits/make_unsigned.h> #include <__utility/unreachable.h> #include <bit> diff --git a/contrib/libs/cxxsupp/libcxx/include/__functional/function.h b/contrib/libs/cxxsupp/libcxx/include/__functional/function.h index 2d9cdc0459..9f92f61814 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__functional/function.h +++ b/contrib/libs/cxxsupp/libcxx/include/__functional/function.h @@ -23,6 +23,7 @@ #include <__memory/builtin_new_allocator.h> #include <__memory/compressed_pair.h> #include <__memory/unique_ptr.h> +#include <__type_traits/strip_signature.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> @@ -261,16 +262,16 @@ class __base<_Rp(_ArgTypes...)> __base& operator=(const __base&); public: _LIBCPP_INLINE_VISIBILITY __base() {} - _LIBCPP_INLINE_VISIBILITY virtual ~__base() {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~__base() {} virtual __base* __clone() const = 0; virtual void __clone(__base*) const = 0; virtual void destroy() _NOEXCEPT = 0; virtual void destroy_deallocate() _NOEXCEPT = 0; virtual _Rp operator()(_ArgTypes&& ...) = 0; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(const type_info&) const _NOEXCEPT = 0; virtual const std::type_info& target_type() const _NOEXCEPT = 0; -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; // __func implements __base for a given functor type. @@ -304,10 +305,10 @@ public: virtual void destroy() _NOEXCEPT; virtual void destroy_deallocate() _NOEXCEPT; virtual _Rp operator()(_ArgTypes&&... __arg); -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(const type_info&) const _NOEXCEPT; virtual const std::type_info& target_type() const _NOEXCEPT; -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> @@ -355,7 +356,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> const void* @@ -373,7 +374,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT return typeid(_Fp); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI // __value_func creates a value-type from a __func. @@ -381,7 +382,9 @@ template <class _Fp> class __value_func; template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> { + _LIBCPP_SUPPRESS_DEPRECATED_PUSH typename aligned_storage<3 * sizeof(void*)>::type __buf_; + _LIBCPP_SUPPRESS_DEPRECATED_POP typedef __base<_Rp(_ArgTypes...)> __func; __func* __f_; @@ -514,7 +517,9 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> return; if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_) { + _LIBCPP_SUPPRESS_DEPRECATED_PUSH typename aligned_storage<sizeof(__buf_)>::type __tempbuf; + _LIBCPP_SUPPRESS_DEPRECATED_POP __func* __t = __as_base(&__tempbuf); __f_->__clone(__t); __f_->destroy(); @@ -548,7 +553,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI _LIBCPP_INLINE_VISIBILITY const std::type_info& target_type() const _NOEXCEPT { @@ -564,7 +569,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> return nullptr; return (const _Tp*)__f_->target(typeid(_Tp)); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; // Storage for a functor object, to be used with __policy to manage copy and @@ -611,7 +616,7 @@ struct __policy { static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, true, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(void) #else nullptr @@ -637,7 +642,7 @@ struct __policy __choose_policy(/* is_small = */ false_type) { static const _LIBCPP_CONSTEXPR __policy __policy_ = { &__large_clone<_Fun>, &__large_destroy<_Fun>, false, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) #else nullptr @@ -652,7 +657,7 @@ struct __policy { static const _LIBCPP_CONSTEXPR __policy __policy_ = { nullptr, nullptr, false, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) #else nullptr @@ -856,7 +861,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> return !__policy_->__is_null; } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI _LIBCPP_INLINE_VISIBILITY const std::type_info& target_type() const _NOEXCEPT { @@ -873,7 +878,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> else return reinterpret_cast<const _Tp*>(&__buf_.__small); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) @@ -940,7 +945,7 @@ public: return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(type_info const& __ti) const _NOEXCEPT { if (__ti == typeid(__func::__block_type)) return &__f_; @@ -950,7 +955,7 @@ public: virtual const std::type_info& target_type() const _NOEXCEPT { return typeid(__func::__block_type); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #endif // _LIBCPP_HAS_EXTENSION_BLOCKS @@ -1051,57 +1056,18 @@ public: // function invocation: _Rp operator()(_ArgTypes...) const; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI // function target access: const std::type_info& target_type() const _NOEXCEPT; template <typename _Tp> _Tp* target() _NOEXCEPT; template <typename _Tp> const _Tp* target() const _NOEXCEPT; -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #if _LIBCPP_STD_VER >= 17 template<class _Rp, class ..._Ap> function(_Rp(*)(_Ap...)) -> function<_Rp(_Ap...)>; -template<class _Fp> -struct __strip_signature; - -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); }; - -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); }; - -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); }; - -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; -template<class _Rp, class _Gp, class ..._Ap> -struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); }; - template<class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type> function(_Fp) -> function<_Stripped>; #endif // _LIBCPP_STD_VER >= 17 @@ -1190,7 +1156,7 @@ function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Rp, class ..._ArgTypes> const std::type_info& @@ -1215,7 +1181,7 @@ function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT return __f_.template target<_Tp>(); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template <class _Rp, class... _ArgTypes> inline _LIBCPP_INLINE_VISIBILITY diff --git a/contrib/libs/cxxsupp/libcxx/include/__functional/hash.h b/contrib/libs/cxxsupp/libcxx/include/__functional/hash.h index 041730dfb6..39382aa9bf 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__functional/hash.h +++ b/contrib/libs/cxxsupp/libcxx/include/__functional/hash.h @@ -10,9 +10,15 @@ #define _LIBCPP___FUNCTIONAL_HASH_H #include <__config> +#include <__functional/invoke.h> #include <__functional/unary_function.h> #include <__fwd/hash.h> -#include <__tuple/sfinae_helpers.h> +#include <__tuple_dir/sfinae_helpers.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_enum.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/underlying_type.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -21,7 +27,6 @@ #include <cstdint> #include <cstring> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -63,7 +68,7 @@ __murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) const unsigned char* __data = static_cast<const unsigned char*>(__key); for (; __len >= 4; __data += 4, __len -= 4) { - _Size __k = __loadword<_Size>(__data); + _Size __k = std::__loadword<_Size>(__data); __k *= __m; __k ^= __k >> __r; __k *= __m; @@ -128,14 +133,18 @@ struct __murmur2_or_cityhash<_Size, 64> _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { if (__len > 8) { - const _Size __a = __loadword<_Size>(__s); - const _Size __b = __loadword<_Size>(__s + __len - 8); + const _Size __a = std::__loadword<_Size>(__s); + const _Size __b = std::__loadword<_Size>(__s + __len - 8); return __hash_len_16(__a, __rotate_by_at_least_1(__b + __len, __len)) ^ __b; } if (__len >= 4) { - const uint32_t __a = __loadword<uint32_t>(__s); - const uint32_t __b = __loadword<uint32_t>(__s + __len - 4); + const uint32_t __a = std::__loadword<uint32_t>(__s); + const uint32_t __b = std::__loadword<uint32_t>(__s + __len - 4); +#ifdef _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION return __hash_len_16(__len + (static_cast<_Size>(__a) << 3), __b); +#else + return __hash_len_16(__len + (__a << 3), __b); +#endif } if (__len > 0) { const unsigned char __a = static_cast<unsigned char>(__s[0]); @@ -152,10 +161,10 @@ struct __murmur2_or_cityhash<_Size, 64> static _Size __hash_len_17_to_32(const char *__s, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { - const _Size __a = __loadword<_Size>(__s) * __k1; - const _Size __b = __loadword<_Size>(__s + 8); - const _Size __c = __loadword<_Size>(__s + __len - 8) * __k2; - const _Size __d = __loadword<_Size>(__s + __len - 16) * __k0; + const _Size __a = std::__loadword<_Size>(__s) * __k1; + const _Size __b = std::__loadword<_Size>(__s + 8); + const _Size __c = std::__loadword<_Size>(__s + __len - 8) * __k2; + const _Size __d = std::__loadword<_Size>(__s + __len - 16) * __k0; return __hash_len_16(__rotate(__a - __b, 43) + __rotate(__c, 30) + __d, __a + __rotate(__b ^ __k3, 20) - __c + __len); } @@ -180,10 +189,10 @@ struct __murmur2_or_cityhash<_Size, 64> const char* __s, _Size __a, _Size __b) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { - return __weak_hash_len_32_with_seeds(__loadword<_Size>(__s), - __loadword<_Size>(__s + 8), - __loadword<_Size>(__s + 16), - __loadword<_Size>(__s + 24), + return __weak_hash_len_32_with_seeds(std::__loadword<_Size>(__s), + std::__loadword<_Size>(__s + 8), + std::__loadword<_Size>(__s + 16), + std::__loadword<_Size>(__s + 24), __a, __b); } @@ -192,23 +201,23 @@ struct __murmur2_or_cityhash<_Size, 64> static _Size __hash_len_33_to_64(const char *__s, size_t __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { - _Size __z = __loadword<_Size>(__s + 24); - _Size __a = __loadword<_Size>(__s) + - (__len + __loadword<_Size>(__s + __len - 16)) * __k0; + _Size __z = std::__loadword<_Size>(__s + 24); + _Size __a = std::__loadword<_Size>(__s) + + (__len + std::__loadword<_Size>(__s + __len - 16)) * __k0; _Size __b = __rotate(__a + __z, 52); _Size __c = __rotate(__a, 37); - __a += __loadword<_Size>(__s + 8); + __a += std::__loadword<_Size>(__s + 8); __c += __rotate(__a, 7); - __a += __loadword<_Size>(__s + 16); + __a += std::__loadword<_Size>(__s + 16); _Size __vf = __a + __z; _Size __vs = __b + __rotate(__a, 31) + __c; - __a = __loadword<_Size>(__s + 16) + __loadword<_Size>(__s + __len - 32); - __z += __loadword<_Size>(__s + __len - 8); + __a = std::__loadword<_Size>(__s + 16) + std::__loadword<_Size>(__s + __len - 32); + __z += std::__loadword<_Size>(__s + __len - 8); __b = __rotate(__a + __z, 52); __c = __rotate(__a, 37); - __a += __loadword<_Size>(__s + __len - 24); + __a += std::__loadword<_Size>(__s + __len - 24); __c += __rotate(__a, 7); - __a += __loadword<_Size>(__s + __len - 16); + __a += std::__loadword<_Size>(__s + __len - 16); _Size __wf = __a + __z; _Size __ws = __b + __rotate(__a, 31) + __c; _Size __r = __shift_mix((__vf + __ws) * __k2 + (__wf + __vs) * __k0); @@ -234,26 +243,26 @@ __murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len) // For strings over 64 bytes we hash the end first, and then as we // loop we keep 56 bytes of state: v, w, x, y, and z. - _Size __x = __loadword<_Size>(__s + __len - 40); - _Size __y = __loadword<_Size>(__s + __len - 16) + - __loadword<_Size>(__s + __len - 56); - _Size __z = __hash_len_16(__loadword<_Size>(__s + __len - 48) + __len, - __loadword<_Size>(__s + __len - 24)); + _Size __x = std::__loadword<_Size>(__s + __len - 40); + _Size __y = std::__loadword<_Size>(__s + __len - 16) + + std::__loadword<_Size>(__s + __len - 56); + _Size __z = __hash_len_16(std::__loadword<_Size>(__s + __len - 48) + __len, + std::__loadword<_Size>(__s + __len - 24)); pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); - __x = __x * __k1 + __loadword<_Size>(__s); + __x = __x * __k1 + std::__loadword<_Size>(__s); // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. __len = (__len - 1) & ~static_cast<_Size>(63); do { - __x = __rotate(__x + __y + __v.first + __loadword<_Size>(__s + 8), 37) * __k1; - __y = __rotate(__y + __v.second + __loadword<_Size>(__s + 48), 42) * __k1; + __x = __rotate(__x + __y + __v.first + std::__loadword<_Size>(__s + 8), 37) * __k1; + __y = __rotate(__y + __v.second + std::__loadword<_Size>(__s + 48), 42) * __k1; __x ^= __w.second; - __y += __v.first + __loadword<_Size>(__s + 40); + __y += __v.first + std::__loadword<_Size>(__s + 40); __z = __rotate(__z + __w.first, 33) * __k1; __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, - __y + __loadword<_Size>(__s + 16)); + __y + std::__loadword<_Size>(__s + 16)); _VSTD::swap(__z, __x); __s += 64; __len -= 64; diff --git a/contrib/libs/cxxsupp/libcxx/include/__functional/invoke.h b/contrib/libs/cxxsupp/libcxx/include/__functional/invoke.h index fdbbce029e..48e6eac3ce 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__functional/invoke.h +++ b/contrib/libs/cxxsupp/libcxx/include/__functional/invoke.h @@ -398,7 +398,7 @@ template <class _Ret, class _Fp, class ..._Args> struct __invokable_r { template <class _XFp, class ..._XArgs> - static decltype(std::__invoke(declval<_XFp>(), declval<_XArgs>()...)) __try_call(int); + static decltype(std::__invoke(std::declval<_XFp>(), std::declval<_XArgs>()...)) __try_call(int); template <class _XFp, class ..._XArgs> static __nat __try_call(...); @@ -428,15 +428,23 @@ struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...> template <class _Tp> static void __test_noexcept(_Tp) _NOEXCEPT; +#ifdef _LIBCPP_CXX03_LANG + static const bool value = false; +#else static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>( - _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...))); + _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...))); +#endif }; template <class _Ret, class _Fp, class ..._Args> struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...> { +#ifdef _LIBCPP_CXX03_LANG + static const bool value = false; +#else static const bool value = noexcept( - _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...)); + _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...)); +#endif }; template <class _Ret, class _Fp, class ..._Args> diff --git a/contrib/libs/cxxsupp/libcxx/include/__functional/reference_wrapper.h b/contrib/libs/cxxsupp/libcxx/include/__functional/reference_wrapper.h index 6659825818..c377b64377 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__functional/reference_wrapper.h +++ b/contrib/libs/cxxsupp/libcxx/include/__functional/reference_wrapper.h @@ -11,10 +11,13 @@ #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H #include <__config> +#include <__functional/invoke.h> #include <__functional/weak_result_type.h> #include <__memory/addressof.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -35,9 +38,9 @@ private: static void __fun(_Tp&&) = delete; public: - template <class _Up, class = __enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, decltype(__fun(declval<_Up>())) > > + template <class _Up, class = __enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, decltype(__fun(std::declval<_Up>())) > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 - reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(declval<_Up>()))) { + reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(std::declval<_Up>()))) { type& __f = static_cast<_Up&&>(__u); __f_ = _VSTD::addressof(__f); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__functional/unwrap_ref.h b/contrib/libs/cxxsupp/libcxx/include/__functional/unwrap_ref.h index f7207934e1..da000d80b8 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__functional/unwrap_ref.h +++ b/contrib/libs/cxxsupp/libcxx/include/__functional/unwrap_ref.h @@ -10,6 +10,7 @@ #define _LIBCPP___FUNCTIONAL_UNWRAP_REF_H #include <__config> +#include <__type_traits/decay.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__functional/weak_result_type.h b/contrib/libs/cxxsupp/libcxx/include/__functional/weak_result_type.h index 96d8cf7146..18d1bf718c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__functional/weak_result_type.h +++ b/contrib/libs/cxxsupp/libcxx/include/__functional/weak_result_type.h @@ -12,8 +12,11 @@ #include <__config> #include <__functional/binary_function.h> +#include <__functional/invoke.h> #include <__functional/unary_function.h> -#include <type_traits> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__utility/declval.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -283,7 +286,7 @@ struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> template <class _Tp, class ..._Args> struct __invoke_return { - typedef decltype(_VSTD::__invoke(declval<_Tp>(), declval<_Args>()...)) type; + typedef decltype(_VSTD::__invoke(std::declval<_Tp>(), std::declval<_Args>()...)) type; }; _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__fwd/get.h b/contrib/libs/cxxsupp/libcxx/include/__fwd/get.h index 8162403898..ec1fab4602 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__fwd/get.h +++ b/contrib/libs/cxxsupp/libcxx/include/__fwd/get.h @@ -9,11 +9,13 @@ #ifndef _LIBCPP___FWD_GET_H #define _LIBCPP___FWD_GET_H +#include <__concepts/copyable.h> #include <__config> #include <__fwd/array.h> #include <__fwd/pair.h> +#include <__fwd/subrange.h> #include <__fwd/tuple.h> -#include <__tuple/tuple_element.h> +#include <__tuple_dir/tuple_element.h> #include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -90,6 +92,24 @@ const _Tp&& get(const array<_Tp, _Size>&&) _NOEXCEPT; #endif +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> + requires((_Index == 0 && copyable<_Iter>) || _Index == 1) +_LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange); + +template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> + requires(_Index < 2) +_LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange); + +} // namespace ranges + +using ranges::get; + +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FWD_GET_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__fwd/subrange.h b/contrib/libs/cxxsupp/libcxx/include/__fwd/subrange.h new file mode 100644 index 0000000000..8f7239247e --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__fwd/subrange.h @@ -0,0 +1,38 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_SUBRANGE_H +#define _LIBCPP___FWD_SUBRANGE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +#include <__iterator/concepts.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized }; + +template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent, subrange_kind _Kind> + requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) +class _LIBCPP_TEMPLATE_VIS subrange; + +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___FWD_SUBRANGE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__hash_table b/contrib/libs/cxxsupp/libcxx/include/__hash_table index d6af75e9e0..f8896c8664 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__hash_table +++ b/contrib/libs/cxxsupp/libcxx/include/__hash_table @@ -13,7 +13,7 @@ #include <__algorithm/max.h> #include <__algorithm/min.h> #include <__assert> -#include <__bits> // __libcpp_clz +#include <__bit/countl.h> #include <__config> #include <__debug> #include <__functional/hash.h> @@ -565,7 +565,7 @@ public: _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment a non-incrementable unordered container local_iterator"); __node_ = __node_->__next_; - if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) + if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; return *this; } @@ -698,7 +698,7 @@ public: _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), "Attempted to increment a non-incrementable unordered container const_local_iterator"); __node_ = __node_->__next_; - if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) + if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; return *this; } @@ -1156,11 +1156,11 @@ public: _LIBCPP_INLINE_VISIBILITY void __rehash_multi(size_type __n) { __rehash<false>(__n); } _LIBCPP_INLINE_VISIBILITY void __reserve_unique(size_type __n) { - __rehash_unique(static_cast<size_type>(ceil(__n / max_load_factor()))); + __rehash_unique(static_cast<size_type>(std::ceil(__n / max_load_factor()))); } _LIBCPP_INLINE_VISIBILITY void __reserve_multi(size_type __n) { - __rehash_multi(static_cast<size_type>(ceil(__n / max_load_factor()))); + __rehash_multi(static_cast<size_type>(std::ceil(__n / max_load_factor()))); } _LIBCPP_INLINE_VISIBILITY @@ -1184,7 +1184,7 @@ public: { _LIBCPP_ASSERT(bucket_count() > 0, "unordered container::bucket(key) called when bucket_count() == 0"); - return __constrain_hash(hash_function()(__k), bucket_count()); + return std::__constrain_hash(hash_function()(__k), bucket_count()); } template <class _Key> @@ -1433,7 +1433,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) { if (size() > 0) { - __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr(); __u.__p1_.first().__next_ = nullptr; __u.size() = 0; @@ -1457,7 +1457,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, { __p1_.first().__next_ = __u.__p1_.first().__next_; __u.__p1_.first().__next_ = nullptr; - __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr(); size() = __u.size(); __u.size() = 0; @@ -1574,7 +1574,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __p1_.first().__next_ = __u.__p1_.first().__next_; if (size() > 0) { - __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr(); __u.__p1_.first().__next_ = nullptr; __u.size() = 0; @@ -1789,12 +1789,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare( if (__bc != 0) { - size_t __chash = __constrain_hash(__hash, __bc); + size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __ndptr = __bucket_list_[__chash]; if (__ndptr != nullptr) { for (__ndptr = __ndptr->__next_; __ndptr != nullptr && - __constrain_hash(__ndptr->__hash(), __bc) == __chash; + std::__constrain_hash(__ndptr->__hash(), __bc) == __chash; __ndptr = __ndptr->__next_) { if (key_eq()(__ndptr->__upcast()->__value_, __value)) @@ -1804,8 +1804,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare( } if (size()+1 > __bc * max_load_factor() || __bc == 0) { - __rehash_unique(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), - size_type(ceil(float(size() + 1) / max_load_factor())))); + __rehash_unique(_VSTD::max<size_type>(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); } return nullptr; } @@ -1821,7 +1821,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform( __node_pointer __nd) _NOEXCEPT { size_type __bc = bucket_count(); - size_t __chash = __constrain_hash(__nd->__hash(), __bc); + size_t __chash = std::__constrain_hash(__nd->__hash(), __bc); // insert_after __bucket_list_[__chash], or __first_node if bucket is null __next_pointer __pn = __bucket_list_[__chash]; if (__pn == nullptr) @@ -1832,7 +1832,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform( // fix up __bucket_list_ __bucket_list_[__chash] = __pn; if (__nd->__next_ != nullptr) - __bucket_list_[__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr(); + __bucket_list_[std::__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr(); } else { @@ -1876,16 +1876,16 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare( size_type __bc = bucket_count(); if (size()+1 > __bc * max_load_factor() || __bc == 0) { - __rehash_multi(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), - size_type(ceil(float(size() + 1) / max_load_factor())))); + __rehash_multi(_VSTD::max<size_type>(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); } - size_t __chash = __constrain_hash(__cp_hash, __bc); + size_t __chash = std::__constrain_hash(__cp_hash, __bc); __next_pointer __pn = __bucket_list_[__chash]; if (__pn != nullptr) { for (bool __found = false; __pn->__next_ != nullptr && - __constrain_hash(__pn->__next_->__hash(), __bc) == __chash; + std::__constrain_hash(__pn->__next_->__hash(), __bc) == __chash; __pn = __pn->__next_) { // __found key_eq() action @@ -1917,7 +1917,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform( __node_pointer __cp, __next_pointer __pn) _NOEXCEPT { size_type __bc = bucket_count(); - size_t __chash = __constrain_hash(__cp->__hash_, __bc); + size_t __chash = std::__constrain_hash(__cp->__hash_, __bc); if (__pn == nullptr) { __pn =__p1_.first().__ptr(); @@ -1926,7 +1926,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform( // fix up __bucket_list_ __bucket_list_[__chash] = __pn; if (__cp->__next_ != nullptr) - __bucket_list_[__constrain_hash(__cp->__next_->__hash(), __bc)] + __bucket_list_[std::__constrain_hash(__cp->__next_->__hash(), __bc)] = __cp->__ptr(); } else @@ -1935,7 +1935,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform( __pn->__next_ = __cp->__ptr(); if (__cp->__next_ != nullptr) { - size_t __nhash = __constrain_hash(__cp->__next_->__hash(), __bc); + size_t __nhash = std::__constrain_hash(__cp->__next_->__hash(), __bc); if (__nhash != __chash) __bucket_list_[__nhash] = __cp->__ptr(); } @@ -1970,11 +1970,11 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( size_type __bc = bucket_count(); if (size()+1 > __bc * max_load_factor() || __bc == 0) { - __rehash_multi(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), - size_type(ceil(float(size() + 1) / max_load_factor())))); + __rehash_multi(_VSTD::max<size_type>(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); } - size_t __chash = __constrain_hash(__cp->__hash_, __bc); + size_t __chash = std::__constrain_hash(__cp->__hash_, __bc); __next_pointer __pp = __bucket_list_[__chash]; while (__pp->__next_ != __np) __pp = __pp->__next_; @@ -2001,12 +2001,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& size_t __chash; if (__bc != 0) { - __chash = __constrain_hash(__hash, __bc); + __chash = std::__constrain_hash(__hash, __bc); __nd = __bucket_list_[__chash]; if (__nd != nullptr) { for (__nd = __nd->__next_; __nd != nullptr && - (__nd->__hash() == __hash || __constrain_hash(__nd->__hash(), __bc) == __chash); + (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash); __nd = __nd->__next_) { if (key_eq()(__nd->__upcast()->__value_, __k)) @@ -2018,10 +2018,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...); if (size()+1 > __bc * max_load_factor() || __bc == 0) { - __rehash_unique(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), - size_type(ceil(float(size() + 1) / max_load_factor())))); + __rehash_unique(_VSTD::max<size_type>(2 * __bc + !std::__is_hash_power2(__bc), + size_type(std::ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); - __chash = __constrain_hash(__hash, __bc); + __chash = std::__constrain_hash(__hash, __bc); } // insert_after __bucket_list_[__chash], or __first_node if bucket is null __next_pointer __pn = __bucket_list_[__chash]; @@ -2033,7 +2033,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& // fix up __bucket_list_ __bucket_list_[__chash] = __pn; if (__h->__next_ != nullptr) - __bucket_list_[__constrain_hash(__h->__next_->__hash(), __bc)] + __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr(); } else @@ -2229,7 +2229,7 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK if (__n == 1) __n = 2; else if (__n & (__n - 1)) - __n = __next_prime(__n); + __n = std::__next_prime(__n); size_type __bc = bucket_count(); if (__n > __bc) __do_rehash<_UniqueKeys>(__n); @@ -2238,8 +2238,8 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __n = _VSTD::max<size_type> ( __n, - __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) : - __next_prime(size_t(ceil(float(size()) / max_load_factor()))) + std::__is_hash_power2(__bc) ? std::__next_hash_pow2(size_t(std::ceil(float(size()) / max_load_factor()))) : + std::__next_prime(size_t(std::ceil(float(size()) / max_load_factor()))) ); if (__n < __bc) __do_rehash<_UniqueKeys>(__n); @@ -2264,13 +2264,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) __next_pointer __cp = __pp->__next_; if (__cp != nullptr) { - size_type __chash = __constrain_hash(__cp->__hash(), __nbc); + size_type __chash = std::__constrain_hash(__cp->__hash(), __nbc); __bucket_list_[__chash] = __pp; size_type __phash = __chash; for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) { - __chash = __constrain_hash(__cp->__hash(), __nbc); + __chash = std::__constrain_hash(__cp->__hash(), __nbc); if (__chash == __phash) __pp = __cp; else @@ -2312,13 +2312,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) size_type __bc = bucket_count(); if (__bc != 0) { - size_t __chash = __constrain_hash(__hash, __bc); + size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { for (__nd = __nd->__next_; __nd != nullptr && (__nd->__hash() == __hash - || __constrain_hash(__nd->__hash(), __bc) == __chash); + || std::__constrain_hash(__nd->__hash(), __bc) == __chash); __nd = __nd->__next_) { if ((__nd->__hash() == __hash) @@ -2339,13 +2339,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const size_type __bc = bucket_count(); if (__bc != 0) { - size_t __chash = __constrain_hash(__hash, __bc); + size_t __chash = std::__constrain_hash(__hash, __bc); __next_pointer __nd = __bucket_list_[__chash]; if (__nd != nullptr) { for (__nd = __nd->__next_; __nd != nullptr && (__hash == __nd->__hash() - || __constrain_hash(__nd->__hash(), __bc) == __chash); + || std::__constrain_hash(__nd->__hash(), __bc) == __chash); __nd = __nd->__next_) { if ((__nd->__hash() == __hash) @@ -2467,7 +2467,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT // current node __next_pointer __cn = __p.__node_; size_type __bc = bucket_count(); - size_t __chash = __constrain_hash(__cn->__hash(), __bc); + size_t __chash = std::__constrain_hash(__cn->__hash(), __bc); // find previous node __next_pointer __pn = __bucket_list_[__chash]; for (; __pn->__next_ != __cn; __pn = __pn->__next_) @@ -2476,16 +2476,16 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT // if __pn is not in same bucket (before begin is not in same bucket) && // if __cn->__next_ is not in same bucket (nullptr is not in same bucket) if (__pn == __p1_.first().__ptr() - || __constrain_hash(__pn->__hash(), __bc) != __chash) + || std::__constrain_hash(__pn->__hash(), __bc) != __chash) { if (__cn->__next_ == nullptr - || __constrain_hash(__cn->__next_->__hash(), __bc) != __chash) + || std::__constrain_hash(__cn->__next_->__hash(), __bc) != __chash) __bucket_list_[__chash] = nullptr; } // if __cn->__next_ is not in same bucket (nullptr is in same bucket) if (__cn->__next_ != nullptr) { - size_t __nhash = __constrain_hash(__cn->__next_->__hash(), __bc); + size_t __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc); if (__nhash != __chash) __bucket_list_[__nhash] = __pn; } @@ -2639,10 +2639,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) __p2_.swap(__u.__p2_); __p3_.swap(__u.__p3_); if (size() > 0) - __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = + __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr(); if (__u.size() > 0) - __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] = + __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] = __u.__p1_.first().__ptr(); std::__debug_db_swap(this, std::addressof(__u)); } @@ -2659,8 +2659,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const if (__np != nullptr) { for (__np = __np->__next_; __np != nullptr && - __constrain_hash(__np->__hash(), __bc) == __n; - __np = __np->__next_, (void) ++__r) + std::__constrain_hash(__np->__hash(), __bc) == __n; + __np = __np->__next_, (void) ++__r) ; } return __r; diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/advance.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/advance.h index e43e41873a..870778061b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/advance.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/advance.h @@ -17,12 +17,14 @@ #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_integral.h> #include <__utility/convert_to_integral.h> +#include <__utility/declval.h> #include <__utility/move.h> #include <__utility/unreachable.h> #include <cstdlib> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -56,7 +58,7 @@ void __advance(_RandIter& __i, typename iterator_traits<_RandIter>::difference_t template < class _InputIter, class _Distance, - class _IntegralDistance = decltype(_VSTD::__convert_to_integral(declval<_Distance>())), + class _IntegralDistance = decltype(_VSTD::__convert_to_integral(std::declval<_Distance>())), class = __enable_if_t<is_integral<_IntegralDistance>::value> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void advance(_InputIter& __i, _Distance __orig_n) { diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/bounded_iter.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/bounded_iter.h index 071cbdac99..96d311faa3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/bounded_iter.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/bounded_iter.h @@ -14,8 +14,10 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_convertible.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h index a1985c9287..f7883e2c37 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/common_iterator.h @@ -25,6 +25,8 @@ #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> +#include <__type_traits/is_pointer.h> +#include <__utility/declval.h> #include <variant> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -101,14 +103,14 @@ public: constexpr decltype(auto) operator*() { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } constexpr decltype(auto) operator*() const requires __dereferenceable<const _Iter> { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } @@ -119,7 +121,7 @@ public: is_reference_v<iter_reference_t<_I2>> || constructible_from<iter_value_t<_I2>, iter_reference_t<_I2>>) { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) { return _VSTD::__unchecked_get<_Iter>(__hold_); } else if constexpr (is_reference_v<iter_reference_t<_Iter>>) { @@ -131,12 +133,12 @@ public: } common_iterator& operator++() { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); ++_VSTD::__unchecked_get<_Iter>(__hold_); return *this; } decltype(auto) operator++(int) { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); if constexpr (forward_iterator<_Iter>) { auto __tmp = *this; ++*this; @@ -215,19 +217,19 @@ public: } _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i) - noexcept(noexcept(ranges::iter_move(declval<const _Iter&>()))) + noexcept(noexcept(ranges::iter_move(std::declval<const _Iter&>()))) requires input_iterator<_Iter> { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_iterator"); return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_)); } template<indirectly_swappable<_Iter> _I2, class _S2> _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) - noexcept(noexcept(ranges::iter_swap(declval<const _Iter&>(), declval<const _I2&>()))) + noexcept(noexcept(ranges::iter_swap(std::declval<const _Iter&>(), std::declval<const _I2&>()))) { - _LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); - _LIBCPP_ASSERT(holds_alternative<_I2>(__y.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT(std::holds_alternative<_I2>(__y.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); return ranges::iter_swap(_VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_I2>(__y.__hold_)); } }; @@ -255,7 +257,7 @@ struct __arrow_type_or_void { template<class _Iter, class _Sent> requires __common_iter_has_ptr_op<_Iter, _Sent> struct __arrow_type_or_void<_Iter, _Sent> { - using type = decltype(declval<const common_iterator<_Iter, _Sent>&>().operator->()); + using type = decltype(std::declval<const common_iterator<_Iter, _Sent>&>().operator->()); }; template<input_iterator _Iter, class _Sent> diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/concepts.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/concepts.h index 246f84c7cf..d9d40a4249 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/concepts.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/concepts.h @@ -26,13 +26,19 @@ #include <__concepts/semiregular.h> #include <__concepts/totally_ordered.h> #include <__config> +#include <__functional/invoke.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iter_move.h> #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> #include <__memory/pointer_traits.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/counted_iterator.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/counted_iterator.h index 5edd9c9422..5fdbff4b48 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/counted_iterator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/counted_iterator.h @@ -25,9 +25,10 @@ #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> #include <__memory/pointer_traits.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/conditional.h> #include <__utility/move.h> #include <compare> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/distance.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/distance.h index 32e41331f6..681e20d045 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/distance.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/distance.h @@ -17,7 +17,8 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/size.h> -#include <type_traits> +#include <__type_traits/decay.h> +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/incrementable_traits.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/incrementable_traits.h index 6f966ec4c7..3d06dc0535 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/incrementable_traits.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/incrementable_traits.h @@ -12,9 +12,13 @@ #include <__concepts/arithmetic.h> #include <__config> +#include <__type_traits/conditional.h> +#include <__type_traits/is_object.h> #include <__type_traits/is_primary_template.h> +#include <__type_traits/make_signed.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -53,7 +57,7 @@ concept __has_integral_minus = template<__has_integral_minus _Tp> requires (!__has_member_difference_type<_Tp>) struct incrementable_traits<_Tp> { - using difference_type = make_signed_t<decltype(declval<_Tp>() - declval<_Tp>())>; + using difference_type = make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>; }; template <class> diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_move.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_move.h index d8240ab9c2..a7d9413fb8 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_move.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_move.h @@ -13,9 +13,11 @@ #include <__concepts/class_or_enum.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -36,6 +38,7 @@ template <class _Tp> concept __unqualified_iter_move = __class_or_enum<remove_cvref_t<_Tp>> && requires (_Tp&& __t) { + // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap iter_move(std::forward<_Tp>(__t)); }; @@ -59,6 +62,7 @@ concept __just_deref = // [iterator.cust.move] struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) iter_move ADL calls should only be made through ranges::iter_move template<class _Ip> requires __unqualified_iter_move<_Ip> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Ip&& __i) const @@ -66,6 +70,7 @@ struct __fn { { return iter_move(std::forward<_Ip>(__i)); } + // NOLINTEND(libcpp-robust-against-adl) template<class _Ip> requires __move_deref<_Ip> @@ -90,7 +95,7 @@ inline namespace __cpo { template<__dereferenceable _Tp> requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __can_reference; } -using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<_Tp&>())); +using iter_rvalue_reference_t = decltype(ranges::iter_move(std::declval<_Tp&>())); #endif // _LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_swap.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_swap.h index 78152e2d9a..d4c0dca1f6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_swap.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/iter_swap.h @@ -17,9 +17,10 @@ #include <__iterator/iter_move.h> #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -40,6 +41,7 @@ namespace __iter_swap { concept __unqualified_iter_swap = (__class_or_enum<remove_cvref_t<_T1>> || __class_or_enum<remove_cvref_t<_T2>>) && requires (_T1&& __x, _T2&& __y) { + // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); }; @@ -48,7 +50,9 @@ namespace __iter_swap { indirectly_readable<_T1> && indirectly_readable<_T2> && swappable_with<iter_reference_t<_T1>, iter_reference_t<_T2>>; + struct __fn { + // NOLINTBEGIN(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap template <class _T1, class _T2> requires __unqualified_iter_swap<_T1, _T2> _LIBCPP_HIDE_FROM_ABI @@ -57,6 +61,7 @@ namespace __iter_swap { { (void)iter_swap(_VSTD::forward<_T1>(__x), _VSTD::forward<_T2>(__y)); } + // NOLINTEND(libcpp-robust-against-adl) template <class _T1, class _T2> requires (!__unqualified_iter_swap<_T1, _T2>) && @@ -77,7 +82,7 @@ namespace __iter_swap { constexpr void operator()(_T1&& __x, _T2&& __y) const noexcept(noexcept(iter_value_t<_T2>(ranges::iter_move(__y))) && noexcept(*__y = ranges::iter_move(__x)) && - noexcept(*_VSTD::forward<_T1>(__x) = declval<iter_value_t<_T2>>())) + noexcept(*_VSTD::forward<_T1>(__x) = std::declval<iter_value_t<_T2>>())) { iter_value_t<_T2> __old(ranges::iter_move(__y)); *__y = ranges::iter_move(__x); diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_traits.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_traits.h index b4cf072332..c9d8944bfe 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_traits.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_traits.h @@ -21,8 +21,21 @@ #include <__fwd/pair.h> #include <__iterator/incrementable_traits.h> #include <__iterator/readable_traits.h> +#include <__type_traits/add_const.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/conditional.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_primary_template.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_valid_expansion.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -47,7 +60,7 @@ concept __dereferenceable = requires(_Tp& __t) { // [iterator.traits] template<__dereferenceable _Tp> -using iter_reference_t = decltype(*declval<_Tp&>()); +using iter_reference_t = decltype(*std::declval<_Tp&>()); #endif // _LIBCPP_STD_VER > 17 @@ -260,7 +273,7 @@ struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { using type = typ template<class _Ip> requires requires(_Ip& __i) { __i.operator->(); } && (!__has_member_pointer<_Ip>) struct __iterator_traits_member_pointer_or_arrow_or_void<_Ip> { - using type = decltype(declval<_Ip&>().operator->()); + using type = decltype(std::declval<_Ip&>().operator->()); }; // Otherwise, `reference` names `iter-reference-t<I>`. diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_with_data.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_with_data.h new file mode 100644 index 0000000000..06c2fa699c --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/iterator_with_data.h @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ITERATOR_WITH_DATA_H +#define _LIBCPP___ITERATOR_ITERATOR_WITH_DATA_H + +#include <__compare/compare_three_way_result.h> +#include <__compare/three_way_comparable.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <forward_iterator _Iterator, class _Data> +class __iterator_with_data { + _Iterator __iter_{}; + _Data __data_{}; + +public: + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + + _LIBCPP_HIDE_FROM_ABI __iterator_with_data() = default; + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data(_Iterator __iter, _Data __data) + : __iter_(std::move(__iter)), __data_(std::move(__data)) {} + + constexpr _LIBCPP_HIDE_FROM_ABI _Iterator __get_iter() const { return __iter_; } + + constexpr _LIBCPP_HIDE_FROM_ABI _Data __get_data() && { return std::move(__data_); } + + friend constexpr _LIBCPP_HIDE_FROM_ABI bool + operator==(const __iterator_with_data& __lhs, const __iterator_with_data& __rhs) { + return __lhs.__iter_ == __rhs.__iter_; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data& operator++() { + ++__iter_; + return *this; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data operator++(int) { + auto __tmp = *this; + __iter_++; + return __tmp; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data& operator--() + requires bidirectional_iterator<_Iterator> + { + --__iter_; + return *this; + } + + constexpr _LIBCPP_HIDE_FROM_ABI __iterator_with_data operator--(int) + requires bidirectional_iterator<_Iterator> + { + auto __tmp = *this; + --__iter_; + return __tmp; + } + + constexpr _LIBCPP_HIDE_FROM_ABI iter_reference_t<_Iterator> operator*() const { return *__iter_; } + + _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const __iterator_with_data& __iter) noexcept(noexcept(ranges::iter_move(__iter.__iter_))) { + return ranges::iter_move(__iter.__iter_); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr void + iter_swap(const __iterator_with_data& __lhs, + const __iterator_with_data& __rhs) noexcept(noexcept(ranges::iter_swap(__lhs.__iter_, __rhs.__iter_))) + requires indirectly_swappable<_Iterator> + { + return ranges::iter_swap(__lhs.__data_, __rhs.__iter_); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___ITERATOR_ITERATOR_WITH_DATA_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/move_iterator.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/move_iterator.h index b4f2f9ec3d..fa806dbaf7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/move_iterator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/move_iterator.h @@ -24,8 +24,16 @@ #include <__iterator/iterator_traits.h> #include <__iterator/move_sentinel.h> #include <__iterator/readable_traits.h> +#include <__type_traits/conditional.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -49,7 +57,7 @@ struct __move_iter_category_base<_Iter> { template<class _Iter, class _Sent> concept __move_iter_comparable = requires { - { declval<const _Iter&>() == declval<_Sent>() } -> convertible_to<bool>; + { std::declval<const _Iter&>() == std::declval<_Sent>() } -> convertible_to<bool>; }; #endif // _LIBCPP_STD_VER > 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/move_sentinel.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/move_sentinel.h index 5adf877b34..0d7336a1dc 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/move_sentinel.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/move_sentinel.h @@ -50,6 +50,8 @@ private: _Sent __last_ = _Sent(); }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_sentinel); + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/next.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/next.h index 13de2f3f73..44e129e106 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/next.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/next.h @@ -16,7 +16,7 @@ #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> -#include <type_traits> +#include <__type_traits/enable_if.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/prev.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/prev.h index a1d0bc0dbb..cdd1b8ecf6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/prev.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/prev.h @@ -16,7 +16,7 @@ #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> -#include <type_traits> +#include <__type_traits/enable_if.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/projected.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/projected.h index 3a08b58b8b..19c076b2e5 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/projected.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/projected.h @@ -13,7 +13,7 @@ #include <__config> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> -#include <type_traits> +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/readable_traits.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/readable_traits.h index dc818d8a23..8f17757c5a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/readable_traits.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/readable_traits.h @@ -12,7 +12,13 @@ #include <__concepts/same_as.h> #include <__config> -#include <type_traits> +#include <__type_traits/conditional.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_primary_template.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_extent.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/reverse_iterator.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/reverse_iterator.h index 2933a29fc8..f272e03c17 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/reverse_iterator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/reverse_iterator.h @@ -25,12 +25,20 @@ #include <__iterator/next.h> #include <__iterator/prev.h> #include <__iterator/readable_traits.h> +#include <__iterator/segmented_iterator.h> #include <__memory/addressof.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/subrange.h> +#include <__type_traits/conditional.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <__utility/declval.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -177,7 +185,7 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const reverse_iterator& __i) noexcept(is_nothrow_copy_constructible_v<_Iter> && - noexcept(ranges::iter_move(--declval<_Iter&>()))) { + noexcept(ranges::iter_move(--std::declval<_Iter&>()))) { auto __tmp = __i.base(); return ranges::iter_move(--__tmp); } @@ -187,7 +195,7 @@ public: void iter_swap(const reverse_iterator& __x, const reverse_iterator<_Iter2>& __y) noexcept(is_nothrow_copy_constructible_v<_Iter> && is_nothrow_copy_constructible_v<_Iter2> && - noexcept(ranges::iter_swap(--declval<_Iter&>(), --declval<_Iter2&>()))) { + noexcept(ranges::iter_swap(--std::declval<_Iter&>(), --std::declval<_Iter2&>()))) { auto __xtmp = __x.base(); auto __ytmp = __y.base(); ranges::iter_swap(--__xtmp, --__ytmp); @@ -195,12 +203,6 @@ public: #endif // _LIBCPP_STD_VER > 17 }; -template <class _Iter> -struct __is_reverse_iterator : false_type {}; - -template <class _Iter> -struct __is_reverse_iterator<reverse_iterator<_Iter> > : true_type {}; - template <class _Iter1, class _Iter2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool @@ -394,7 +396,7 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const __unconstrained_reverse_iterator& __i) noexcept(is_nothrow_copy_constructible_v<_Iter> && - noexcept(ranges::iter_move(--declval<_Iter&>()))) { + noexcept(ranges::iter_move(--std::declval<_Iter&>()))) { auto __tmp = __i.base(); return ranges::iter_move(--__tmp); } @@ -478,9 +480,6 @@ public: } }; -template <class _Iter> -struct __is_reverse_iterator<__unconstrained_reverse_iterator<_Iter>> : true_type {}; - #endif // _LIBCPP_STD_VER <= 17 template <template <class> class _RevIter1, template <class> class _RevIter2, class _Iter> diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/segmented_iterator.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/segmented_iterator.h new file mode 100644 index 0000000000..c0a77ef1c4 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/segmented_iterator.h @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___SEGMENTED_ITERATOR_H +#define _LIBCPP___SEGMENTED_ITERATOR_H + +// Segmented iterators are iterators over (not necessarily contiguous) sub-ranges. +// +// For example, std::deque stores its data into multiple blocks of contiguous memory, +// which are not stored contiguously themselves. The concept of segmented iterators +// allows algorithms to operate over these multi-level iterators natively, opening the +// door to various optimizations. See http://lafstern.org/matt/segmented.pdf for details. +// +// If __segmented_iterator_traits can be instantiated, the following functions and associated types must be provided: +// - Traits::__local_iterator +// The type of iterators used to iterate inside a segment. +// +// - Traits::__segment_iterator +// The type of iterators used to iterate over segments. +// Segment iterators can be forward iterators or bidirectional iterators, depending on the +// underlying data structure. +// +// - static __segment_iterator Traits::__segment(It __it) +// Returns an iterator to the segment that the provided iterator is in. +// +// - static __local_iterator Traits::__local(It __it) +// Returns the local iterator pointing to the element that the provided iterator points to. +// +// - static __local_iterator Traits::__begin(__segment_iterator __it) +// Returns the local iterator to the beginning of the segment that the provided iterator is pointing into. +// +// - static __local_iterator Traits::__end(__segment_iterator __it) +// Returns the one-past-the-end local iterator to the segment that the provided iterator is pointing into. +// +// - static It Traits::__compose(__segment_iterator, __local_iterator) +// Returns the iterator composed of the segment iterator and local iterator. + +#include <__config> +#include <__type_traits/integral_constant.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Iterator> +struct __segmented_iterator_traits; +/* exposition-only: +{ + using __segment_iterator = ...; + using __local_iterator = ...; + + static __segment_iterator __segment(_Iterator); + static __local_iterator __local(_Iterator); + static __local_iterator __begin(__segment_iterator); + static __local_iterator __end(__segment_iterator); + static _Iterator __compose(__segment_iterator, __local_iterator); +}; +*/ + +template <class _Tp, size_t = 0> +struct __has_specialization : false_type {}; + +#ifndef __CUDACC__ +template <class _Tp> +struct __has_specialization<_Tp, sizeof(_Tp) * 0> : true_type {}; +#endif + +template <class _Iterator> +using __is_segmented_iterator = __has_specialization<__segmented_iterator_traits<_Iterator> >; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SEGMENTED_ITERATOR_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/size.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/size.h index e060134966..1452bd1d55 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/size.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/size.h @@ -11,8 +11,9 @@ #define _LIBCPP___ITERATOR_SIZE_H #include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/make_signed.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__iterator/wrap_iter.h b/contrib/libs/cxxsupp/libcxx/include/__iterator/wrap_iter.h index 80be74ef58..16defc1d8b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__iterator/wrap_iter.h +++ b/contrib/libs/cxxsupp/libcxx/include/__iterator/wrap_iter.h @@ -15,7 +15,8 @@ #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> #include <__memory/pointer_traits.h> -#include <type_traits> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__locale b/contrib/libs/cxxsupp/libcxx/include/__locale index 0fe43dcb3e..334a8fd052 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__locale +++ b/contrib/libs/cxxsupp/libcxx/include/__locale @@ -841,7 +841,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isspace(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c); } template <class _CharT> @@ -849,7 +849,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isprint(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::print, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::print, __c); } template <class _CharT> @@ -857,7 +857,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool iscntrl(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::cntrl, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::cntrl, __c); } template <class _CharT> @@ -865,7 +865,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isupper(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::upper, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::upper, __c); } template <class _CharT> @@ -873,7 +873,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool islower(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::lower, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::lower, __c); } template <class _CharT> @@ -881,7 +881,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isalpha(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c); } template <class _CharT> @@ -889,7 +889,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isdigit(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::digit, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::digit, __c); } template <class _CharT> @@ -897,7 +897,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool ispunct(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::punct, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::punct, __c); } template <class _CharT> @@ -905,7 +905,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isxdigit(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::xdigit, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::xdigit, __c); } template <class _CharT> @@ -913,7 +913,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isalnum(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alnum, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::alnum, __c); } template <class _CharT> @@ -921,7 +921,7 @@ inline _LIBCPP_INLINE_VISIBILITY bool isgraph(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c); + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c); } template <class _CharT> @@ -929,7 +929,7 @@ inline _LIBCPP_INLINE_VISIBILITY _CharT toupper(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).toupper(__c); + return std::use_facet<ctype<_CharT> >(__loc).toupper(__c); } template <class _CharT> @@ -937,7 +937,7 @@ inline _LIBCPP_INLINE_VISIBILITY _CharT tolower(_CharT __c, const locale& __loc) { - return use_facet<ctype<_CharT> >(__loc).tolower(__c); + return std::use_facet<ctype<_CharT> >(__loc).tolower(__c); } // codecvt_base diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/allocate_at_least.h b/contrib/libs/cxxsupp/libcxx/include/__memory/allocate_at_least.h index 7ce588a25d..ef205f855c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/allocate_at_least.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/allocate_at_least.h @@ -25,6 +25,7 @@ struct allocation_result { _Pointer ptr; size_t count; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result); template <class _Alloc> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/allocator.h b/contrib/libs/cxxsupp/libcxx/include/__memory/allocator.h index 7a930959a1..54c9b78d52 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/allocator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/allocator.h @@ -13,11 +13,14 @@ #include <__config> #include <__memory/allocate_at_least.h> #include <__memory/allocator_traits.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_void.h> +#include <__type_traits/is_volatile.h> #include <__utility/forward.h> #include <cstddef> #include <new> #include <stdexcept> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_arg_t.h b/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_arg_t.h index 44df046ed7..15f8c98c4c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_arg_t.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_arg_t.h @@ -12,8 +12,10 @@ #include <__config> #include <__memory/uses_allocator.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_traits.h b/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_traits.h index 6acc14aa23..3a23b47c74 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_traits.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/allocator_traits.h @@ -13,9 +13,16 @@ #include <__config> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_empty.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_reference.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -180,7 +187,7 @@ struct __has_allocate_hint : false_type { }; template <class _Alloc, class _SizeType, class _ConstVoidPtr> struct __has_allocate_hint<_Alloc, _SizeType, _ConstVoidPtr, decltype( - (void)declval<_Alloc>().allocate(declval<_SizeType>(), declval<_ConstVoidPtr>()) + (void)std::declval<_Alloc>().allocate(std::declval<_SizeType>(), std::declval<_ConstVoidPtr>()) )> : true_type { }; // __has_construct @@ -189,7 +196,7 @@ struct __has_construct_impl : false_type { }; template <class _Alloc, class ..._Args> struct __has_construct_impl<decltype( - (void)declval<_Alloc>().construct(declval<_Args>()...) + (void)std::declval<_Alloc>().construct(std::declval<_Args>()...) ), _Alloc, _Args...> : true_type { }; template <class _Alloc, class ..._Args> @@ -201,7 +208,7 @@ struct __has_destroy : false_type { }; template <class _Alloc, class _Pointer> struct __has_destroy<_Alloc, _Pointer, decltype( - (void)declval<_Alloc>().destroy(declval<_Pointer>()) + (void)std::declval<_Alloc>().destroy(std::declval<_Pointer>()) )> : true_type { }; // __has_max_size @@ -210,7 +217,7 @@ struct __has_max_size : false_type { }; template <class _Alloc> struct __has_max_size<_Alloc, decltype( - (void)declval<_Alloc&>().max_size() + (void)std::declval<_Alloc&>().max_size() )> : true_type { }; // __has_select_on_container_copy_construction @@ -219,7 +226,7 @@ struct __has_select_on_container_copy_construction : false_type { }; template <class _Alloc> struct __has_select_on_container_copy_construction<_Alloc, decltype( - (void)declval<_Alloc>().select_on_container_copy_construction() + (void)std::declval<_Alloc>().select_on_container_copy_construction() )> : true_type { }; _LIBCPP_SUPPRESS_DEPRECATED_POP diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/assume_aligned.h b/contrib/libs/cxxsupp/libcxx/include/__memory/assume_aligned.h index 0f12fb11fd..a1fd2441f9 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/assume_aligned.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/assume_aligned.h @@ -12,9 +12,9 @@ #include <__assert> #include <__config> +#include <__type_traits/is_constant_evaluated.h> #include <cstddef> #include <cstdint> -#include <type_traits> // for is_constant_evaluated() #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/compressed_pair.h b/contrib/libs/cxxsupp/libcxx/include/__memory/compressed_pair.h index 9dd42f8d6e..8093d7c931 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/compressed_pair.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/compressed_pair.h @@ -13,12 +13,19 @@ #include <__config> #include <__fwd/get.h> #include <__fwd/tuple.h> -#include <__tuple/tuple_indices.h> +#include <__tuple_dir/tuple_indices.h> +#include <__type_traits/decay.h> #include <__type_traits/dependent_type.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_empty.h> +#include <__type_traits/is_final.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/concepts.h b/contrib/libs/cxxsupp/libcxx/include/__memory/concepts.h index 76d2a2e729..12d7bf85ed 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/concepts.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/concepts.h @@ -17,7 +17,8 @@ #include <__iterator/readable_traits.h> #include <__ranges/access.h> #include <__ranges/concepts.h> -#include <type_traits> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/construct_at.h b/contrib/libs/cxxsupp/libcxx/include/__memory/construct_at.h index a11a6ebe44..14484dd6aa 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/construct_at.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/construct_at.h @@ -15,10 +15,12 @@ #include <__iterator/access.h> #include <__memory/addressof.h> #include <__memory/voidify.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_array.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> #include <new> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,7 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 -template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))> +template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))> _LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) { _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at"); return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...); @@ -38,7 +40,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __ #endif -template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))> +template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Args&&... __args) { #if _LIBCPP_STD_VER > 17 return std::construct_at(__location, std::forward<_Args>(__args)...); @@ -81,6 +83,16 @@ _ForwardIterator __destroy(_ForwardIterator __first, _ForwardIterator __last) { return __first; } +template <class _BidirectionalIterator> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_BidirectionalIterator __reverse_destroy(_BidirectionalIterator __first, _BidirectionalIterator __last) { + while (__last != __first) { + --__last; + std::__destroy_at(std::addressof(*__last)); + } + return __last; +} + #if _LIBCPP_STD_VER > 14 template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0> diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/pointer_traits.h b/contrib/libs/cxxsupp/libcxx/include/__memory/pointer_traits.h index fd52647178..c4f20def45 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/pointer_traits.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/pointer_traits.h @@ -12,8 +12,15 @@ #include <__config> #include <__memory/addressof.h> +#include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_class.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_void.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -172,7 +179,7 @@ struct _HasToAddress : false_type {}; template <class _Pointer> struct _HasToAddress<_Pointer, - decltype((void)pointer_traits<_Pointer>::to_address(declval<const _Pointer&>())) + decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) > : true_type {}; template <class _Pointer, class = void> @@ -180,7 +187,7 @@ struct _HasArrow : false_type {}; template <class _Pointer> struct _HasArrow<_Pointer, - decltype((void)declval<const _Pointer&>().operator->()) + decltype((void)std::declval<const _Pointer&>().operator->()) > : true_type {}; template <class _Pointer> @@ -193,7 +200,7 @@ template <class _Pointer, class = __enable_if_t< _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -typename decay<decltype(__to_address_helper<_Pointer>::__call(declval<const _Pointer&>()))>::type +typename decay<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))>::type __to_address(const _Pointer& __p) _NOEXCEPT { return __to_address_helper<_Pointer>::__call(__p); } @@ -201,16 +208,16 @@ __to_address(const _Pointer& __p) _NOEXCEPT { template <class _Pointer, class> struct __to_address_helper { _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - static decltype(_VSTD::__to_address(declval<const _Pointer&>().operator->())) + static decltype(_VSTD::__to_address(std::declval<const _Pointer&>().operator->())) __call(const _Pointer& __p) _NOEXCEPT { return _VSTD::__to_address(__p.operator->()); } }; template <class _Pointer> -struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(declval<const _Pointer&>()))> { +struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))> { _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - static decltype(pointer_traits<_Pointer>::to_address(declval<const _Pointer&>())) + static decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) __call(const _Pointer& __p) _NOEXCEPT { return pointer_traits<_Pointer>::to_address(__p); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_construct_at.h b/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_construct_at.h index 19cd0ff7e8..e63585d1ab 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_construct_at.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_construct_at.h @@ -39,7 +39,7 @@ namespace __construct_at { struct __fn { template<class _Tp, class... _Args, class = decltype( - ::new (declval<void*>()) _Tp(declval<_Args>()...) + ::new (std::declval<void*>()) _Tp(std::declval<_Args>()...) )> _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator()(_Tp* __location, _Args&& ...__args) const { diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_uninitialized_algorithms.h b/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_uninitialized_algorithms.h index 7d2ac3af03..15c78e20ba 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_uninitialized_algorithms.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/ranges_uninitialized_algorithms.h @@ -23,9 +23,9 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> +#include <__type_traits/remove_reference.h> #include <__utility/move.h> #include <new> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -256,7 +256,7 @@ struct __fn { sentinel_for<_InputIterator> _Sentinel1, __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel2> - requires constructible_from<iter_value_t<_OutputIterator>, iter_reference_t<_InputIterator>> + requires constructible_from<iter_value_t<_OutputIterator>, iter_rvalue_reference_t<_InputIterator>> uninitialized_move_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, _Sentinel1 __ilast, _OutputIterator __ofirst, _Sentinel2 __olast) const { using _ValueType = remove_reference_t<iter_reference_t<_OutputIterator>>; @@ -267,7 +267,7 @@ struct __fn { } template <input_range _InputRange, __nothrow_forward_range _OutputRange> - requires constructible_from<range_value_t<_OutputRange>, range_reference_t<_InputRange>> + requires constructible_from<range_value_t<_OutputRange>, range_rvalue_reference_t<_InputRange>> uninitialized_move_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>> operator()(_InputRange&& __in_range, _OutputRange&& __out_range) const { return (*this)(ranges::begin(__in_range), ranges::end(__in_range), @@ -292,7 +292,7 @@ struct __fn { template <input_iterator _InputIterator, __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel> - requires constructible_from<iter_value_t<_OutputIterator>, iter_reference_t<_InputIterator>> + requires constructible_from<iter_value_t<_OutputIterator>, iter_rvalue_reference_t<_InputIterator>> uninitialized_move_n_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, iter_difference_t<_InputIterator> __n, _OutputIterator __ofirst, _Sentinel __olast) const { diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/shared_ptr.h b/contrib/libs/cxxsupp/libcxx/include/__memory/shared_ptr.h index bab8c8c15c..46c0534c3d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/shared_ptr.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/shared_ptr.h @@ -37,7 +37,6 @@ #include <iosfwd> #include <new> #include <stdexcept> -#include <type_traits> #include <typeinfo> #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) # include <atomic> @@ -246,7 +245,7 @@ public: __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a) : __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {} -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI const void* __get_deleter(const type_info&) const _NOEXCEPT override; #endif @@ -255,7 +254,7 @@ private: void __on_zero_shared_weak() _NOEXCEPT override; }; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template <class _Tp, class _Dp, class _Alloc> const void* @@ -264,7 +263,7 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) cons return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : nullptr; } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template <class _Tp, class _Dp, class _Alloc> void @@ -287,6 +286,11 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT __a.deallocate(_PTraits::pointer_to(*this), 1); } +// This tag is used to instantiate an allocator type. The various shared_ptr control blocks +// detect that the allocator has been instantiated for this type and perform alternative +// initialization/destruction based on that. +struct __for_overwrite_tag {}; + template <class _Tp, class _Alloc> struct __shared_ptr_emplace : __shared_weak_count @@ -296,10 +300,15 @@ struct __shared_ptr_emplace explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...__args) : __storage_(_VSTD::move(__a)) { -#if _LIBCPP_STD_VER > 17 - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; - _TpAlloc __tmp(*__get_alloc()); - allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + static_assert(sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite"); + ::new ((void*)__get_elem()) _Tp; + } else { + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + _TpAlloc __tmp(*__get_alloc()); + allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); + } #else ::new ((void*)__get_elem()) _Tp(_VSTD::forward<_Args>(__args)...); #endif @@ -314,9 +323,13 @@ struct __shared_ptr_emplace private: void __on_zero_shared() _NOEXCEPT override { #if _LIBCPP_STD_VER > 17 - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; - _TpAlloc __tmp(*__get_alloc()); - allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + __get_elem()->~_Tp(); + } else { + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + _TpAlloc __tmp(*__get_alloc()); + allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); + } #else __get_elem()->~_Tp(); #endif @@ -382,40 +395,84 @@ public: template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; -template<class _Tp, class _Up> +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.general-6 +// A pointer type Y* is said to be compatible with a pointer type T* +// when either Y* is convertible to T* or Y is U[N] and T is cv U[]. +#if _LIBCPP_STD_VER >= 17 +template <class _Yp, class _Tp> +struct __bounded_convertible_to_unbounded : false_type {}; + +template <class _Up, std::size_t _Np, class _Tp> +struct __bounded_convertible_to_unbounded<_Up[_Np], _Tp> + : is_same<__remove_cv_t<_Tp>, _Up[]> {}; + +template <class _Yp, class _Tp> struct __compatible_with -#if _LIBCPP_STD_VER > 14 - : is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {}; + : _Or< + is_convertible<_Yp*, _Tp*>, + __bounded_convertible_to_unbounded<_Yp, _Tp> + > {}; #else - : is_convertible<_Tp*, _Up*> {}; -#endif // _LIBCPP_STD_VER > 14 +template <class _Yp, class _Tp> +struct __compatible_with + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + +// Constructors that take raw pointers have a different set of "compatible" constraints +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.const-9.1 +// - If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, +// or T is U[] and Y(*)[] is convertible to T*. +// - If T is not an array type, then Y* is convertible to T*. +#if _LIBCPP_STD_VER >= 17 +template <class _Yp, class _Tp, class = void> +struct __raw_pointer_compatible_with : _And< + _Not<is_array<_Tp>>, + is_convertible<_Yp*, _Tp*> + > {}; + +template <class _Yp, class _Up, std::size_t _Np> +struct __raw_pointer_compatible_with<_Yp, _Up[_Np], __enable_if_t< + is_convertible<_Yp(*)[_Np], _Up(*)[_Np]>::value> > + : true_type {}; + +template <class _Yp, class _Up> +struct __raw_pointer_compatible_with<_Yp, _Up[], __enable_if_t< + is_convertible<_Yp(*)[], _Up(*)[]>::value> > + : true_type {}; + +#else +template <class _Yp, class _Tp> +struct __raw_pointer_compatible_with + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + template <class _Ptr, class = void> struct __is_deletable : false_type { }; template <class _Ptr> -struct __is_deletable<_Ptr, decltype(delete declval<_Ptr>())> : true_type { }; +struct __is_deletable<_Ptr, decltype(delete std::declval<_Ptr>())> : true_type { }; template <class _Ptr, class = void> struct __is_array_deletable : false_type { }; template <class _Ptr> -struct __is_array_deletable<_Ptr, decltype(delete[] declval<_Ptr>())> : true_type { }; +struct __is_array_deletable<_Ptr, decltype(delete[] std::declval<_Ptr>())> : true_type { }; template <class _Dp, class _Pt, - class = decltype(declval<_Dp>()(declval<_Pt>()))> + class = decltype(std::declval<_Dp>()(std::declval<_Pt>()))> static true_type __well_formed_deleter_test(int); template <class, class> static false_type __well_formed_deleter_test(...); template <class _Dp, class _Pt> -struct __well_formed_deleter : decltype(__well_formed_deleter_test<_Dp, _Pt>(0)) {}; +struct __well_formed_deleter : decltype(std::__well_formed_deleter_test<_Dp, _Pt>(0)) {}; -template<class _Dp, class _Tp, class _Yp> +template<class _Dp, class _Yp, class _Tp> struct __shared_ptr_deleter_ctor_reqs { - static const bool value = __compatible_with<_Tp, _Yp>::value && + static const bool value = __raw_pointer_compatible_with<_Yp, _Tp>::value && is_move_constructible<_Dp>::value && - __well_formed_deleter<_Dp, _Tp*>::value; + __well_formed_deleter<_Dp, _Yp*>::value; }; #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) @@ -454,7 +511,7 @@ public: template<class _Yp, class = __enable_if_t< _And< - __compatible_with<_Yp, _Tp> + __raw_pointer_compatible_with<_Yp, _Tp> // In C++03 we get errors when trying to do SFINAE with the // delete operator, so we always pretend that it's deletable. // The same happens on GCC. @@ -472,7 +529,7 @@ public: __enable_weak_this(__p, __p); } - template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> > + template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d) : __ptr_(__p) @@ -499,7 +556,7 @@ public: #endif // _LIBCPP_NO_EXCEPTIONS } - template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> > + template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d, _Alloc __a) : __ptr_(__p) @@ -661,6 +718,7 @@ public: template <class _Yp, class _Dp, class = __enable_if_t< !is_lvalue_reference<_Dp>::value && + __compatible_with<_Yp, _Tp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI @@ -683,6 +741,7 @@ public: template <class _Yp, class _Dp, class = void, class = __enable_if_t< is_lvalue_reference<_Dp>::value && + __compatible_with<_Yp, _Tp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI @@ -755,9 +814,10 @@ public: } #endif - template <class _Yp, class _Dp, class = __enable_if_t< - is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value - > > + template <class _Yp, class _Dp, class = __enable_if_t<_And< + __compatible_with<_Yp, _Tp>, + is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*> + >::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(unique_ptr<_Yp, _Dp>&& __r) { @@ -779,7 +839,7 @@ public: } template<class _Yp, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value + __raw_pointer_compatible_with<_Yp, _Tp>::value > > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p) @@ -788,8 +848,7 @@ public: } template<class _Yp, class _Dp, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d) { @@ -797,8 +856,7 @@ public: } template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d, _Alloc __a) { @@ -873,7 +931,7 @@ public: } #endif -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template <class _Dp> _LIBCPP_HIDE_FROM_ABI _Dp* __get_deleter() const _NOEXCEPT @@ -882,7 +940,7 @@ public: ? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp))) : nullptr); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template<class _Yp, class _CntrlBlk> _LIBCPP_HIDE_FROM_ABI @@ -972,6 +1030,26 @@ shared_ptr<_Tp> make_shared(_Args&& ...__args) return _VSTD::allocate_shared<_Tp>(allocator<_Tp>(), _VSTD::forward<_Args>(__args)...); } +#if _LIBCPP_STD_VER >= 20 + +template<class _Tp, class _Alloc, __enable_if_t<!is_array<_Tp>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI +shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) +{ + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::allocate_shared<_Tp>(__alloc); +} + +template<class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI +shared_ptr<_Tp> make_shared_for_overwrite() +{ + return std::allocate_shared_for_overwrite<_Tp>(allocator<_Tp>()); +} + +#endif // _LIBCPP_STD_VER >= 20 + #if _LIBCPP_STD_VER > 14 template <size_t _Alignment> @@ -992,14 +1070,24 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count, _Tp const& __arg) : __alloc_(__alloc), __count_(__count) { - std::__uninitialized_allocator_fill_n(__alloc_, std::begin(__data_), __count_, __arg); + std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::begin(__data_), __count_, __arg); } _LIBCPP_HIDE_FROM_ABI explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count) : __alloc_(__alloc), __count_(__count) { - std::__uninitialized_allocator_value_construct_n(__alloc_, std::begin(__data_), __count_); +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + // We are purposefully not using an allocator-aware default construction because the spec says so. + // There's currently no way of expressing default initialization in an allocator-aware manner anyway. + std::uninitialized_default_construct_n(std::begin(__data_), __count_); + } else { + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); + } +#else + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); +#endif } // Returns the number of bytes required to store a control block followed by the given number @@ -1018,13 +1106,22 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count return (__bytes + __align - 1) & ~(__align - 1); } - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~__unbounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_ private: void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + std::__reverse_destroy(__data_, __data_ + __count_); + } else { + __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); + std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); + } +#else __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); +#endif } void __on_zero_shared_weak() _NOEXCEPT override { @@ -1077,21 +1174,40 @@ struct __bounded_array_control_block<_Tp[_Count], _Alloc> _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc, _Tp const& __arg) : __alloc_(__alloc) { - std::__uninitialized_allocator_fill_n(__alloc_, std::addressof(__data_[0]), _Count, __arg); + std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count, __arg); } _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc) : __alloc_(__alloc) { - std::__uninitialized_allocator_value_construct_n(__alloc_, std::addressof(__data_[0]), _Count); +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + // We are purposefully not using an allocator-aware default construction because the spec says so. + // There's currently no way of expressing default initialization in an allocator-aware manner anyway. + std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count); + } else { + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); + } +#else + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); +#endif } - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~__bounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_ private: void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + std::__reverse_destroy(__data_, __data_ + _Count); + } else { + __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); + std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); + } +#else __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); +#endif } void __on_zero_shared_weak() _NOEXCEPT override { @@ -1128,6 +1244,7 @@ shared_ptr<_Array> __allocate_shared_bounded_array(const _Alloc& __a, _Arg&& ... #if _LIBCPP_STD_VER > 17 +// bounded array variants template<class _Tp, class _Alloc, class = __enable_if_t<is_bounded_array<_Tp>::value>> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a) @@ -1142,18 +1259,13 @@ shared_ptr<_Tp> allocate_shared(const _Alloc& __a, const remove_extent_t<_Tp>& _ return std::__allocate_shared_bounded_array<_Tp>(__a, __u); } -template<class _Tp, class _Alloc, class = __enable_if_t<is_unbounded_array<_Tp>::value>> -_LIBCPP_HIDE_FROM_ABI -shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n) -{ - return std::__allocate_shared_unbounded_array<_Tp>(__a, __n); -} - -template<class _Tp, class _Alloc, class = __enable_if_t<is_unbounded_array<_Tp>::value>> +template<class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI -shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n, const remove_extent_t<_Tp>& __u) +shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) { - return std::__allocate_shared_unbounded_array<_Tp>(__a, __n, __u); + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::__allocate_shared_bounded_array<_Tp>(__alloc); } template<class _Tp, class = __enable_if_t<is_bounded_array<_Tp>::value>> @@ -1170,6 +1282,37 @@ shared_ptr<_Tp> make_shared(const remove_extent_t<_Tp>& __u) return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>(), __u); } +template<class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI +shared_ptr<_Tp> make_shared_for_overwrite() +{ + return std::__allocate_shared_bounded_array<_Tp>(allocator<__for_overwrite_tag>()); +} + +// unbounded array variants +template<class _Tp, class _Alloc, class = __enable_if_t<is_unbounded_array<_Tp>::value>> +_LIBCPP_HIDE_FROM_ABI +shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n) +{ + return std::__allocate_shared_unbounded_array<_Tp>(__a, __n); +} + +template<class _Tp, class _Alloc, class = __enable_if_t<is_unbounded_array<_Tp>::value>> +_LIBCPP_HIDE_FROM_ABI +shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n, const remove_extent_t<_Tp>& __u) +{ + return std::__allocate_shared_unbounded_array<_Tp>(__a, __n, __u); +} + +template<class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI +shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a, size_t __n) +{ + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::__allocate_shared_unbounded_array<_Tp>(__alloc, __n); +} + template<class _Tp, class = __enable_if_t<is_unbounded_array<_Tp>::value>> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(size_t __n) @@ -1184,6 +1327,13 @@ shared_ptr<_Tp> make_shared(size_t __n, const remove_extent_t<_Tp>& __u) return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n, __u); } +template<class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI +shared_ptr<_Tp> make_shared_for_overwrite(size_t __n) +{ + return std::__allocate_shared_unbounded_array<_Tp>(allocator<__for_overwrite_tag>(), __n); +} + #endif // _LIBCPP_STD_VER > 17 template<class _Tp, class _Up> @@ -1407,7 +1557,7 @@ reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT typename shared_ptr<_Tp>::element_type*>(__r.get())); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Dp, class _Tp> inline _LIBCPP_INLINE_VISIBILITY @@ -1417,7 +1567,7 @@ get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT return __p.template __get_deleter<_Dp>(); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template<class _Tp> class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr @@ -1836,7 +1986,7 @@ _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p) { - __sp_mut& __m = __get_sp_mut(__p); + __sp_mut& __m = std::__get_sp_mut(__p); __m.lock(); shared_ptr<_Tp> __q = *__p; __m.unlock(); @@ -1849,7 +1999,7 @@ _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR shared_ptr<_Tp> atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order) { - return atomic_load(__p); + return std::atomic_load(__p); } template <class _Tp> @@ -1857,7 +2007,7 @@ _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR _LIBCPP_HIDE_FROM_ABI void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) { - __sp_mut& __m = __get_sp_mut(__p); + __sp_mut& __m = std::__get_sp_mut(__p); __m.lock(); __p->swap(__r); __m.unlock(); @@ -1869,7 +2019,7 @@ _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR void atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) { - atomic_store(__p, __r); + std::atomic_store(__p, __r); } template <class _Tp> @@ -1877,7 +2027,7 @@ _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) { - __sp_mut& __m = __get_sp_mut(__p); + __sp_mut& __m = std::__get_sp_mut(__p); __m.lock(); __p->swap(__r); __m.unlock(); @@ -1890,7 +2040,7 @@ _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR shared_ptr<_Tp> atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) { - return atomic_exchange(__p, __r); + return std::atomic_exchange(__p, __r); } template <class _Tp> @@ -1899,7 +2049,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) { shared_ptr<_Tp> __temp; - __sp_mut& __m = __get_sp_mut(__p); + __sp_mut& __m = std::__get_sp_mut(__p); __m.lock(); if (__p->__owner_equivalent(*__v)) { @@ -1920,7 +2070,7 @@ _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR bool atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) { - return atomic_compare_exchange_strong(__p, __v, __w); + return std::atomic_compare_exchange_strong(__p, __v, __w); } template <class _Tp> @@ -1930,7 +2080,7 @@ bool atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w, memory_order, memory_order) { - return atomic_compare_exchange_strong(__p, __v, __w); + return std::atomic_compare_exchange_strong(__p, __v, __w); } template <class _Tp> @@ -1940,7 +2090,7 @@ bool atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w, memory_order, memory_order) { - return atomic_compare_exchange_weak(__p, __v, __w); + return std::atomic_compare_exchange_weak(__p, __v, __w); } #endif // !defined(_LIBCPP_HAS_NO_THREADS) diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/uninitialized_algorithms.h b/contrib/libs/cxxsupp/libcxx/include/__memory/uninitialized_algorithms.h index 948774d53f..fa4881e0be 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/uninitialized_algorithms.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/uninitialized_algorithms.h @@ -20,12 +20,21 @@ #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__memory/voidify.h> +#include <__type_traits/extent.h> +#include <__type_traits/is_array.h> #include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_trivially_copy_assignable.h> +#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_move_assignable.h> +#include <__type_traits/is_trivially_move_constructible.h> +#include <__type_traits/is_unbounded_array.h> +#include <__type_traits/negation.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_extent.h> +#include <__utility/exception_guard.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <__utility/transaction.h> #include <new> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -284,7 +293,7 @@ template <class _ForwardIterator, class _Size> inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { using _ValueType = typename iterator_traits<_ForwardIterator>::value_type; - return __uninitialized_value_construct_n<_ValueType>(_VSTD::move(__first), __n); + return std::__uninitialized_value_construct_n<_ValueType>(_VSTD::move(__first), __n); } // uninitialized_move @@ -401,7 +410,7 @@ constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter // This function assumes that the allocator is bound to the correct type. template<class _Alloc, class _Tp> _LIBCPP_HIDE_FROM_ABI -constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { +constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) { static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, "The allocator should already be rebound to the correct type"); @@ -412,9 +421,12 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { _Tp& __array = *__loc; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); }); + auto __guard = std::__make_exception_guard([&]() { + std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); + }); + for (; __i != extent_v<_Tp>; ++__i) { - std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i])); + std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i])); } __guard.__complete(); } else { @@ -434,13 +446,13 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { // This function assumes that the allocator is bound to the correct type. template<class _Alloc, class _Tp, class _Arg> _LIBCPP_HIDE_FROM_ABI -constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { +constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, "The allocator should already be rebound to the correct type"); if constexpr (is_array_v<_Tp>) { static_assert(is_array_v<_Arg>, - "Provided non-array initialization argument to __allocator_construct_at when " + "Provided non-array initialization argument to __allocator_construct_at_multidimensional when " "trying to construct an array."); using _Element = remove_extent_t<_Tp>; @@ -449,9 +461,11 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& _Tp& __array = *__loc; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); }); + auto __guard = std::__make_exception_guard([&]() { + std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); + }); for (; __i != extent_v<_Tp>; ++__i) { - std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); + std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); } __guard.__complete(); } else { @@ -467,33 +481,33 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& // initialization using allocator_traits destruction. If the elements in the range are C-style // arrays, they are initialized element-wise using allocator construction, and recursively so. template<class _Alloc, class _BidirIter, class _Tp, class _Size = typename iterator_traits<_BidirIter>::difference_type> -_LIBCPP_HIDE_FROM_ABI -constexpr void __uninitialized_allocator_fill_n(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { +_LIBCPP_HIDE_FROM_ABI constexpr void +__uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { using _ValueType = typename iterator_traits<_BidirIter>::value_type; __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); _BidirIter __begin = __it; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); + auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { - std::__allocator_construct_at(__value_alloc, std::addressof(*__it), __value); + std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value); } __guard.__complete(); } -// Same as __uninitialized_allocator_fill_n, but doesn't pass any initialization argument +// Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument // to the allocator's construct method, which results in value initialization. -template<class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> -_LIBCPP_HIDE_FROM_ABI -constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _BidirIter __it, _Size __n) { +template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> +_LIBCPP_HIDE_FROM_ABI constexpr void +__uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) { using _ValueType = typename iterator_traits<_BidirIter>::value_type; __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); _BidirIter __begin = __it; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __transaction __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); + auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { - std::__allocator_construct_at(__value_alloc, std::addressof(*__it)); + std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it)); } __guard.__complete(); } @@ -532,21 +546,15 @@ private: template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { -#ifndef _LIBCPP_NO_EXCEPTIONS auto __destruct_first = __first2; - try { -#endif + auto __guard = + std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); while (__first1 != __last1) { allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), *__first1); ++__first1; ++__first2; } -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - _AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)(); - throw; - } -#endif + __guard.__complete(); return __first2; } @@ -590,10 +598,9 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_alloc _Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { static_assert(__is_cpp17_move_insertable<_Alloc>::value, "The specified type does not meet the requirements of Cpp17MoveInsertable"); -#ifndef _LIBCPP_NO_EXCEPTIONS auto __destruct_first = __first2; - try { -#endif + auto __guard = + std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); while (__first1 != __last1) { #ifndef _LIBCPP_NO_EXCEPTIONS allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1)); @@ -603,12 +610,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_alloc ++__first1; ++__first2; } -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - _AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)(); - throw; - } -#endif + __guard.__complete(); return __first2; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/unique_ptr.h b/contrib/libs/cxxsupp/libcxx/include/__memory/unique_ptr.h index 2230d934be..333691f715 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/unique_ptr.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/unique_ptr.h @@ -19,11 +19,27 @@ #include <__memory/allocator_traits.h> // __pointer #include <__memory/auto_ptr.h> #include <__memory/compressed_pair.h> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/common_type.h> +#include <__type_traits/dependent_type.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/is_void.h> +#include <__type_traits/remove_extent.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <__utility/move.h> #include <cstddef> #include <stlfwd> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -684,6 +700,25 @@ template<class _Tp, class... _Args> #endif // _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_single +make_unique_for_overwrite() { + return unique_ptr<_Tp>(new _Tp); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound +make_unique_for_overwrite(size_t __n) { + return unique_ptr<_Tp>(new __remove_extent_t<_Tp>[__n]); +} + +template<class _Tp, class... _Args> +typename __unique_if<_Tp>::__unique_array_known_bound make_unique_for_overwrite(_Args&&...) = delete; + +#endif // _LIBCPP_STD_VER >= 20 + template <class _Tp> struct _LIBCPP_TEMPLATE_VIS hash; template <class _Tp, class _Dp> diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator.h b/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator.h index 4a07a4a521..fe89704027 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator.h @@ -11,8 +11,8 @@ #define _LIBCPP___MEMORY_USES_ALLOCATOR_H #include <__config> +#include <__type_traits/is_convertible.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator_construction.h b/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator_construction.h index 02e0668d12..0f63b080da 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator_construction.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory/uses_allocator_construction.h @@ -14,6 +14,8 @@ #include <__memory/uses_allocator.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> +#include <__utility/declval.h> #include <__utility/pair.h> #include <tuple> diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/monotonic_buffer_resource.h b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/monotonic_buffer_resource.h index 5c35a62b16..5b0d246258 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/monotonic_buffer_resource.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/monotonic_buffer_resource.h @@ -69,7 +69,7 @@ public: : __res_(__upstream) { __initial_.__start_ = static_cast<char*>(__buffer); if (__buffer != nullptr) { - __initial_.__cur_ = static_cast<char*>(__buffer); + __initial_.__cur_ = static_cast<char*>(__buffer) + __buffer_size; __initial_.__end_ = static_cast<char*>(__buffer) + __buffer_size; } else { __initial_.__cur_ = nullptr; @@ -80,12 +80,13 @@ public: monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; - _LIBCPP_HIDE_FROM_ABI ~monotonic_buffer_resource() override { release(); } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~monotonic_buffer_resource() override { release(); } monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete; _LIBCPP_HIDE_FROM_ABI void release() { - __initial_.__cur_ = __initial_.__start_; + if (__initial_.__start_ != nullptr) + __initial_.__cur_ = __initial_.__end_; while (__chunks_ != nullptr) { __chunk_footer* __next = __chunks_->__next_; __res_->deallocate(__chunks_->__start_, __chunks_->__allocation_size(), __chunks_->__align_); @@ -98,9 +99,9 @@ public: protected: void* do_allocate(size_t __bytes, size_t __alignment) override; // key function - _LIBCPP_HIDE_FROM_ABI void do_deallocate(void*, size_t, size_t) override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void do_deallocate(void*, size_t, size_t) override {} - _LIBCPP_HIDE_FROM_ABI bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override { return this == std::addressof(__other); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/polymorphic_allocator.h b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/polymorphic_allocator.h index a5ca39b57e..f7b9a0b408 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -12,6 +12,7 @@ #include <__assert> #include <__config> #include <__memory_resource/memory_resource.h> +#include <__utility/exception_guard.h> #include <cstddef> #include <limits> #include <new> @@ -33,8 +34,13 @@ namespace pmr { // [mem.poly.allocator.class] -template <class _ValueType> +template <class _ValueType +# if _LIBCPP_STD_VER >= 20 + = byte +# endif + > class _LIBCPP_TEMPLATE_VIS polymorphic_allocator { + public: using value_type = _ValueType; @@ -66,6 +72,46 @@ public: __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType)); } +# if _LIBCPP_STD_VER >= 20 + + [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] void* + allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) { + return __res_->allocate(__nbytes, __alignment); + } + + void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) { + __res_->deallocate(__ptr, __nbytes, __alignment); + } + + template <class _Type> + [[nodiscard]] _Type* allocate_object(size_t __n = 1) { + if (numeric_limits<size_t>::max() / sizeof(_Type) < __n) + std::__throw_bad_array_new_length(); + return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type))); + } + + template <class _Type> + void deallocate_object(_Type* __ptr, size_t __n = 1) { + deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type)); + } + + template <class _Type, class... _CtorArgs> + [[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) { + _Type* __ptr = allocate_object<_Type>(); + auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); }); + construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...); + __guard.__complete(); + return __ptr; + } + + template <class _Type> + void delete_object(_Type* __ptr) { + destroy(__ptr); + deallocate_object(__ptr); + } + +# endif // _LIBCPP_STD_VER >= 20 + template <class _Tp, class... _Ts> _LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Ts&&... __args) { std::__user_alloc_construct_impl( diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/synchronized_pool_resource.h b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/synchronized_pool_resource.h index 550223c7d9..1877147ca1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/synchronized_pool_resource.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/synchronized_pool_resource.h @@ -62,14 +62,14 @@ public: _LIBCPP_HIDE_FROM_ABI pool_options options() const { return __unsync_.options(); } protected: - _LIBCPP_HIDE_FROM_ABI void* do_allocate(size_t __bytes, size_t __align) override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void* do_allocate(size_t __bytes, size_t __align) override { # if !defined(_LIBCPP_HAS_NO_THREADS) unique_lock<mutex> __lk(__mut_); # endif return __unsync_.allocate(__bytes, __align); } - _LIBCPP_HIDE_FROM_ABI void do_deallocate(void* __p, size_t __bytes, size_t __align) override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void do_deallocate(void* __p, size_t __bytes, size_t __align) override { # if !defined(_LIBCPP_HAS_NO_THREADS) unique_lock<mutex> __lk(__mut_); # endif diff --git a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/unsynchronized_pool_resource.h b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/unsynchronized_pool_resource.h index 7270cf19e2..91d38aac0d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__memory_resource/unsynchronized_pool_resource.h +++ b/contrib/libs/cxxsupp/libcxx/include/__memory_resource/unsynchronized_pool_resource.h @@ -70,7 +70,7 @@ public: unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; - _LIBCPP_HIDE_FROM_ABI ~unsynchronized_pool_resource() override { release(); } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~unsynchronized_pool_resource() override { release(); } unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete; @@ -85,7 +85,7 @@ protected: void do_deallocate(void* __p, size_t __bytes, size_t __align) override; - _LIBCPP_HIDE_FROM_ABI bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool do_is_equal(const memory_resource& __other) const _NOEXCEPT override { return &__other == this; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__numeric/gcd_lcm.h b/contrib/libs/cxxsupp/libcxx/include/__numeric/gcd_lcm.h index b3d776b3a4..5a3f81b695 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__numeric/gcd_lcm.h +++ b/contrib/libs/cxxsupp/libcxx/include/__numeric/gcd_lcm.h @@ -12,8 +12,12 @@ #include <__assert> #include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_signed.h> +#include <__type_traits/make_unsigned.h> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__numeric/midpoint.h b/contrib/libs/cxxsupp/libcxx/include/__numeric/midpoint.h index d8cce7929b..bac3642cbd 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__numeric/midpoint.h +++ b/contrib/libs/cxxsupp/libcxx/include/__numeric/midpoint.h @@ -11,8 +11,18 @@ #define _LIBCPP___NUMERIC_MIDPOINT_H #include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_null_pointer.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_void.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_pointer.h> +#include <cstddef> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -69,10 +79,10 @@ midpoint(_Fp __a, _Fp __b) noexcept { constexpr _Fp __lo = numeric_limits<_Fp>::min()*2; constexpr _Fp __hi = numeric_limits<_Fp>::max()/2; - return __fp_abs(__a) <= __hi && __fp_abs(__b) <= __hi ? // typical case: overflow is impossible + return std::__fp_abs(__a) <= __hi && std::__fp_abs(__b) <= __hi ? // typical case: overflow is impossible (__a + __b)/2 : // always correctly rounded - __fp_abs(__a) < __lo ? __a + __b/2 : // not safe to halve a - __fp_abs(__b) < __lo ? __a/2 + __b : // not safe to halve b + std::__fp_abs(__a) < __lo ? __a + __b/2 : // not safe to halve a + std::__fp_abs(__b) < __lo ? __a/2 + __b : // not safe to halve b __a/2 + __b/2; // otherwise correctly rounded } diff --git a/contrib/libs/cxxsupp/libcxx/include/__random/binomial_distribution.h b/contrib/libs/cxxsupp/libcxx/include/__random/binomial_distribution.h index 28f176e14f..7b0f055d50 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__random/binomial_distribution.h +++ b/contrib/libs/cxxsupp/libcxx/include/__random/binomial_distribution.h @@ -133,9 +133,9 @@ binomial_distribution<_IntType>::param_type::param_type(result_type __t, double if (0 < __p_ && __p_ < 1) { __r0_ = static_cast<result_type>((__t_ + 1) * __p_); - __pr_ = _VSTD::exp(__libcpp_lgamma(__t_ + 1.) - - __libcpp_lgamma(__r0_ + 1.) - - __libcpp_lgamma(__t_ - __r0_ + 1.) + __r0_ * _VSTD::log(__p_) + + __pr_ = _VSTD::exp(std::__libcpp_lgamma(__t_ + 1.) - + std::__libcpp_lgamma(__r0_ + 1.) - + std::__libcpp_lgamma(__t_ - __r0_ + 1.) + __r0_ * _VSTD::log(__p_) + (__t_ - __r0_) * _VSTD::log(1 - __p_)); __odds_ratio_ = __p_ / (1 - __p_); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__random/is_valid.h b/contrib/libs/cxxsupp/libcxx/include/__random/is_valid.h index be3b61b8dc..1d65de00fb 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__random/is_valid.h +++ b/contrib/libs/cxxsupp/libcxx/include/__random/is_valid.h @@ -53,7 +53,7 @@ template<> struct __libcpp_random_is_valid_inttype<__uint128_t> : true_type {}; template<class, class = void> struct __libcpp_random_is_valid_urng : false_type {}; template<class _Gp> struct __libcpp_random_is_valid_urng<_Gp, __enable_if_t< is_unsigned<typename _Gp::result_type>::value && - _IsSame<decltype(declval<_Gp&>()()), typename _Gp::result_type>::value + _IsSame<decltype(std::declval<_Gp&>()()), typename _Gp::result_type>::value > > : true_type {}; _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__random/uniform_int_distribution.h b/contrib/libs/cxxsupp/libcxx/include/__random/uniform_int_distribution.h index e9930e8575..b7db8a3f9c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__random/uniform_int_distribution.h +++ b/contrib/libs/cxxsupp/libcxx/include/__random/uniform_int_distribution.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H #define _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H -#include <__bits> #include <__config> #include <__random/is_valid.h> #include <__random/log2.h> @@ -242,7 +241,7 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK typedef __independent_bits_engine<_URNG, _UIntType> _Eng; if (_Rp == 0) return static_cast<result_type>(_Eng(__g, _Dt)()); - size_t __w = _Dt - __countl_zero(_Rp) - 1; + size_t __w = _Dt - std::__countl_zero(_Rp) - 1; if ((_Rp & (numeric_limits<_UIntType>::max() >> (_Dt - __w))) != 0) ++__w; _Eng __e(__g, __w); diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/access.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/access.h index 87392a163e..e48a71adf7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/access.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/access.h @@ -15,8 +15,13 @@ #include <__iterator/concepts.h> #include <__iterator/readable_traits.h> #include <__ranges/enable_borrowed_range.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include <type_traits> +#include <__utility/declval.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -100,7 +105,7 @@ inline namespace __cpo { namespace ranges { template <class _Tp> - using iterator_t = decltype(ranges::begin(declval<_Tp&>())); + using iterator_t = decltype(ranges::begin(std::declval<_Tp&>())); } // namespace ranges // [range.access.end] diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/all.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/all.h index c30c9e32e4..511f7b3b46 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/all.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/all.h @@ -73,7 +73,7 @@ inline namespace __cpo { } // namespace __cpo template<ranges::viewable_range _Range> -using all_t = decltype(views::all(declval<_Range>())); +using all_t = decltype(views::all(std::declval<_Range>())); } // namespace ranges::views diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/as_rvalue_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/as_rvalue_view.h new file mode 100644 index 0000000000..422d8a8e08 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/as_rvalue_view.h @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_AS_RVALUE_H +#define _LIBCPP___RANGES_AS_RVALUE_H + +#include <__concepts/constructible.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/move_iterator.h> +#include <__iterator/move_sentinel.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +template <view _View> + requires input_range<_View> +class as_rvalue_view : public view_interface<as_rvalue_view<_View>> { + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + +public: + _LIBCPP_HIDE_FROM_ABI as_rvalue_view() + requires default_initializable<_View> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit as_rvalue_view(_View __base) : __base_(std::move(__base)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() + requires(!__simple_view<_View>) + { + return move_iterator(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const + requires range<const _View> + { + return move_iterator(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() + requires(!__simple_view<_View>) + { + if constexpr (common_range<_View>) { + return move_iterator(ranges::end(__base_)); + } else { + return move_sentinel(ranges::end(__base_)); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires range<const _View> + { + if constexpr (common_range<const _View>) { + return move_iterator(ranges::end(__base_)); + } else { + return move_sentinel(ranges::end(__base_)); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() + requires sized_range<_View> + { + return ranges::size(__base_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires sized_range<const _View> + { + return ranges::size(__base_); + } +}; + +template <class _Range> +as_rvalue_view(_Range&&) -> as_rvalue_view<views::all_t<_Range>>; + +template <class _View> +inline constexpr bool enable_borrowed_range<as_rvalue_view<_View>> = enable_borrowed_range<_View>; + +namespace views { +namespace __as_rvalue { +struct __fn : __range_adaptor_closure<__fn> { + template <class _Range> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const + noexcept(noexcept(/**/ as_rvalue_view(std::forward<_Range>(__range)))) + -> decltype(/*--*/ as_rvalue_view(std::forward<_Range>(__range))) { + return /*-------------*/ as_rvalue_view(std::forward<_Range>(__range)); + } + + template <class _Range> + requires same_as<range_rvalue_reference_t<_Range>, range_reference_t<_Range>> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const + noexcept(noexcept(/**/ views::all(std::forward<_Range>(__range)))) + -> decltype(/*--*/ views::all(std::forward<_Range>(__range))) { + return /*-------------*/ views::all(std::forward<_Range>(__range)); + } +}; +} // namespace __as_rvalue + +inline namespace __cpo { +constexpr auto as_rvalue = __as_rvalue::__fn{}; +} // namespace __cpo +} // namespace views +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___RANGES_AS_RVALUE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/concepts.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/concepts.h index 739e14184a..e34c545578 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/concepts.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/concepts.h @@ -24,8 +24,12 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> #include <__ranges/size.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> #include <initializer_list> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -55,7 +59,7 @@ namespace ranges { // `iterator_t` defined in <__ranges/access.h> template <range _Rp> - using sentinel_t = decltype(ranges::end(declval<_Rp&>())); + using sentinel_t = decltype(ranges::end(std::declval<_Rp&>())); template <range _Rp> using range_difference_t = iter_difference_t<iterator_t<_Rp>>; @@ -74,7 +78,7 @@ namespace ranges { concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); }; template<sized_range _Rp> - using range_size_t = decltype(ranges::size(declval<_Rp&>())); + using range_size_t = decltype(ranges::size(std::declval<_Rp&>())); // `disable_sized_range` defined in `<__ranges/size.h>` diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/dangling.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/dangling.h index 525b5ff0aa..c10453454d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/dangling.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/dangling.h @@ -13,7 +13,7 @@ #include <__config> #include <__ranges/access.h> #include <__ranges/concepts.h> -#include <type_traits> +#include <__type_traits/conditional.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/data.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/data.h index cadbfc8cf3..0ac25b52c7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/data.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/data.h @@ -16,8 +16,13 @@ #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> #include <__ranges/access.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_pointer.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/elements_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/elements_view.h new file mode 100644 index 0000000000..997380ee9c --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/elements_view.h @@ -0,0 +1,413 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_ELEMENTS_VIEW_H +#define _LIBCPP___RANGES_ELEMENTS_VIEW_H + +#include <__compare/three_way_comparable.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__config> +#include <__fwd/get.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_like.h> +#include <__tuple_dir/tuple_size.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/maybe_const.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +template <class _Tp, size_t _Np> +concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value; + +template <class _Tp, size_t _Np> +concept __returnable_element = is_reference_v<_Tp> || move_constructible<tuple_element_t<_Np, _Tp>>; + +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +class elements_view : public view_interface<elements_view<_View, _Np>> { +private: + template <bool> + class __iterator; + + template <bool> + class __sentinel; + +public: + _LIBCPP_HIDE_FROM_ABI elements_view() + requires default_initializable<_View> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit elements_view(_View __base) : __base_(std::move(__base)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() + requires(!__simple_view<_View>) + { + return __iterator</*_Const=*/false>(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const + requires range<const _View> + { + return __iterator</*_Const=*/true>(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() + requires(!__simple_view<_View> && !common_range<_View>) + { + return __sentinel</*_Const=*/false>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() + requires(!__simple_view<_View> && common_range<_View>) + { + return __iterator</*_Const=*/false>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires range<const _View> + { + return __sentinel</*_Const=*/true>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires common_range<const _View> + { + return __iterator</*_Const=*/true>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() + requires sized_range<_View> + { + return ranges::size(__base_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires sized_range<const _View> + { + return ranges::size(__base_); + } + +private: + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); +}; + +template <class, size_t> +struct __elements_view_iterator_category_base {}; + +template <forward_range _Base, size_t _Np> +struct __elements_view_iterator_category_base<_Base, _Np> { + static consteval auto __get_iterator_category() { + using _Result = decltype(std::get<_Np>(*std::declval<iterator_t<_Base>>())); + using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; + + if constexpr (!is_lvalue_reference_v<_Result>) { + return input_iterator_tag{}; + } else if constexpr (derived_from<_Cat, random_access_iterator_tag>) { + return random_access_iterator_tag{}; + } else { + return _Cat{}; + } + } + + using iterator_category = decltype(__get_iterator_category()); +}; + +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +template <bool _Const> +class elements_view<_View, _Np>::__iterator + : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { + template <bool> + friend class __iterator; + + template <bool> + friend class __sentinel; + + using _Base = __maybe_const<_Const, _View>; + + iterator_t<_Base> __current_ = iterator_t<_Base>(); + + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_element(const iterator_t<_Base>& __i) { + if constexpr (is_reference_v<range_reference_t<_Base>>) { + return std::get<_Np>(*__i); + } else { + using _Element = remove_cv_t<tuple_element_t<_Np, range_reference_t<_Base>>>; + return static_cast<_Element>(std::get<_Np>(*__i)); + } + } + + static consteval auto __get_iterator_concept() { + if constexpr (random_access_range<_Base>) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_range<_Base>) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_range<_Base>) { + return forward_iterator_tag{}; + } else { + return input_iterator_tag{}; + } + } + +public: + using iterator_concept = decltype(__get_iterator_concept()); + using value_type = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>; + using difference_type = range_difference_t<_Base>; + + _LIBCPP_HIDE_FROM_ABI __iterator() + requires default_initializable<iterator_t<_Base>> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) + requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> + : __current_(std::move(__i.__current_)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; } + + _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(__current_); } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { + ++__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) + requires forward_range<_Base> + { + auto temp = *this; + ++__current_; + return temp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() + requires bidirectional_range<_Base> + { + --__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) + requires bidirectional_range<_Base> + { + auto temp = *this; + --__current_; + return temp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) + requires random_access_range<_Base> + { + __current_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) + requires random_access_range<_Base> + { + __current_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const + requires random_access_range<_Base> + { + return __get_element(__current_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires equality_comparable<iterator_t<_Base>> + { + return __x.__current_ == __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + requires random_access_range<_Base> + { + return __x.__current_ < __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + requires random_access_range<_Base> + { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + requires random_access_range<_Base> + { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + requires random_access_range<_Base> + { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> + { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __x, difference_type __y) + requires random_access_range<_Base> + { + return __iterator{__x} += __y; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __x, const __iterator& __y) + requires random_access_range<_Base> + { + return __y + __x; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __x, difference_type __y) + requires random_access_range<_Base> + { + return __iterator{__x} -= __y; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> + { + return __x.__current_ - __y.__current_; + } +}; + +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +template <bool _Const> +class elements_view<_View, _Np>::__sentinel { +private: + using _Base = __maybe_const<_Const, _View>; + _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); + + template <bool> + friend class __sentinel; + + template <bool _AnyConst> + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_current(const __iterator<_AnyConst>& __iter) { + return (__iter.__current_); + } + +public: + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other) + requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> + : __end_(std::move(__other.__end_)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } + + template <bool _OtherConst> + requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + return __get_current(__x) == __y.__end_; + } + + template <bool _OtherConst> + requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + return __get_current(__x) - __y.__end_; + } + + template <bool _OtherConst> + requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> + operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { + return __x.__end_ - __get_current(__y); + } +}; + +template <class _Tp, size_t _Np> +inline constexpr bool enable_borrowed_range<elements_view<_Tp, _Np>> = enable_borrowed_range<_Tp>; + +template <class _Tp> +using keys_view = elements_view<_Tp, 0>; +template <class _Tp> +using values_view = elements_view<_Tp, 1>; + +namespace views { +namespace __elements { + +template <size_t _Np> +struct __fn : __range_adaptor_closure<__fn<_Np>> { + template <class _Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const + /**/ noexcept(noexcept(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)))) + /*------*/ -> decltype(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range))) { + /*-------------*/ return elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)); + } +}; +} // namespace __elements + +inline namespace __cpo { +template <size_t _Np> +inline constexpr auto elements = __elements::__fn<_Np>{}; +inline constexpr auto keys = elements<0>; +inline constexpr auto values = elements<1>; +} // namespace __cpo +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_ELEMENTS_VIEW_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/empty.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/empty.h index 2370f1373c..8a1c75c0ba 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/empty.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/empty.h @@ -15,7 +15,6 @@ #include <__iterator/concepts.h> #include <__ranges/access.h> #include <__ranges/size.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/enable_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/enable_view.h index 2dc4752ff4..c85064b915 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/enable_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/enable_view.h @@ -13,7 +13,9 @@ #include <__concepts/derived_from.h> #include <__concepts/same_as.h> #include <__config> -#include <type_traits> +#include <__type_traits/is_class.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/filter_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/filter_view.h index 0622da54ef..e14a9abeb9 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/filter_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/filter_view.h @@ -120,6 +120,7 @@ namespace ranges { template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> { + public: _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>(); _LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr; @@ -224,8 +225,8 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_View> base() const { return __end_; } - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(__iterator const& __x, __sentinel const& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(__iterator const& __x, __sentinel const& __y) { return __x.__current_ == __y.__end_; } }; diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/istream_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/istream_view.h index 4113b329b2..66cd915276 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/istream_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/istream_view.h @@ -39,6 +39,8 @@ concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _V template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>> requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> { + class __iterator; + public: _LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream) : __stream_(std::addressof(__stream)) {} @@ -51,8 +53,6 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; } private: - class __iterator; - basic_istream<_CharT, _Traits>* __stream_; _LIBCPP_NO_UNIQUE_ADDRESS _Val __value_ = _Val(); }; @@ -65,7 +65,8 @@ public: using difference_type = ptrdiff_t; using value_type = _Val; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view& __parent) noexcept + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator( + basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept : __parent_(std::addressof(__parent)) {} __iterator(const __iterator&) = delete; @@ -88,7 +89,7 @@ public: } private: - basic_istream_view* __parent_; + basic_istream_view<_Val, _CharT, _Traits>* __parent_; _LIBCPP_HIDE_FROM_ABI constexpr basic_istream<_CharT, _Traits>* __get_parent_stream() const { return __parent_->__stream_; @@ -98,10 +99,10 @@ private: template <class _Val> using istream_view = basic_istream_view<_Val, char>; -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class _Val> using wistream_view = basic_istream_view<_Val, wchar_t>; -#endif +# endif namespace views { namespace __istream { @@ -127,7 +128,7 @@ struct __fn { inline namespace __cpo { template <class _Tp> - inline constexpr auto istream = __istream::__fn<_Tp>{}; +inline constexpr auto istream = __istream::__fn<_Tp>{}; } // namespace __cpo } // namespace views diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h index 293926cc12..b5a4c4e733 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h @@ -20,9 +20,12 @@ #include <__iterator/iter_move.h> #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> +#include <__iterator/iterator_with_data.h> +#include <__iterator/segmented_iterator.h> #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> +#include <__ranges/empty.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> @@ -37,6 +40,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// Note: `join_view` is still marked experimental because there is an ABI-breaking change that affects `join_view` in +// the pipeline (https://isocpp.org/files/papers/D2770R0.html). +// TODO: make `join_view` non-experimental once D2770 is implemented. #if _LIBCPP_STD_VER > 17 namespace ranges { @@ -71,8 +77,12 @@ namespace ranges { using _InnerRange = range_reference_t<_View>; template<bool> struct __iterator; + template<bool> struct __sentinel; + template <class> + friend struct std::__segmented_iterator_traits; + static constexpr bool _UseCache = !is_reference_v<_InnerRange>; using _Cache = _If<_UseCache, __non_propagating_cache<remove_cvref_t<_InnerRange>>, __empty_cache>; _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cache_; @@ -141,11 +151,13 @@ namespace ranges { template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> - template<bool _Const> struct join_view<_View>::__sentinel { - template<bool> friend struct __sentinel; + template<bool _Const> + struct join_view<_View>::__sentinel { + template<bool> + friend struct __sentinel; private: - using _Parent = __maybe_const<_Const, join_view>; + using _Parent = __maybe_const<_Const, join_view<_View>>; using _Base = __maybe_const<_Const, _View>; sentinel_t<_Base> __end_ = sentinel_t<_Base>(); @@ -170,18 +182,29 @@ namespace ranges { } }; + // https://reviews.llvm.org/D142811#inline-1383022 + // To simplify the segmented iterator traits specialization, + // make the iterator `final` template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> - template<bool _Const> struct join_view<_View>::__iterator + template<bool _Const> + struct join_view<_View>::__iterator final : public __join_view_iterator_category<__maybe_const<_Const, _View>> { - template<bool> friend struct __iterator; + template<bool> + friend struct __iterator; + + template <class> + friend struct std::__segmented_iterator_traits; + + static constexpr bool __is_join_view_iterator = true; private: - using _Parent = __maybe_const<_Const, join_view>; + using _Parent = __maybe_const<_Const, join_view<_View>>; using _Base = __maybe_const<_Const, _View>; using _Outer = iterator_t<_Base>; using _Inner = iterator_t<range_reference_t<_Base>>; + using _InnerRange = range_reference_t<_View>; static constexpr bool __ref_is_glvalue = is_reference_v<range_reference_t<_Base>>; @@ -210,6 +233,9 @@ namespace ranges { __inner_.reset(); } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner) + : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} + public: using iterator_concept = _If< __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && @@ -365,7 +391,51 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +template <class _JoinViewIterator> + requires(_JoinViewIterator::__is_join_view_iterator && + ranges::common_range<typename _JoinViewIterator::_Parent> && + __is_cpp17_random_access_iterator<typename _JoinViewIterator::_Outer>::value && + __is_cpp17_random_access_iterator<typename _JoinViewIterator::_Inner>::value) +struct __segmented_iterator_traits<_JoinViewIterator> { + + using __segment_iterator = + _LIBCPP_NODEBUG __iterator_with_data<typename _JoinViewIterator::_Outer, typename _JoinViewIterator::_Parent*>; + using __local_iterator = typename _JoinViewIterator::_Inner; + + // TODO: Would it make sense to enable the optimization for other iterator types? + + static constexpr _LIBCPP_HIDE_FROM_ABI __segment_iterator __segment(_JoinViewIterator __iter) { + if (ranges::empty(__iter.__parent_->__base_)) + return {}; + if (!__iter.__inner_.has_value()) + return __segment_iterator(--__iter.__outer_, __iter.__parent_); + return __segment_iterator(__iter.__outer_, __iter.__parent_); + } + + static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __local(_JoinViewIterator __iter) { + if (ranges::empty(__iter.__parent_->__base_)) + return {}; + if (!__iter.__inner_.has_value()) + return ranges::end(*--__iter.__outer_); + return *__iter.__inner_; + } + + static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __begin(__segment_iterator __iter) { + return ranges::begin(*__iter.__get_iter()); + } + + static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __end(__segment_iterator __iter) { + return ranges::end(*__iter.__get_iter()); + } + + static constexpr _LIBCPP_HIDE_FROM_ABI _JoinViewIterator + __compose(__segment_iterator __seg_iter, __local_iterator __local_iter) { + return _JoinViewIterator( + std::move(__seg_iter).__get_data(), std::move(__seg_iter).__get_iter(), std::move(__local_iter)); + } +}; + +#endif // #if _LIBCPP_STD_VER > 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/ref_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/ref_view.h index e949f75344..1e5f7466f3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/ref_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/ref_view.h @@ -47,7 +47,7 @@ namespace ranges { public: template<class _Tp> requires __different_from<_Tp, ref_view> && - convertible_to<_Tp, _Range&> && requires { __fun(declval<_Tp>()); } + convertible_to<_Tp, _Range&> && requires { __fun(std::declval<_Tp>()); } _LIBCPP_HIDE_FROM_ABI constexpr ref_view(_Tp&& __t) : __range_(std::addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/size.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/size.h index 720e3d4fd2..0ac8d63063 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/size.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/size.h @@ -16,9 +16,13 @@ #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__ranges/access.h> +#include <__type_traits/decay.h> +#include <__type_traits/make_signed.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cvref.h> #include <__utility/auto_cast.h> +#include <__utility/declval.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -67,7 +71,7 @@ concept __difference = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) { { ranges::begin(__t) } -> forward_iterator; - { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(declval<_Tp>()))>; + { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(std::declval<_Tp>()))>; }; struct __fn { diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/split_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/split_view.h new file mode 100644 index 0000000000..6ebe5a43ed --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/split_view.h @@ -0,0 +1,226 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_SPLIT_VIEW_H +#define _LIBCPP___RANGES_SPLIT_VIEW_H + +#include <__algorithm/ranges_search.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/ranges_operations.h> +#include <__iterator/indirectly_comparable.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/empty.h> +#include <__ranges/non_propagating_cache.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/single_view.h> +#include <__ranges/subrange.h> +#include <__ranges/view_interface.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +class split_view : public view_interface<split_view<_View, _Pattern>> { +private: + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + _LIBCPP_NO_UNIQUE_ADDRESS _Pattern __pattern_ = _Pattern(); + using _Cache = __non_propagating_cache<subrange<iterator_t<_View>>>; + _Cache __cached_begin_ = _Cache(); + + template <class, class> + friend struct __iterator; + + template <class, class> + friend struct __sentinel; + + struct __iterator; + struct __sentinel; + + _LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) { + auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_); + if (__begin != ranges::end(__base_) && ranges::empty(__pattern_)) { + ++__begin; + ++__end; + } + return {__begin, __end}; + } + +public: + _LIBCPP_HIDE_FROM_ABI split_view() + requires default_initializable<_View> && default_initializable<_Pattern> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr split_view(_View __base, _Pattern __pattern) + : __base_(std::move(__base)), __pattern_(std::move((__pattern))) {} + + template <forward_range _Range> + requires constructible_from<_View, views::all_t<_Range>> && + constructible_from<_Pattern, single_view<range_value_t<_Range>>> + _LIBCPP_HIDE_FROM_ABI constexpr split_view(_Range&& __range, range_value_t<_Range> __elem) + : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() { + if (!__cached_begin_.__has_value()) { + __cached_begin_.__emplace(__find_next(ranges::begin(__base_))); + } + return {*this, ranges::begin(__base_), *__cached_begin_}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() { + if constexpr (common_range<_View>) { + return __iterator{*this, ranges::end(__base_), {}}; + } else { + return __sentinel{*this}; + } + } +}; + +template <class _Range, class _Pattern> +split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_t<_Pattern>>; + +template <forward_range _Range> +split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; + +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +struct split_view<_View, _Pattern>::__iterator { +private: + split_view* __parent_ = nullptr; + _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>(); + _LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>(); + bool __trailing_empty_ = false; + + friend struct __sentinel; + +public: + using iterator_concept = forward_iterator_tag; + using iterator_category = input_iterator_tag; + using value_type = subrange<iterator_t<_View>>; + using difference_type = range_difference_t<_View>; + + _LIBCPP_HIDE_FROM_ABI __iterator() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator( + split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next) + : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() const { return __cur_; } + + _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { + __cur_ = __next_.begin(); + if (__cur_ != ranges::end(__parent_->__base_)) { + __cur_ = __next_.end(); + if (__cur_ == ranges::end(__parent_->__base_)) { + __trailing_empty_ = true; + __next_ = {__cur_, __cur_}; + } else { + __next_ = __parent_->__find_next(__cur_); + } + } else { + __trailing_empty_ = false; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { + return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_; + } +}; + +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +struct split_view<_View, _Pattern>::__sentinel { +private: + _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>(); + + _LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) { + return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_; + } + +public: + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent) + : __end_(ranges::end(__parent.__base_)) {} + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { + return __equals(__x, __y); + } +}; + +namespace views { +namespace __split_view { +struct __fn : __range_adaptor_closure<__fn> { + // clang-format off + template <class _Range, class _Pattern> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const + noexcept(noexcept(split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) + -> decltype( split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) + { return split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)); } + // clang-format on + + template <class _Pattern> + requires constructible_from<decay_t<_Pattern>, _Pattern> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const + noexcept(is_nothrow_constructible_v<decay_t<_Pattern>, _Pattern>) { + return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern))); + } +}; +} // namespace __split_view + +inline namespace __cpo { +inline constexpr auto split = __split_view::__fn{}; +} // namespace __cpo +} // namespace views + +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_SPLIT_VIEW_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/subrange.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/subrange.h index 3efcd9602a..2d9e4cc7e5 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/subrange.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/subrange.h @@ -18,6 +18,7 @@ #include <__concepts/different_from.h> #include <__config> #include <__fwd/get.h> +#include <__fwd/subrange.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> @@ -28,10 +29,18 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple/tuple_element.h> -#include <__tuple/tuple_size.h> +#include <__tuple_dir/pair_like.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_size.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_pointer.h> #include <__utility/move.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -52,17 +61,6 @@ namespace ranges { convertible_to<_From, _To> && !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>; - template<class _Tp> - concept __pair_like = - !is_reference_v<_Tp> && requires(_Tp __t) { - typename tuple_size<_Tp>::type; // Ensures `tuple_size<T>` is complete. - requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>; - typename tuple_element_t<0, remove_const_t<_Tp>>; - typename tuple_element_t<1, remove_const_t<_Tp>>; - { std::get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>; - { std::get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>; - }; - template<class _Pair, class _Iter, class _Sent> concept __pair_like_convertible_from = !range<_Pair> && __pair_like<_Pair> && @@ -70,8 +68,6 @@ namespace ranges { __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>; - enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized }; - template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter, subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> ? subrange_kind::sized diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h index 546e898aec..bea3862cd7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h @@ -12,6 +12,7 @@ #include <__algorithm/min.h> #include <__algorithm/ranges_min.h> +#include <__assert> #include <__concepts/constructible.h> #include <__concepts/convertible_to.h> #include <__config> @@ -63,9 +64,10 @@ public: _LIBCPP_HIDE_FROM_ABI take_view() requires default_initializable<_View> = default; - _LIBCPP_HIDE_FROM_ABI - constexpr take_view(_View __base, range_difference_t<_View> __count) - : __base_(std::move(__base)), __count_(__count) {} + _LIBCPP_HIDE_FROM_ABI constexpr take_view(_View __base, range_difference_t<_View> __count) + : __base_(std::move(__base)), __count_(__count) { + _LIBCPP_ASSERT(__count >= 0, "count has to be greater than or equal to zero"); + } _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/view_interface.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/view_interface.h index b89ee999f8..5581eb9c73 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/view_interface.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/view_interface.h @@ -21,7 +21,9 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/empty.h> -#include <type_traits> +#include <__type_traits/is_class.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -100,7 +102,7 @@ public: constexpr auto size() requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>> { - return ranges::end(__derived()) - ranges::begin(__derived()); + return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); } template<class _D2 = _Derived> @@ -108,7 +110,7 @@ public: constexpr auto size() const requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>> { - return ranges::end(__derived()) - ranges::begin(__derived()); + return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); } template<class _D2 = _Derived> diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/zip_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/zip_view.h index 6eb0ffdf84..5624726e13 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/zip_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/zip_view.h @@ -403,15 +403,15 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr auto iter_move(const __iterator& __i) noexcept( - (noexcept(ranges::iter_move(declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...) && + (noexcept(ranges::iter_move(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...) && (is_nothrow_move_constructible_v<range_rvalue_reference_t<__maybe_const<_Const, _Views>>> && ...)) { return ranges::__tuple_transform(ranges::iter_move, __i.__current_); } _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const __iterator& __l, const __iterator& __r) noexcept( - (noexcept(ranges::iter_swap(declval<const iterator_t<__maybe_const<_Const, _Views>>&>(), - declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && + (noexcept(ranges::iter_swap(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>(), + std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...)) requires(indirectly_swappable<iterator_t<__maybe_const<_Const, _Views>>> && ...) { ranges::__tuple_zip_for_each(ranges::iter_swap, __l.__current_, __r.__current_); diff --git a/contrib/libs/cxxsupp/libcxx/include/__split_buffer b/contrib/libs/cxxsupp/libcxx/include/__split_buffer index 5750a71531..4855089bcf 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__split_buffer +++ b/contrib/libs/cxxsupp/libcxx/include/__split_buffer @@ -507,7 +507,7 @@ __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) } else { - size_type __c = max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); + size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc()); __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); @@ -537,7 +537,7 @@ __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) } else { - size_type __c = max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); + size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc()); __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); @@ -569,7 +569,7 @@ __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) } else { - size_type __c = max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); + size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); @@ -599,7 +599,7 @@ __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) } else { - size_type __c = max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); + size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); @@ -631,7 +631,7 @@ __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) } else { - size_type __c = max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); + size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1); __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc()); __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); diff --git a/contrib/libs/cxxsupp/libcxx/include/__string/char_traits.h b/contrib/libs/cxxsupp/libcxx/include/__string/char_traits.h index dc9afbd336..622ee224f1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__string/char_traits.h +++ b/contrib/libs/cxxsupp/libcxx/include/__string/char_traits.h @@ -210,25 +210,22 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char> static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {return (unsigned char)__c1 < (unsigned char)__c2;} - static _LIBCPP_CONSTEXPR_SINCE_CXX17 - int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; + static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { + if (__n == 0) + return 0; + return std::__constexpr_memcmp(__s1, __s2, __n); + } - static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT { - // GCC currently does not support __builtin_strlen during constant evaluation. - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 -#ifdef _LIBCPP_COMPILER_GCC - if (__libcpp_is_constant_evaluated()) { - size_t __i = 0; - for (; __s[__i] != char_type('\0'); ++__i) - ; - return __i; - } -#endif - return __builtin_strlen(__s); - } + static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT { + return std::__constexpr_strlen(__s); + } - static _LIBCPP_CONSTEXPR_SINCE_CXX17 - const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; + static _LIBCPP_CONSTEXPR_SINCE_CXX17 + const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { + if (__n == 0) + return nullptr; + return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n); + } static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { @@ -261,49 +258,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char> {return int_type(EOF);} }; -inline _LIBCPP_CONSTEXPR_SINCE_CXX17 -int -char_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT -{ - if (__n == 0) - return 0; -#if __has_feature(cxx_constexpr_string_builtins) - return __builtin_memcmp(__s1, __s2, __n); -#elif _LIBCPP_STD_VER <= 14 - return _VSTD::memcmp(__s1, __s2, __n); -#else - for (; __n; --__n, ++__s1, ++__s2) - { - if (lt(*__s1, *__s2)) - return -1; - if (lt(*__s2, *__s1)) - return 1; - } - return 0; -#endif -} - -inline _LIBCPP_CONSTEXPR_SINCE_CXX17 -const char* -char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT -{ - if (__n == 0) - return nullptr; -#if __has_feature(cxx_constexpr_string_builtins) && !defined(__CUDACC__) - return __builtin_char_memchr(__s, to_int_type(__a), __n); -#elif _LIBCPP_STD_VER <= 14 - return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n); -#else - for (; __n; --__n) - { - if (eq(*__s, __a)) - return __s; - ++__s; - } - return nullptr; -#endif -} - // char_traits<wchar_t> #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -326,12 +280,22 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 < __c2;} - static _LIBCPP_CONSTEXPR_SINCE_CXX17 - int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; - static _LIBCPP_CONSTEXPR_SINCE_CXX17 - size_t length(const char_type* __s) _NOEXCEPT; - static _LIBCPP_CONSTEXPR_SINCE_CXX17 - const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; + static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { + if (__n == 0) + return 0; + return std::__constexpr_wmemcmp(__s1, __s2, __n); + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT { + return std::__constexpr_wcslen(__s); + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX17 + const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { + if (__n == 0) + return nullptr; + return std::__constexpr_wmemchr(__s, __a, __n); + } static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { @@ -363,65 +327,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {return int_type(WEOF);} }; - -inline _LIBCPP_CONSTEXPR_SINCE_CXX17 -int -char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT -{ - if (__n == 0) - return 0; -#if __has_feature(cxx_constexpr_string_builtins) && !defined(__CUDACC__) - return __builtin_wmemcmp(__s1, __s2, __n); -#elif _LIBCPP_STD_VER <= 14 - return _VSTD::wmemcmp(__s1, __s2, __n); -#else - for (; __n; --__n, ++__s1, ++__s2) - { - if (lt(*__s1, *__s2)) - return -1; - if (lt(*__s2, *__s1)) - return 1; - } - return 0; -#endif -} - -inline _LIBCPP_CONSTEXPR_SINCE_CXX17 -size_t -char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT -{ -#if __has_feature(cxx_constexpr_string_builtins) && !defined(__CUDACC__) - return __builtin_wcslen(__s); -#elif _LIBCPP_STD_VER <= 14 - return _VSTD::wcslen(__s); -#else - size_t __len = 0; - for (; !eq(*__s, char_type(0)); ++__s) - ++__len; - return __len; -#endif -} - -inline _LIBCPP_CONSTEXPR_SINCE_CXX17 -const wchar_t* -char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT -{ - if (__n == 0) - return nullptr; -#if __has_feature(cxx_constexpr_string_builtins) && !defined(__CUDACC__) - return __builtin_wmemchr(__s, __a, __n); -#elif _LIBCPP_STD_VER <= 14 - return _VSTD::wmemchr(__s, __a, __n); -#else - for (; __n; --__n) - { - if (eq(*__s, __a)) - return __s; - ++__s; - } - return nullptr; -#endif -} #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS #ifndef _LIBCPP_HAS_NO_CHAR8_T @@ -445,8 +350,10 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept {return __c1 < __c2;} - static constexpr - int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; + static _LIBCPP_HIDE_FROM_ABI constexpr int + compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { + return std::__constexpr_memcmp(__s1, __s2, __n); + } static constexpr size_t length(const char_type* __s) _NOEXCEPT; @@ -496,24 +403,6 @@ char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT return __len; } -inline constexpr -int -char_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT -{ -#if __has_feature(cxx_constexpr_string_builtins) - return __builtin_memcmp(__s1, __s2, __n); -#else - for (; __n; --__n, ++__s1, ++__s2) - { - if (lt(*__s1, *__s2)) - return -1; - if (lt(*__s2, *__s1)) - return 1; - } - return 0; -#endif -} - // TODO use '__builtin_char_memchr' if it ever supports char8_t ?? inline constexpr const char8_t* @@ -782,7 +671,7 @@ __str_find(const _CharT *__p, _SizeT __sz, if (__n == 0) // There is nothing to search, just return __pos. return __pos; - const _CharT *__r = __search_substring<_CharT, _Traits>( + const _CharT *__r = std::__search_substring<_CharT, _Traits>( __p + __pos, __p + __sz, __s, __s + __n); if (__r == __p + __sz) diff --git a/contrib/libs/cxxsupp/libcxx/include/__support/android/locale_bionic.h b/contrib/libs/cxxsupp/libcxx/include/__support/android/locale_bionic.h index 5f4a89a7c6..30e345cf9e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__support/android/locale_bionic.h +++ b/contrib/libs/cxxsupp/libcxx/include/__support/android/locale_bionic.h @@ -46,18 +46,15 @@ extern "C" { extern "C" { #endif -inline _LIBCPP_HIDE_FROM_ABI float -strtof_l(const char* __nptr, char** __endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C float strtof_l(const char* __nptr, char** __endptr, locale_t) { return ::strtof(__nptr, __endptr); } -inline _LIBCPP_HIDE_FROM_ABI double -strtod_l(const char* __nptr, char** __endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C double strtod_l(const char* __nptr, char** __endptr, locale_t) { return ::strtod(__nptr, __endptr); } -inline _LIBCPP_HIDE_FROM_ABI long -strtol_l(const char* __nptr, char** __endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtol(__nptr, __endptr, __base); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__support/musl/xlocale.h b/contrib/libs/cxxsupp/libcxx/include/__support/musl/xlocale.h index 675ba93e11..fe1dcf61a5 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__support/musl/xlocale.h +++ b/contrib/libs/cxxsupp/libcxx/include/__support/musl/xlocale.h @@ -24,28 +24,24 @@ extern "C" { #endif -inline _LIBCPP_HIDE_FROM_ABI long long -strtoll_l(const char *__nptr, char **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long long strtoll_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI unsigned long long -strtoull_l(const char *__nptr, char **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C unsigned long long +strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtoull(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI long long -wcstoll_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long long wcstoll_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) { return ::wcstoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI long long -wcstoull_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long long wcstoull_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) { return ::wcstoull(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI long double -wcstold_l(const wchar_t *__nptr, wchar_t **__endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long double wcstold_l(const wchar_t* __nptr, wchar_t** __endptr, locale_t) { return ::wcstold(__nptr, __endptr); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__support/openbsd/xlocale.h b/contrib/libs/cxxsupp/libcxx/include/__support/openbsd/xlocale.h index 0269e8133b..b969ae9d10 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__support/openbsd/xlocale.h +++ b/contrib/libs/cxxsupp/libcxx/include/__support/openbsd/xlocale.h @@ -20,18 +20,14 @@ extern "C" { #endif - -inline _LIBCPP_HIDE_FROM_ABI long -strtol_l(const char *__nptr, char **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtol(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI unsigned long -strtoul_l(const char *__nptr, char **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C unsigned long strtoul_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtoul(__nptr, __endptr, __base); } - #ifdef __cplusplus } #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__nop_locale_mgmt.h b/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__nop_locale_mgmt.h index 23727a5a3b..4b3caa895f 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__nop_locale_mgmt.h +++ b/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__nop_locale_mgmt.h @@ -19,24 +19,13 @@ extern "C" { // Patch over lack of extended locale support typedef void *locale_t; -inline _LIBCPP_HIDE_FROM_ABI locale_t -duplocale(locale_t) { - return NULL; -} - -inline _LIBCPP_HIDE_FROM_ABI void -freelocale(locale_t) { -} - -inline _LIBCPP_HIDE_FROM_ABI locale_t -newlocale(int, const char *, locale_t) { - return NULL; -} - -inline _LIBCPP_HIDE_FROM_ABI locale_t -uselocale(locale_t) { - return NULL; -} +inline _LIBCPP_HIDE_FROM_ABI_C locale_t duplocale(locale_t) { return NULL; } + +inline _LIBCPP_HIDE_FROM_ABI_C void freelocale(locale_t) {} + +inline _LIBCPP_HIDE_FROM_ABI_C locale_t newlocale(int, const char*, locale_t) { return NULL; } + +inline _LIBCPP_HIDE_FROM_ABI_C locale_t uselocale(locale_t) { return NULL; } #define LC_COLLATE_MASK (1 << LC_COLLATE) #define LC_CTYPE_MASK (1 << LC_CTYPE) diff --git a/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__posix_l_fallback.h b/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__posix_l_fallback.h index 8196c2362c..774081a8a4 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__posix_l_fallback.h +++ b/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__posix_l_fallback.h @@ -27,144 +27,83 @@ extern "C" { #endif -inline _LIBCPP_HIDE_FROM_ABI int isalnum_l(int __c, locale_t) { - return ::isalnum(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isalnum_l(int __c, locale_t) { return ::isalnum(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isalpha_l(int __c, locale_t) { - return ::isalpha(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isalpha_l(int __c, locale_t) { return ::isalpha(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isblank_l(int __c, locale_t) { - return ::isblank(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isblank_l(int __c, locale_t) { return ::isblank(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iscntrl_l(int __c, locale_t) { - return ::iscntrl(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iscntrl_l(int __c, locale_t) { return ::iscntrl(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isdigit_l(int __c, locale_t) { - return ::isdigit(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isdigit_l(int __c, locale_t) { return ::isdigit(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isgraph_l(int __c, locale_t) { - return ::isgraph(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isgraph_l(int __c, locale_t) { return ::isgraph(__c); } -inline _LIBCPP_HIDE_FROM_ABI int islower_l(int __c, locale_t) { - return ::islower(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int islower_l(int __c, locale_t) { return ::islower(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isprint_l(int __c, locale_t) { - return ::isprint(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isprint_l(int __c, locale_t) { return ::isprint(__c); } -inline _LIBCPP_HIDE_FROM_ABI int ispunct_l(int __c, locale_t) { - return ::ispunct(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int ispunct_l(int __c, locale_t) { return ::ispunct(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isspace_l(int __c, locale_t) { - return ::isspace(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isspace_l(int __c, locale_t) { return ::isspace(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isupper_l(int __c, locale_t) { - return ::isupper(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isupper_l(int __c, locale_t) { return ::isupper(__c); } -inline _LIBCPP_HIDE_FROM_ABI int isxdigit_l(int __c, locale_t) { - return ::isxdigit(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int isxdigit_l(int __c, locale_t) { return ::isxdigit(__c); } -inline _LIBCPP_HIDE_FROM_ABI int toupper_l(int __c, locale_t) { - return ::toupper(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int toupper_l(int __c, locale_t) { return ::toupper(__c); } -inline _LIBCPP_HIDE_FROM_ABI int tolower_l(int __c, locale_t) { - return ::tolower(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int tolower_l(int __c, locale_t) { return ::tolower(__c); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -inline _LIBCPP_HIDE_FROM_ABI int iswalnum_l(wint_t __c, locale_t) { - return ::iswalnum(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswalnum_l(wint_t __c, locale_t) { return ::iswalnum(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswalpha_l(wint_t __c, locale_t) { - return ::iswalpha(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswalpha_l(wint_t __c, locale_t) { return ::iswalpha(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswblank_l(wint_t __c, locale_t) { - return ::iswblank(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswblank_l(wint_t __c, locale_t) { return ::iswblank(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswcntrl_l(wint_t __c, locale_t) { - return ::iswcntrl(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswcntrl_l(wint_t __c, locale_t) { return ::iswcntrl(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswdigit_l(wint_t __c, locale_t) { - return ::iswdigit(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswdigit_l(wint_t __c, locale_t) { return ::iswdigit(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswgraph_l(wint_t __c, locale_t) { - return ::iswgraph(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswgraph_l(wint_t __c, locale_t) { return ::iswgraph(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswlower_l(wint_t __c, locale_t) { - return ::iswlower(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswlower_l(wint_t __c, locale_t) { return ::iswlower(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswprint_l(wint_t __c, locale_t) { - return ::iswprint(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswprint_l(wint_t __c, locale_t) { return ::iswprint(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswpunct_l(wint_t __c, locale_t) { - return ::iswpunct(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswpunct_l(wint_t __c, locale_t) { return ::iswpunct(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswspace_l(wint_t __c, locale_t) { - return ::iswspace(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswspace_l(wint_t __c, locale_t) { return ::iswspace(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswupper_l(wint_t __c, locale_t) { - return ::iswupper(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswupper_l(wint_t __c, locale_t) { return ::iswupper(__c); } -inline _LIBCPP_HIDE_FROM_ABI int iswxdigit_l(wint_t __c, locale_t) { - return ::iswxdigit(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C int iswxdigit_l(wint_t __c, locale_t) { return ::iswxdigit(__c); } -inline _LIBCPP_HIDE_FROM_ABI wint_t towupper_l(wint_t __c, locale_t) { - return ::towupper(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C wint_t towupper_l(wint_t __c, locale_t) { return ::towupper(__c); } -inline _LIBCPP_HIDE_FROM_ABI wint_t towlower_l(wint_t __c, locale_t) { - return ::towlower(__c); -} +inline _LIBCPP_HIDE_FROM_ABI_C wint_t towlower_l(wint_t __c, locale_t) { return ::towlower(__c); } #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS -inline _LIBCPP_HIDE_FROM_ABI int -strcoll_l(const char *__s1, const char *__s2, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C int strcoll_l(const char* __s1, const char* __s2, locale_t) { return ::strcoll(__s1, __s2); } -inline _LIBCPP_HIDE_FROM_ABI size_t -strxfrm_l(char *__dest, const char *__src, size_t __n, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C size_t strxfrm_l(char* __dest, const char* __src, size_t __n, locale_t) { return ::strxfrm(__dest, __src, __n); } -inline _LIBCPP_HIDE_FROM_ABI size_t -strftime_l(char *__s, size_t __max, const char *__format, const struct tm *__tm, - locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C size_t +strftime_l(char* __s, size_t __max, const char* __format, const struct tm* __tm, locale_t) { return ::strftime(__s, __max, __format, __tm); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -inline _LIBCPP_HIDE_FROM_ABI int -wcscoll_l(const wchar_t *__ws1, const wchar_t *__ws2, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C int wcscoll_l(const wchar_t* __ws1, const wchar_t* __ws2, locale_t) { return ::wcscoll(__ws1, __ws2); } -inline _LIBCPP_HIDE_FROM_ABI size_t -wcsxfrm_l(wchar_t *__dest, const wchar_t *__src, size_t __n, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C size_t wcsxfrm_l(wchar_t* __dest, const wchar_t* __src, size_t __n, locale_t) { return ::wcsxfrm(__dest, __src, __n); } #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS diff --git a/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__strtonum_fallback.h b/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__strtonum_fallback.h index d1ef8aaa83..ae8e13a758 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__strtonum_fallback.h +++ b/contrib/libs/cxxsupp/libcxx/include/__support/xlocale/__strtonum_fallback.h @@ -26,44 +26,38 @@ extern "C" { #endif -inline _LIBCPP_HIDE_FROM_ABI float -strtof_l(const char *__nptr, char **__endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C float strtof_l(const char* __nptr, char** __endptr, locale_t) { return ::strtof(__nptr, __endptr); } -inline _LIBCPP_HIDE_FROM_ABI double -strtod_l(const char *__nptr, char **__endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C double strtod_l(const char* __nptr, char** __endptr, locale_t) { return ::strtod(__nptr, __endptr); } -inline _LIBCPP_HIDE_FROM_ABI long double -strtold_l(const char *__nptr, char **__endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long double strtold_l(const char* __nptr, char** __endptr, locale_t) { return ::strtold(__nptr, __endptr); } -inline _LIBCPP_HIDE_FROM_ABI long long -strtoll_l(const char *__nptr, char **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long long strtoll_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI unsigned long long -strtoull_l(const char *__nptr, char **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C unsigned long long +strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtoull(__nptr, __endptr, __base); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -inline _LIBCPP_HIDE_FROM_ABI long long -wcstoll_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long long wcstoll_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) { return ::wcstoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI unsigned long long -wcstoull_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C unsigned long long +wcstoull_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) { return ::wcstoull(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI long double -wcstold_l(const wchar_t *__nptr, wchar_t **__endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI_C long double wcstold_l(const wchar_t* __nptr, wchar_t** __endptr, locale_t) { return ::wcstold(__nptr, __endptr); } #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS diff --git a/contrib/libs/cxxsupp/libcxx/include/__tree b/contrib/libs/cxxsupp/libcxx/include/__tree index 05a3da1580..f5d9d595b4 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tree +++ b/contrib/libs/cxxsupp/libcxx/include/__tree @@ -14,6 +14,7 @@ #include <__assert> #include <__config> #include <__debug> +#include <__functional/invoke.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> @@ -23,6 +24,17 @@ #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> #include <__type_traits/can_extract_key.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/remove_const_ref.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/apply_cv.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/apply_cv.h index 296755a1d5..296755a1d5 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/apply_cv.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/apply_cv.h diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/make_tuple_types.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/make_tuple_types.h index 38e2547d13..913ff9bbd6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/make_tuple_types.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/make_tuple_types.h @@ -12,11 +12,11 @@ #include <__config> #include <__fwd/array.h> #include <__fwd/tuple.h> -#include <__tuple/apply_cv.h> -#include <__tuple/tuple_element.h> -#include <__tuple/tuple_indices.h> -#include <__tuple/tuple_size.h> -#include <__tuple/tuple_types.h> +#include <__tuple_dir/apply_cv.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_indices.h> +#include <__tuple_dir/tuple_size.h> +#include <__tuple_dir/tuple_types.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_reference.h> #include <cstddef> diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/pair_like.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/pair_like.h new file mode 100644 index 0000000000..87407ad95b --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/pair_like.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TUPLE_PAIR_LIKE_H +#define _LIBCPP___TUPLE_PAIR_LIKE_H + +#include <__config> +#include <__tuple_dir/tuple_like.h> +#include <__tuple_dir/tuple_size.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp> +concept __pair_like = __tuple_like<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TUPLE_PAIR_LIKE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/sfinae_helpers.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/sfinae_helpers.h index ebe1e07a00..bedb62b6c7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/sfinae_helpers.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/sfinae_helpers.h @@ -11,11 +11,11 @@ #include <__config> #include <__fwd/tuple.h> -#include <__tuple/make_tuple_types.h> -#include <__tuple/tuple_element.h> -#include <__tuple/tuple_like.h> -#include <__tuple/tuple_size.h> -#include <__tuple/tuple_types.h> +#include <__tuple_dir/make_tuple_types.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_like_ext.h> +#include <__tuple_dir/tuple_size.h> +#include <__tuple_dir/tuple_types.h> #include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_assignable.h> @@ -58,8 +58,8 @@ struct __tuple_sfinae_base { // __tuple_convertible -template <class _Tp, class _Up, bool = __tuple_like<__libcpp_remove_reference_t<_Tp> >::value, - bool = __tuple_like<_Up>::value, +template <class _Tp, class _Up, bool = __tuple_like_ext<__libcpp_remove_reference_t<_Tp> >::value, + bool = __tuple_like_ext<_Up>::value, class = void> struct __tuple_convertible : public false_type {}; @@ -75,8 +75,8 @@ struct __tuple_convertible<_Tp, _Up, true, true, // __tuple_constructible -template <class _Tp, class _Up, bool = __tuple_like<__libcpp_remove_reference_t<_Tp> >::value, - bool = __tuple_like<_Up>::value> +template <class _Tp, class _Up, bool = __tuple_like_ext<__libcpp_remove_reference_t<_Tp> >::value, + bool = __tuple_like_ext<_Up>::value> struct __tuple_constructible : public false_type {}; @@ -90,8 +90,8 @@ struct __tuple_constructible<_Tp, _Up, true, true> // __tuple_assignable -template <class _Tp, class _Up, bool = __tuple_like<__libcpp_remove_reference_t<_Tp> >::value, - bool = __tuple_like<_Up>::value> +template <class _Tp, class _Up, bool = __tuple_like_ext<__libcpp_remove_reference_t<_Tp> >::value, + bool = __tuple_like_ext<_Up>::value> struct __tuple_assignable : public false_type {}; @@ -119,7 +119,7 @@ struct __tuple_like_with_size_imp<true, _SizeTrait, _Expected> template <class _Tuple, size_t _ExpectedSize, class _RawTuple = __libcpp_remove_reference_t<_Tuple> > using __tuple_like_with_size _LIBCPP_NODEBUG = __tuple_like_with_size_imp< - __tuple_like<_RawTuple>::value, + __tuple_like_ext<_RawTuple>::value, tuple_size<_RawTuple>, _ExpectedSize >; diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_element.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_element.h index 2e9d9c738e..1ed996e80f 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_element.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_element.h @@ -10,8 +10,8 @@ #define _LIBCPP___TUPLE_TUPLE_ELEMENT_H #include <__config> -#include <__tuple/tuple_indices.h> -#include <__tuple/tuple_types.h> +#include <__tuple_dir/tuple_indices.h> +#include <__tuple_dir/tuple_types.h> #include <__type_traits/add_const.h> #include <__type_traits/add_cv.h> #include <__type_traits/add_volatile.h> @@ -73,7 +73,6 @@ using __type_pack_element _LIBCPP_NODEBUG = typename decltype( typename __make_tuple_indices<sizeof...(_Types)>::type >{}) )::type; - #else // !defined(__CUDACC__) || !defined(_MSC_VER) template <size_t _Idx, class ..._Types> struct __y_type_pack_element { diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_indices.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_indices.h index 18666d5948..18666d5948 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_indices.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_indices.h diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_like.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_like.h index 3b596916a6..dab395be61 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_like.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_like.h @@ -12,9 +12,10 @@ #include <__config> #include <__fwd/array.h> #include <__fwd/pair.h> +#include <__fwd/subrange.h> #include <__fwd/tuple.h> -#include <__tuple/tuple_types.h> #include <__type_traits/integral_constant.h> +#include <__type_traits/remove_cvref.h> #include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -23,21 +24,27 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct __tuple_like : false_type {}; +#if _LIBCPP_STD_VER >= 20 -template <class _Tp> struct __tuple_like<const _Tp> : public __tuple_like<_Tp> {}; -template <class _Tp> struct __tuple_like<volatile _Tp> : public __tuple_like<_Tp> {}; -template <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_like<_Tp> {}; +template <class _Tp> +struct __tuple_like_impl : false_type {}; -#ifndef _LIBCPP_CXX03_LANG -template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {}; -#endif +template <class... _Tp> +struct __tuple_like_impl<tuple<_Tp...> > : true_type {}; + +template <class _T1, class _T2> +struct __tuple_like_impl<pair<_T1, _T2> > : true_type {}; + +template <class _Tp, size_t _Size> +struct __tuple_like_impl<array<_Tp, _Size> > : true_type {}; -template <class _T1, class _T2> struct __tuple_like<pair<_T1, _T2> > : true_type {}; +template <class _Ip, class _Sp, ranges::subrange_kind _Kp> +struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {}; -template <class _Tp, size_t _Size> struct __tuple_like<array<_Tp, _Size> > : true_type {}; +template <class _Tp> +concept __tuple_like = __tuple_like_impl<remove_cvref_t<_Tp>>::value; -template <class... _Tp> struct __tuple_like<__tuple_types<_Tp...> > : true_type {}; +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_like_ext.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_like_ext.h new file mode 100644 index 0000000000..bf98696112 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_like_ext.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TUPLE_TUPLE_LIKE_EXT_H +#define _LIBCPP___TUPLE_TUPLE_LIKE_EXT_H + +#include <__config> +#include <__fwd/array.h> +#include <__fwd/pair.h> +#include <__fwd/tuple.h> +#include <__tuple_dir/tuple_types.h> +#include <__type_traits/integral_constant.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> struct __tuple_like_ext : false_type {}; + +template <class _Tp> struct __tuple_like_ext<const _Tp> : public __tuple_like_ext<_Tp> {}; +template <class _Tp> struct __tuple_like_ext<volatile _Tp> : public __tuple_like_ext<_Tp> {}; +template <class _Tp> struct __tuple_like_ext<const volatile _Tp> : public __tuple_like_ext<_Tp> {}; + +#ifndef _LIBCPP_CXX03_LANG +template <class... _Tp> struct __tuple_like_ext<tuple<_Tp...> > : true_type {}; +#endif + +template <class _T1, class _T2> struct __tuple_like_ext<pair<_T1, _T2> > : true_type {}; + +template <class _Tp, size_t _Size> struct __tuple_like_ext<array<_Tp, _Size> > : true_type {}; + +template <class... _Tp> struct __tuple_like_ext<__tuple_types<_Tp...> > : true_type {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TUPLE_TUPLE_LIKE_EXT_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_size.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_size.h index 26f9d9725d..d551b2258c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_size.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_size.h @@ -11,7 +11,7 @@ #include <__config> #include <__fwd/tuple.h> -#include <__tuple/tuple_types.h> +#include <__tuple_dir/tuple_types.h> #include <__type_traits/is_const.h> #include <__type_traits/is_volatile.h> #include <cstddef> diff --git a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_types.h b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_types.h index c5be81cce8..c5be81cce8 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__tuple/tuple_types.h +++ b/contrib/libs/cxxsupp/libcxx/include/__tuple_dir/tuple_types.h diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/add_pointer.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/add_pointer.h index 9d0c201007..1af5eca65c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/add_pointer.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/add_pointer.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__add_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template <class _Tp> using __add_pointer_t = __add_pointer(_Tp); @@ -39,7 +39,7 @@ template <class _Tp> struct __add_pointer_impl<_Tp, false> template <class _Tp> using __add_pointer_t = typename __add_pointer_impl<_Tp>::type; -#endif // __has_builtin(__add_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template <class _Tp> struct add_pointer { diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_storage.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_storage.h index a9f1244ed3..c564d58245 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_storage.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_storage.h @@ -83,7 +83,7 @@ struct __find_max_align<__type_list<_Hp, _Tp>, _Len> : public integral_constant<size_t, __select_align<_Len, _Hp::value, __find_max_align<_Tp, _Len>::value>::value> {}; template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value> -struct _LIBCPP_TEMPLATE_VIS aligned_storage +struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage { typedef typename __find_pod<__all_types, _Align>::type _Aligner; union type @@ -94,13 +94,17 @@ struct _LIBCPP_TEMPLATE_VIS aligned_storage }; #if _LIBCPP_STD_VER > 11 + + _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value> - using aligned_storage_t = typename aligned_storage<_Len, _Align>::type; + using aligned_storage_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_storage<_Len, _Align>::type; + _LIBCPP_SUPPRESS_DEPRECATED_POP + #endif #define _CREATE_ALIGNED_STORAGE_SPECIALIZATION(n) \ template <size_t _Len>\ -struct _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n>\ +struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n>\ {\ struct _ALIGNAS(n) type\ {\ diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_union.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_union.h index 31eb9353a9..2c64130da3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_union.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/aligned_union.h @@ -37,7 +37,7 @@ struct __static_max<_I0, _I1, _In...> }; template <size_t _Len, class _Type0, class ..._Types> -struct aligned_union +struct _LIBCPP_DEPRECATED_IN_CXX23 aligned_union { static const size_t alignment_value = __static_max<_LIBCPP_PREFERRED_ALIGNOF(_Type0), _LIBCPP_PREFERRED_ALIGNOF(_Types)...>::value; @@ -47,7 +47,8 @@ struct aligned_union }; #if _LIBCPP_STD_VER > 11 -template <size_t _Len, class ..._Types> using aligned_union_t = typename aligned_union<_Len, _Types...>::type; +template <size_t _Len, class... _Types> +using aligned_union_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_union<_Len, _Types...>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_reference.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_reference.h index 559d39858e..f9195865c8 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_reference.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_reference.h @@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Let COND_RES(X, Y) be: template <class _Xp, class _Yp> using __cond_res = - decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()()); + decltype(false ? std::declval<_Xp(&)()>()() : std::declval<_Yp(&)()>()()); // Let `XREF(A)` denote a unary alias template `T` such that `T<U>` denotes the same type as `U` // with the addition of `A`'s cv and reference qualifiers, for a non-reference cv-unqualified type diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_type.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_type.h index 8009142dfe..6d2df6c9b3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_type.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/common_type.h @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 // Let COND_RES(X, Y) be: template <class _Tp, class _Up> -using __cond_type = decltype(false ? declval<_Tp>() : declval<_Up>()); +using __cond_type = decltype(false ? std::declval<_Tp>() : std::declval<_Up>()); template <class _Tp, class _Up, class = void> struct __common_type3 {}; @@ -47,10 +47,10 @@ struct __common_type2_imp {}; // sub-bullet 3 - "if decay_t<decltype(false ? declval<D1>() : declval<D2>())> ..." template <class _Tp, class _Up> -struct __common_type2_imp<_Tp, _Up, __void_t<decltype(true ? declval<_Tp>() : declval<_Up>())> > +struct __common_type2_imp<_Tp, _Up, __void_t<decltype(true ? std::declval<_Tp>() : std::declval<_Up>())> > { typedef _LIBCPP_NODEBUG typename decay<decltype( - true ? declval<_Tp>() : declval<_Up>() + true ? std::declval<_Tp>() : std::declval<_Up>() )>::type type; }; diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/conjunction.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/conjunction.h index 2802d28452..0d95347e99 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/conjunction.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/conjunction.h @@ -35,7 +35,7 @@ false_type __and_helper(...); // be instantiated) since it is an alias, unlike `conjunction<_Pred...>`, which is a struct. // If you want to defer the evaluation of `_And<_Pred...>` itself, use `_Lazy<_And, _Pred...>`. template <class... _Pred> -using _And _LIBCPP_NODEBUG = decltype(__and_helper<_Pred...>(0)); +using _And _LIBCPP_NODEBUG = decltype(std::__and_helper<_Pred...>(0)); #if _LIBCPP_STD_VER > 14 diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/enable_if.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/enable_if.h index c5e8df45ea..706386deb1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/enable_if.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/enable_if.h @@ -26,6 +26,12 @@ template <bool _Bp, class _Tp = void> using __enable_if_t _LIBCPP_NODEBUG = type template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type; #endif +// CUDA headers use libc++ internals. +#ifdef __CUDACC__ +template <bool _Cond, class _Ret = void> +using __lazy_enable_if _LIBCPP_NODEBUG = __enable_if_t<_Cond, _Ret>; +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_ENABLE_IF_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_allocator.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_allocator.h index 53401e9f4f..ee4154d7e4 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_allocator.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_allocator.h @@ -27,7 +27,7 @@ struct __is_allocator : false_type {}; template<typename _Alloc> struct __is_allocator<_Alloc, __void_t<typename _Alloc::value_type>, - __void_t<decltype(declval<_Alloc&>().allocate(size_t(0)))> + __void_t<decltype(std::declval<_Alloc&>().allocate(size_t(0)))> > : true_type {}; diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_always_bitcastable.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_always_bitcastable.h new file mode 100644 index 0000000000..63304eb492 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_always_bitcastable.h @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_IS_ALWAYS_BITCASTABLE_H +#define _LIBCPP___TYPE_TRAITS_IS_ALWAYS_BITCASTABLE_H + +#include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/remove_cv.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Checks whether an object of type `From` can always be bit-cast to an object of type `To` and represent a valid value +// of type `To`. In other words, `From` and `To` have the same value representation and the set of values of `From` is +// a subset of the set of values of `To`. +// +// Note that types that cannot be assigned to each other using built-in assignment (e.g. arrays) might still be +// considered bit-castable. +template <class _From, class _To> +struct __is_always_bitcastable { + using _UnqualFrom = __remove_cv_t<_From>; + using _UnqualTo = __remove_cv_t<_To>; + + static const bool value = + // First, the simple case -- `From` and `To` are the same object type. + (is_same<_UnqualFrom, _UnqualTo>::value && is_trivially_copyable<_UnqualFrom>::value) || + + // Beyond the simple case, we say that one type is "always bit-castable" to another if: + // - (1) `From` and `To` have the same value representation, and in addition every possible value of `From` has + // a corresponding value in the `To` type (in other words, the set of values of `To` is a superset of the set of + // values of `From`); + // - (2) When the corresponding values are not the same value (as, for example, between an unsigned and a signed + // integer, where a large positive value of the unsigned integer corresponds to a negative value in the signed + // integer type), the value of `To` that results from a bitwise copy of `From` is the same what would be produced + // by the built-in assignment (if it were defined for the two types, to which there are minor exceptions, e.g. + // built-in arrays). + // + // In practice, that means: + // - all integral types (except `bool`, see below) -- that is, character types and `int` types, both signed and + // unsigned... + // - as well as arrays of such types... + // - ...that have the same size. + // + // Other trivially-copyable types can't be validly bit-cast outside of their own type: + // - floating-point types normally have different sizes and thus aren't bit-castable between each other (fails #1); + // - integral types and floating-point types use different representations, so for example bit-casting an integral + // `1` to `float` results in a very small less-than-one value, unlike built-in assignment that produces `1.0` + // (fails #2); + // - booleans normally use only a single bit of their object representation; bit-casting an integer to a boolean + // will result in a boolean object with an incorrect representation, which is undefined behavior (fails #2). + // Bit-casting from a boolean into an integer, however, is valid; + // - enumeration types may have different ranges of possible values (fails #1); + // - for pointers, it is not guaranteed that pointers to different types use the same set of values to represent + // addresses, and the conversion results are explicitly unspecified for types with different alignments + // (fails #1); + // - for structs and unions it is impossible to determine whether the set of values of one of them is a subset of + // the other (fails #1); + // - there is no need to consider `nullptr_t` for practical purposes. + ( + sizeof(_From) == sizeof(_To) && + is_integral<_From>::value && + is_integral<_To>::value && + !is_same<_UnqualTo, bool>::value + ); +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_IS_ALWAYS_BITCASTABLE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_callable.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_callable.h index 73f894dce9..445373c43b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_callable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_callable.h @@ -25,7 +25,7 @@ template<class...> false_type __is_callable_helper(...); template<class _Func, class... _Args> -struct __is_callable : decltype(__is_callable_helper<_Func, _Args...>(0)) {}; +struct __is_callable : decltype(std::__is_callable_helper<_Func, _Args...>(0)) {}; _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_convertible.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_convertible.h index 1085d632a5..5f77fd4d70 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_convertible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_convertible.h @@ -40,7 +40,7 @@ struct __is_convertible_test : public false_type {}; template <class _From, class _To> struct __is_convertible_test<_From, _To, - decltype(__is_convertible_imp::__test_convert<_To>(declval<_From>()))> : public true_type + decltype(__is_convertible_imp::__test_convert<_To>(std::declval<_From>()))> : public true_type {}; template <class _Tp, bool _IsArray = is_array<_Tp>::value, diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_destructible.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_destructible.h index 700b8d591a..87a68bfce2 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_destructible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_destructible.h @@ -48,7 +48,7 @@ template <typename _Tp> struct __is_destructor_wellformed { template <typename _Tp1> static true_type __test ( - typename __is_destructible_apply<decltype(declval<_Tp1&>().~_Tp1())>::type + typename __is_destructible_apply<decltype(std::declval<_Tp1&>().~_Tp1())>::type ); template <typename _Tp1> diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_implicitly_default_constructible.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_implicitly_default_constructible.h index 3643897a2d..b77f94845f 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_implicitly_default_constructible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_implicitly_default_constructible.h @@ -33,12 +33,12 @@ struct __is_implicitly_default_constructible { }; template <class _Tp> -struct __is_implicitly_default_constructible<_Tp, decltype(__test_implicit_default_constructible<_Tp const&>({})), true_type> +struct __is_implicitly_default_constructible<_Tp, decltype(std::__test_implicit_default_constructible<_Tp const&>({})), true_type> : true_type { }; template <class _Tp> -struct __is_implicitly_default_constructible<_Tp, decltype(__test_implicit_default_constructible<_Tp const&>({})), false_type> +struct __is_implicitly_default_constructible<_Tp, decltype(std::__test_implicit_default_constructible<_Tp const&>({})), false_type> : false_type { }; #endif // !C++03 diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_member_pointer.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_member_pointer.h index 2c453c8dc6..23b2288fda 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_member_pointer.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_member_pointer.h @@ -11,6 +11,7 @@ #include <__config> #include <__type_traits/integral_constant.h> +#include <__type_traits/is_member_function_pointer.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_constructible.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_constructible.h index da116a95db..20c6199521 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_constructible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_constructible.h @@ -11,6 +11,10 @@ #include <__config> #include <__type_traits/integral_constant.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_reference.h> +#include <__utility/declval.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,7 +34,7 @@ template <bool, bool, class _Tp, class... _Args> struct __libcpp_is_nothrow_cons template <class _Tp, class... _Args> struct __libcpp_is_nothrow_constructible</*is constructible*/true, /*is reference*/false, _Tp, _Args...> - : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))> + : public integral_constant<bool, noexcept(_Tp(std::declval<_Args>()...))> { }; @@ -39,7 +43,7 @@ void __implicit_conversion_to(_Tp) noexcept { } template <class _Tp, class _Arg> struct __libcpp_is_nothrow_constructible</*is constructible*/true, /*is reference*/true, _Tp, _Arg> - : public integral_constant<bool, noexcept(_VSTD::__implicit_conversion_to<_Tp>(declval<_Arg>()))> + : public integral_constant<bool, noexcept(_VSTD::__implicit_conversion_to<_Tp>(std::declval<_Arg>()))> { }; diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_convertible.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_convertible.h index 712b6f2cf4..a8ca1c4c41 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_convertible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_convertible.h @@ -30,7 +30,7 @@ template <typename _Tp> static void __test_noexcept(_Tp) noexcept; template<typename _Fm, typename _To> -static bool_constant<noexcept(_VSTD::__test_noexcept<_To>(declval<_Fm>()))> +static bool_constant<noexcept(_VSTD::__test_noexcept<_To>(std::declval<_Fm>()))> __is_nothrow_convertible_test(); template <typename _Fm, typename _To> diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_destructible.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_destructible.h index 050362f9f4..03ebf44049 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_destructible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_nothrow_destructible.h @@ -36,7 +36,7 @@ struct __libcpp_is_nothrow_destructible<false, _Tp> template <class _Tp> struct __libcpp_is_nothrow_destructible<true, _Tp> - : public integral_constant<bool, noexcept(declval<_Tp>().~_Tp()) > + : public integral_constant<bool, noexcept(std::declval<_Tp>().~_Tp()) > { }; diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_scalar.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_scalar.h index b72da1806b..6bd80ed3f2 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_scalar.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_scalar.h @@ -14,6 +14,7 @@ #include <__type_traits/is_arithmetic.h> #include <__type_traits/is_enum.h> #include <__type_traits/is_member_pointer.h> +#include <__type_traits/is_null_pointer.h> #include <__type_traits/is_pointer.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_signed.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_signed.h index 92a45e3536..99e5ea00c0 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_signed.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_signed.h @@ -11,6 +11,8 @@ #include <__config> #include <__type_traits/integral_constant.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_integral.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_specialization.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_specialization.h new file mode 100644 index 0000000000..0cc3667425 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_specialization.h @@ -0,0 +1,45 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_IS_SPECIALIZATION +#define _LIBCPP___TYPE_TRAITS_IS_SPECIALIZATION + +// This contains parts of P2098R1 but is based on MSVC STL's implementation. +// +// The paper has been rejected +// We will not pursue P2098R0 (std::is_specialization_of) at this time; we'd +// like to see a solution to this problem, but it requires language evolution +// too. +// +// Since it is expected a real solution will be provided in the future only the +// minimal part is implemented. +// +// Note a cvref qualified _Tp is never considered a specialization. + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +template <class _Tp, template <class...> class _Template> +inline constexpr bool __is_specialization_v = false; // true if and only if _Tp is a specialization of _Template + +template <template <class...> class _Template, class... _Args> +inline constexpr bool __is_specialization_v<_Template<_Args...>, _Template> = true; + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_IS_SPECIALIZATION diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_swappable.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_swappable.h index a131182282..3821de17f6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_swappable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_swappable.h @@ -64,7 +64,7 @@ template <class _Tp, class _Up = _Tp, struct __swappable_with { template <class _LHS, class _RHS> - static decltype(swap(declval<_LHS>(), declval<_RHS>())) + static decltype(swap(std::declval<_LHS>(), std::declval<_RHS>())) __test_swap(int); template <class, class> static __nat __test_swap(long); @@ -84,8 +84,8 @@ template <class _Tp, class _Up = _Tp, bool _Swappable = __swappable_with<_Tp, _U struct __nothrow_swappable_with { static const bool value = #ifndef _LIBCPP_HAS_NO_NOEXCEPT - noexcept(swap(declval<_Tp>(), declval<_Up>())) - && noexcept(swap(declval<_Up>(), declval<_Tp>())); + noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) + && noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())); #else false; #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_trivially_destructible.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_trivially_destructible.h index 2d1c28bd31..2a79840e3c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_trivially_destructible.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_trivially_destructible.h @@ -11,6 +11,7 @@ #include <__config> #include <__type_traits/integral_constant.h> +#include <__type_traits/is_destructible.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_valid_expansion.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_valid_expansion.h index c45db7509e..db7d7e5f1d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_valid_expansion.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_valid_expansion.h @@ -24,7 +24,7 @@ template <template <class...> class, class ...> false_type __sfinae_test_impl(...); template <template <class ...> class _Templ, class ..._Args> -using _IsValidExpansion _LIBCPP_NODEBUG = decltype(__sfinae_test_impl<_Templ, _Args...>(0)); +using _IsValidExpansion _LIBCPP_NODEBUG = decltype(std::__sfinae_test_impl<_Templ, _Args...>(0)); _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_void.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_void.h index a82c2cb442..c626a19814 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_void.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/is_void.h @@ -11,6 +11,8 @@ #include <__config> #include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/promote.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/promote.h index e647dff469..c2af327c64 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/promote.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/promote.h @@ -40,7 +40,7 @@ struct __numeric_type static double __test(double); static long double __test(long double); - typedef decltype(__test(declval<_Tp>())) type; + typedef decltype(__test(std::declval<_Tp>())) type; static const bool value = _IsNotSame<type, void>::value; }; diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/remove_pointer.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/remove_pointer.h index 33ddb7103f..2f810ba666 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__type_traits/remove_pointer.h +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/remove_pointer.h @@ -17,7 +17,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__remove_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) template <class _Tp> struct remove_pointer { using type _LIBCPP_NODEBUG = __remove_pointer(_Tp); @@ -34,7 +34,7 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const volat template <class _Tp> using __remove_pointer_t = typename remove_pointer<_Tp>::type; -#endif // __has_builtin(__remove_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) #if _LIBCPP_STD_VER > 11 template <class _Tp> using remove_pointer_t = __remove_pointer_t<_Tp>; diff --git a/contrib/libs/cxxsupp/libcxx/include/__type_traits/strip_signature.h b/contrib/libs/cxxsupp/libcxx/include/__type_traits/strip_signature.h new file mode 100644 index 0000000000..2bb7393c1e --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__type_traits/strip_signature.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_STRIP_SIGNATURE_H +#define _LIBCPP___TYPE_TRAITS_STRIP_SIGNATURE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template<class _Fp> +struct __strip_signature; + +# if defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L + +template <class _Rp, class... _Args> +struct __strip_signature<_Rp(*)(_Args...)> { + using type = _Rp(_Args...); +}; + +template <class _Rp, class... _Args> +struct __strip_signature<_Rp(*)(_Args...) noexcept> { + using type = _Rp(_Args...); +}; + +# endif // defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L + +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile> { using type = _Rp(_Ap...); }; + +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) &> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const &> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile &> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile &> { using type = _Rp(_Ap...); }; + +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) noexcept> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const noexcept> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile noexcept> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile noexcept> { using type = _Rp(_Ap...); }; + +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) & noexcept> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const & noexcept> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; +template<class _Rp, class _Gp, class ..._Ap> +struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); }; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___TYPE_TRAITS_STRIP_SIGNATURE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/as_const.h b/contrib/libs/cxxsupp/libcxx/include/__utility/as_const.h index e28d7bc1a2..d4a72f43d4 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/as_const.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/as_const.h @@ -10,9 +10,9 @@ #define _LIBCPP___UTILITY_AS_CONST_H #include <__config> +#include <__type_traits/add_const.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/auto_cast.h b/contrib/libs/cxxsupp/libcxx/include/__utility/auto_cast.h index e907944395..381ed0c205 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/auto_cast.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/auto_cast.h @@ -11,7 +11,7 @@ #define _LIBCPP___UTILITY_AUTO_CAST_H #include <__config> -#include <type_traits> +#include <__type_traits/decay.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/cmp.h b/contrib/libs/cxxsupp/libcxx/include/__utility/cmp.h index 3cfd981067..d448a1d084 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/cmp.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/cmp.h @@ -10,10 +10,14 @@ #define _LIBCPP___UTILITY_CMP_H #include <__config> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_signed.h> +#include <__type_traits/make_unsigned.h> #include <__utility/forward.h> #include <__utility/move.h> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/declval.h b/contrib/libs/cxxsupp/libcxx/include/__utility/declval.h index 97fd1eba91..c2f4bec132 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/declval.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/declval.h @@ -27,7 +27,7 @@ _Tp __declval(long); _LIBCPP_SUPPRESS_DEPRECATED_POP template <class _Tp> -decltype(__declval<_Tp>(0)) declval() _NOEXCEPT; +decltype(std::__declval<_Tp>(0)) declval() _NOEXCEPT; _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/exception_guard.h b/contrib/libs/cxxsupp/libcxx/include/__utility/exception_guard.h new file mode 100644 index 0000000000..46f9359a5c --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/exception_guard.h @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___UTILITY_TRANSACTION_H +#define _LIBCPP___UTILITY_TRANSACTION_H + +#include <__assert> +#include <__config> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__utility/exchange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __exception_guard is a helper class for writing code with the strong exception guarantee. +// +// When writing code that can throw an exception, one can store rollback instructions in an +// exception guard so that if an exception is thrown at any point during the lifetime of the +// exception guard, it will be rolled back automatically. When the exception guard is done, one +// must mark it as being complete so it isn't rolled back when the exception guard is destroyed. +// +// Exception guards are not default constructible, they can't be copied or assigned to, but +// they can be moved around for convenience. +// +// __exception_guard is a no-op in -fno-exceptions mode to produce better code-gen. This means +// that we don't provide the strong exception guarantees. However, Clang doesn't generate cleanup +// code with exceptions disabled, so even if we wanted to provide the strong exception guarantees +// we couldn't. This is also only relevant for constructs with a stack of +// -fexceptions > -fno-exceptions > -fexceptions code, since the exception can't be caught where +// exceptions are disabled. While -fexceptions > -fno-exceptions is quite common +// (e.g. libc++.dylib > -fno-exceptions), having another layer with exceptions enabled seems a lot +// less common, especially one that tries to catch an exception through -fno-exceptions code. +// +// __exception_guard can help greatly simplify code that would normally be cluttered by +// `#if _LIBCPP_NO_EXCEPTIONS`. For example: +// +// template <class Iterator, class Size, class OutputIterator> +// Iterator uninitialized_copy_n(Iterator iter, Size n, OutputIterator out) { +// typedef typename iterator_traits<Iterator>::value_type value_type; +// __exception_guard guard([start=out, &out] { +// std::destroy(start, out); +// }); +// +// for (; n > 0; ++iter, ++out, --n) { +// ::new ((void*)std::addressof(*out)) value_type(*iter); +// } +// guard.__complete(); +// return out; +// } +// + +#ifndef _LIBCPP_NO_EXCEPTIONS +template <class _Rollback> +struct __exception_guard_exceptions { + __exception_guard_exceptions() = delete; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __exception_guard_exceptions(_Rollback __rollback) + : __rollback_(std::move(__rollback)), __completed_(false) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + __exception_guard_exceptions(__exception_guard_exceptions&& __other) + _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) + : __rollback_(std::move(__other.__rollback_)), __completed_(__other.__completed_) { + __other.__completed_ = true; + } + + __exception_guard_exceptions(__exception_guard_exceptions const&) = delete; + __exception_guard_exceptions& operator=(__exception_guard_exceptions const&) = delete; + __exception_guard_exceptions& operator=(__exception_guard_exceptions&&) = delete; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __complete() _NOEXCEPT { __completed_ = true; } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__exception_guard_exceptions() { + if (!__completed_) + __rollback_(); + } + +private: + _Rollback __rollback_; + bool __completed_; +}; + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard_exceptions); + +template <class _Rollback> +using __exception_guard = __exception_guard_exceptions<_Rollback>; +#else // _LIBCPP_NO_EXCEPTIONS +template <class _Rollback> +struct __exception_guard_noexceptions { + __exception_guard_noexceptions() = delete; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + _LIBCPP_NODEBUG explicit __exception_guard_noexceptions(_Rollback) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG + __exception_guard_noexceptions(__exception_guard_noexceptions&& __other) + _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) + : __completed_(__other.__completed_) { + __other.__completed_ = true; + } + + __exception_guard_noexceptions(__exception_guard_noexceptions const&) = delete; + __exception_guard_noexceptions& operator=(__exception_guard_noexceptions const&) = delete; + __exception_guard_noexceptions& operator=(__exception_guard_noexceptions&&) = delete; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG void __complete() _NOEXCEPT { + __completed_ = true; + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG ~__exception_guard_noexceptions() { + _LIBCPP_ASSERT(__completed_, "__exception_guard not completed with exceptions disabled"); + } + +private: + bool __completed_ = false; +}; + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard_noexceptions); + +template <class _Rollback> +using __exception_guard = __exception_guard_noexceptions<_Rollback>; +#endif // _LIBCPP_NO_EXCEPTIONS + +template <class _Rollback> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __exception_guard<_Rollback> __make_exception_guard(_Rollback __rollback) { + return __exception_guard<_Rollback>(std::move(__rollback)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___UTILITY_TRANSACTION_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/exchange.h b/contrib/libs/cxxsupp/libcxx/include/__utility/exchange.h index 6838fc8c62..8df71a17b1 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/exchange.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/exchange.h @@ -10,9 +10,10 @@ #define _LIBCPP___UTILITY_EXCHANGE_H #include <__config> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/forward.h b/contrib/libs/cxxsupp/libcxx/include/__utility/forward.h index 4e254e0fa0..010f2362bd 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/forward.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/forward.h @@ -21,14 +21,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _Tp&& -forward(__libcpp_remove_reference_t<_Tp>& __t) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp&& +forward(_LIBCPP_LIFETIMEBOUND __libcpp_remove_reference_t<_Tp>& __t) _NOEXCEPT { return static_cast<_Tp&&>(__t); } template <class _Tp> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _Tp&& -forward(__libcpp_remove_reference_t<_Tp>&& __t) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp&& +forward(_LIBCPP_LIFETIMEBOUND __libcpp_remove_reference_t<_Tp>&& __t) _NOEXCEPT { static_assert(!is_lvalue_reference<_Tp>::value, "cannot forward an rvalue as an lvalue"); return static_cast<_Tp&&>(__t); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/forward_like.h b/contrib/libs/cxxsupp/libcxx/include/__utility/forward_like.h index 1446964da5..7bb0d7d203 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/forward_like.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/forward_like.h @@ -34,7 +34,8 @@ template <class _Ap, class _Bp> using _ForwardLike = _OverrideRef<_Ap&&, _CopyConst<remove_reference_t<_Ap>, remove_reference_t<_Bp>>>; template <class _Tp, class _Up> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto forward_like(_Up&& __ux) noexcept -> _ForwardLike<_Tp, _Up> { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto forward_like(_LIBCPP_LIFETIMEBOUND _Up&& __ux) noexcept + -> _ForwardLike<_Tp, _Up> { return static_cast<_ForwardLike<_Tp, _Up>>(__ux); } diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/in_place.h b/contrib/libs/cxxsupp/libcxx/include/__utility/in_place.h index bedd9e1e00..a3518455e2 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/in_place.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/in_place.h @@ -10,7 +10,8 @@ #define _LIBCPP___UTILITY_IN_PLACE_H #include <__config> -#include <type_traits> +#include <__type_traits/remove_cvref.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/integer_sequence.h b/contrib/libs/cxxsupp/libcxx/include/__utility/integer_sequence.h index 87c76e9d92..257b4301c0 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/integer_sequence.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/integer_sequence.h @@ -10,7 +10,8 @@ #define _LIBCPP___UTILITY_INTEGER_SEQUENCE_H #include <__config> -#include <type_traits> +#include <__type_traits/is_integral.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -137,6 +138,14 @@ template<size_t _Np> template<class... _Tp> using index_sequence_for = make_index_sequence<sizeof...(_Tp)>; +# if _LIBCPP_STD_VER > 17 +// Executes __func for every element in an index_sequence. +template <size_t... _Index, class _Function> +_LIBCPP_HIDE_FROM_ABI constexpr void __for_each_index_sequence(index_sequence<_Index...>, _Function __func) { + (__func.template operator()<_Index>(), ...); +} +# endif // _LIBCPP_STD_VER > 17 + #endif // _LIBCPP_STD_VER > 11 _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/move.h b/contrib/libs/cxxsupp/libcxx/include/__utility/move.h index 522673005b..4859c39e8b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/move.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/move.h @@ -11,7 +11,10 @@ #define _LIBCPP___UTILITY_MOVE_H #include <__config> -#include <type_traits> +#include <__type_traits/conditional.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/remove_reference.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,8 +23,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __libcpp_remove_reference_t<_Tp>&& -move(_Tp&& __t) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __libcpp_remove_reference_t<_Tp>&& +move(_LIBCPP_LIFETIMEBOUND _Tp&& __t) _NOEXCEPT { typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tp> _Up; return static_cast<_Up&&>(__t); } @@ -31,9 +34,9 @@ using __move_if_noexcept_result_t = __conditional_t<!is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value, const _Tp&, _Tp&&>; template <class _Tp> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 __move_if_noexcept_result_t<_Tp> -move_if_noexcept(_Tp& __x) _NOEXCEPT { - return _VSTD::move(__x); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __move_if_noexcept_result_t<_Tp> +move_if_noexcept(_LIBCPP_LIFETIMEBOUND _Tp& __x) _NOEXCEPT { + return std::move(__x); } _LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/pair.h b/contrib/libs/cxxsupp/libcxx/include/__utility/pair.h index d928689118..8151674bcc 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/pair.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/pair.h @@ -15,16 +15,33 @@ #include <__functional/unwrap_ref.h> #include <__fwd/get.h> #include <__fwd/tuple.h> -#include <__tuple/sfinae_helpers.h> -#include <__tuple/tuple_element.h> -#include <__tuple/tuple_indices.h> -#include <__tuple/tuple_size.h> +#include <__tuple_dir/sfinae_helpers.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_indices.h> +#include <__tuple_dir/tuple_size.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/common_type.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_implicitly_default_constructible.h> +#include <__type_traits/is_move_assignable.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_assignable.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/nat.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/rel_ops.h b/contrib/libs/cxxsupp/libcxx/include/__utility/rel_ops.h index 2577e94e91..5f8d42c0b2 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/rel_ops.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/rel_ops.h @@ -10,9 +10,6 @@ #define _LIBCPP___UTILITY_REL_OPS_H #include <__config> -#include <__utility/forward.h> -#include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/swap.h b/contrib/libs/cxxsupp/libcxx/include/__utility/swap.h index 545614aeca..0843b35a8b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/swap.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/swap.h @@ -10,10 +10,14 @@ #define _LIBCPP___UTILITY_SWAP_H #include <__config> +#include <__type_traits/is_move_assignable.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_swappable.h> #include <__utility/declval.h> #include <__utility/move.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/to_underlying.h b/contrib/libs/cxxsupp/libcxx/include/__utility/to_underlying.h index 3428406e8d..a194d3ef28 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/to_underlying.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/to_underlying.h @@ -11,7 +11,7 @@ #define _LIBCPP___UTILITY_TO_UNDERLYING_H #include <__config> -#include <type_traits> +#include <__type_traits/underlying_type.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/transaction.h b/contrib/libs/cxxsupp/libcxx/include/__utility/transaction.h deleted file mode 100644 index dc65c349d1..0000000000 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/transaction.h +++ /dev/null @@ -1,97 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___UTILITY_TRANSACTION_H -#define _LIBCPP___UTILITY_TRANSACTION_H - -#include <__config> -#include <__utility/exchange.h> -#include <__utility/move.h> -#include <type_traits> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -// __transaction is a helper class for writing code with the strong exception guarantee. -// -// When writing code that can throw an exception, one can store rollback instructions in a -// transaction so that if an exception is thrown at any point during the lifetime of the -// transaction, it will be rolled back automatically. When the transaction is done, one -// must mark it as being complete so it isn't rolled back when the transaction is destroyed. -// -// Transactions are not default constructible, they can't be copied or assigned to, but -// they can be moved around for convenience. -// -// __transaction can help greatly simplify code that would normally be cluttered by -// `#if _LIBCPP_NO_EXCEPTIONS`. For example: -// -// template <class Iterator, class Size, class OutputIterator> -// Iterator uninitialized_copy_n(Iterator iter, Size n, OutputIterator out) { -// typedef typename iterator_traits<Iterator>::value_type value_type; -// __transaction transaction([start=out, &out] { -// std::destroy(start, out); -// }); -// -// for (; n > 0; ++iter, ++out, --n) { -// ::new ((void*)std::addressof(*out)) value_type(*iter); -// } -// transaction.__complete(); -// return out; -// } -// -template <class _Rollback> -struct __transaction { - __transaction() = delete; - - _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __transaction(_Rollback __rollback) - : __rollback_(_VSTD::move(__rollback)) - , __completed_(false) - { } - - _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX20 __transaction(__transaction&& __other) - _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) - : __rollback_(_VSTD::move(__other.__rollback_)) - , __completed_(__other.__completed_) - { - __other.__completed_ = true; - } - - __transaction(__transaction const&) = delete; - __transaction& operator=(__transaction const&) = delete; - __transaction& operator=(__transaction&&) = delete; - - _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX20 void __complete() _NOEXCEPT { - __completed_ = true; - } - - _LIBCPP_HIDE_FROM_ABI - _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__transaction() { - if (!__completed_) - __rollback_(); - } - -private: - _Rollback __rollback_; - bool __completed_; -}; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__transaction); - -template <class _Rollback> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __transaction<_Rollback> __make_transaction(_Rollback __rollback) { - return __transaction<_Rollback>(std::move(__rollback)); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___UTILITY_TRANSACTION_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__utility/unreachable.h b/contrib/libs/cxxsupp/libcxx/include/__utility/unreachable.h index 485edb227c..d93e60b10b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__utility/unreachable.h +++ b/contrib/libs/cxxsupp/libcxx/include/__utility/unreachable.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___UTILITY_UNREACHABLE_H #define _LIBCPP___UTILITY_UNREACHABLE_H +#include <__assert> #include <__config> -#include <cstdlib> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -18,21 +18,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __libcpp_unreachable() -{ -#if __has_builtin(__builtin_unreachable) - __builtin_unreachable(); -#else - std::abort(); -#endif +_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __libcpp_unreachable() { + _LIBCPP_ASSERT(false, "std::unreachable() was reached"); + __builtin_unreachable(); } #if _LIBCPP_STD_VER > 20 [[noreturn]] _LIBCPP_HIDE_FROM_ABI inline void unreachable() { __libcpp_unreachable(); } -#endif // _LIBCPP_STD_VER > 20 +#endif _LIBCPP_END_NAMESPACE_STD -#endif +#endif // _LIBCPP___UTILITY_UNREACHABLE_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__verbose_abort b/contrib/libs/cxxsupp/libcxx/include/__verbose_abort index fddef4900e..a16d75d5ac 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__verbose_abort +++ b/contrib/libs/cxxsupp/libcxx/include/__verbose_abort @@ -17,35 +17,41 @@ # pragma GCC system_header #endif -// Provide a default implementation of __libcpp_verbose_abort if we know that neither the built -// library nor the user is providing one. Otherwise, just declare it and use the one from the -// built library or the one provided by the user. -// -// We can't provide a great implementation because it needs to be pretty much -// dependency-free (this is included everywhere else in the library). -#if defined(_LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) && !defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED) - -extern "C" void abort(); - -_LIBCPP_BEGIN_NAMESPACE_STD - -_LIBCPP_NORETURN _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) _LIBCPP_HIDE_FROM_ABI inline -void __libcpp_verbose_abort(const char *, ...) { - ::abort(); - __builtin_unreachable(); // never reached, but needed to tell the compiler that the function never returns -} - -_LIBCPP_END_NAMESPACE_STD - -#else - _LIBCPP_BEGIN_NAMESPACE_STD +// This function should never be called directly from the code -- it should only be called through +// the _LIBCPP_VERBOSE_ABORT macro. _LIBCPP_NORETURN _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) void __libcpp_verbose_abort(const char *__format, ...); -_LIBCPP_END_NAMESPACE_STD +// _LIBCPP_VERBOSE_ABORT(format, args...) +// +// This macro is used to abort the program abnormally while providing additional diagnostic information. +// +// The first argument is a printf-style format string, and the remaining arguments are values to format +// into the format-string. This macro can be customized by users to provide fine-grained control over +// how verbose termination is triggered. +// +// If the user does not supply their own version of the _LIBCPP_VERBOSE_ABORT macro, we pick the default +// behavior based on whether we know the built library we're running against provides support for the +// verbose termination handler or not. If it does, we call it. If it doesn't, we call __builtin_abort to +// make sure that the program terminates but without taking any complex dependencies in this header. +#if !defined(_LIBCPP_VERBOSE_ABORT) + +// Support _LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED until LLVM 18, but tell people +// to move to customizing _LIBCPP_VERBOSE_ABORT instead. +# if defined(_LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) && defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED) +# undef _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY +# warning _LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED is deprecated, please customize _LIBCPP_VERBOSE_ABORT instead +# endif + +# if defined(_LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) +# define _LIBCPP_VERBOSE_ABORT(...) __builtin_abort() +# else +# define _LIBCPP_VERBOSE_ABORT(...) ::std::__libcpp_verbose_abort(__VA_ARGS__) +# endif +#endif // !defined(_LIBCPP_VERBOSE_ABORT) -#endif +_LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___VERBOSE_ABORT diff --git a/contrib/libs/cxxsupp/libcxx/include/algorithm b/contrib/libs/cxxsupp/libcxx/include/algorithm index 85639ec448..a4351eaf9c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/algorithm +++ b/contrib/libs/cxxsupp/libcxx/include/algorithm @@ -1704,11 +1704,9 @@ template <class BidirectionalIterator, class Compare> */ #include <__assert> // all public C++ headers provide the assertion handler -#include <__bits> #include <__config> #include <__debug> #include <cstddef> -#include <cstring> #include <type_traits> #include <version> @@ -1918,6 +1916,7 @@ template <class BidirectionalIterator, class Compare> #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> # include <concepts> +# include <cstring> # include <iterator> # include <memory> # include <stdexcept> diff --git a/contrib/libs/cxxsupp/libcxx/include/any b/contrib/libs/cxxsupp/libcxx/include/any index ec5171ff71..50a44d7f4d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/any +++ b/contrib/libs/cxxsupp/libcxx/include/any @@ -138,7 +138,9 @@ add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT; namespace __any_imp { + _LIBCPP_SUPPRESS_DEPRECATED_PUSH using _Buffer = aligned_storage_t<3*sizeof(void*), alignment_of<void*>::value>; + _LIBCPP_SUPPRESS_DEPRECATED_POP template <class _Tp> using _IsSmallObject = integral_constant<bool @@ -173,7 +175,7 @@ namespace __any_imp inline _LIBCPP_INLINE_VISIBILITY bool __compare_typeid(type_info const* __id, const void* __fallback_id) { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) if (__id && *__id == typeid(_Tp)) return true; #endif @@ -292,7 +294,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool has_value() const _NOEXCEPT { return __h_ != nullptr; } -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) _LIBCPP_INLINE_VISIBILITY const type_info & type() const _NOEXCEPT { if (__h_) { @@ -424,7 +426,7 @@ namespace __any_imp _LIBCPP_INLINE_VISIBILITY static void* __type_info() { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); #else return nullptr; @@ -512,7 +514,7 @@ namespace __any_imp _LIBCPP_INLINE_VISIBILITY static void* __type_info() { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); #else return nullptr; @@ -678,7 +680,7 @@ any_cast(any * __any) _NOEXCEPT typedef add_pointer_t<_ValueType> _ReturnType; if (__any && __any->__h_) { void *__p = __any->__call(_Action::_Get, nullptr, -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) &typeid(_ValueType), #else nullptr, diff --git a/contrib/libs/cxxsupp/libcxx/include/array b/contrib/libs/cxxsupp/libcxx/include/array index cb1a6d1202..068a6bd4cc 100644 --- a/contrib/libs/cxxsupp/libcxx/include/array +++ b/contrib/libs/cxxsupp/libcxx/include/array @@ -115,7 +115,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__iterator/reverse_iterator.h> -#include <__tuple/sfinae_helpers.h> +#include <__tuple_dir/sfinae_helpers.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> #include <__utility/unreachable.h> @@ -137,8 +137,8 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce #include <initializer_list> // [tuple.helper] -#include <__tuple/tuple_element.h> -#include <__tuple/tuple_size.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_size.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/atomic b/contrib/libs/cxxsupp/libcxx/include/atomic index fac146537d..d0d682da62 100644 --- a/contrib/libs/cxxsupp/libcxx/include/atomic +++ b/contrib/libs/cxxsupp/libcxx/include/atomic @@ -377,23 +377,23 @@ template<class T> memory_order) noexcept; template<class T> - void atomic_wait(const volatile atomic<T>*, atomic<T>::value_type); + void atomic_wait(const volatile atomic<T>*, atomic<T>::value_type) noexcept; template<class T> - void atomic_wait(const atomic<T>*, atomic<T>::value_type); + void atomic_wait(const atomic<T>*, atomic<T>::value_type) noexcept; template<class T> void atomic_wait_explicit(const volatile atomic<T>*, atomic<T>::value_type, - memory_order); + memory_order) noexcept; template<class T> void atomic_wait_explicit(const atomic<T>*, atomic<T>::value_type, - memory_order); + memory_order) noexcept; template<class T> - void atomic_notify_one(volatile atomic<T>*); + void atomic_notify_one(volatile atomic<T>*) noexcept; template<class T> - void atomic_notify_one(atomic<T>*); + void atomic_notify_one(atomic<T>*) noexcept; template<class T> - void atomic_notify_all(volatile atomic<T>*); + void atomic_notify_all(volatile atomic<T>*) noexcept; template<class T> - void atomic_notify_all(atomic<T>*); + void atomic_notify_all(atomic<T>*) noexcept; // Atomics for standard typedef types @@ -524,10 +524,19 @@ template <class T> #include <__config> #include <__thread/poll_with_backoff.h> #include <__thread/timed_backoff_policy.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_pointer.h> +#include <__type_traits/underlying_type.h> #include <cstddef> #include <cstdint> #include <cstring> -#include <type_traits> #include <version> #ifndef _LIBCPP_HAS_NO_THREADS @@ -1452,10 +1461,10 @@ struct __libcpp_atomic_wait_backoff_impl { { if(__elapsed > chrono::microseconds(64)) { - auto const __monitor = __libcpp_atomic_monitor(__a); + auto const __monitor = std::__libcpp_atomic_monitor(__a); if(__test_fn()) return true; - __libcpp_atomic_wait(__a, __monitor); + std::__libcpp_atomic_wait(__a, __monitor); } else if(__elapsed > chrono::microseconds(4)) __libcpp_thread_yield(); @@ -1470,7 +1479,7 @@ _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Fn && __test_fn) { __libcpp_atomic_wait_backoff_impl<_Atp, typename decay<_Fn>::type> __backoff_fn = {__a, __test_fn}; - return __libcpp_thread_poll_with_backoff(__test_fn, __backoff_fn); + return std::__libcpp_thread_poll_with_backoff(__test_fn, __backoff_fn); } #else // _LIBCPP_HAS_NO_THREADS @@ -1494,7 +1503,7 @@ struct __cxx_atomic_wait_test_fn_impl { memory_order __order; _LIBCPP_INLINE_VISIBILITY bool operator()() const { - return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__a, __order), __val); + return !std::__cxx_nonatomic_compare_equal(std::__cxx_atomic_load(__a, __order), __val); } }; @@ -1503,7 +1512,7 @@ _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Tp const __val, memory_order __order) { __cxx_atomic_wait_test_fn_impl<_Atp, _Tp> __test_fn = {__a, __val, __order}; - return __cxx_atomic_wait(__a, __test_fn); + return std::__cxx_atomic_wait(__a, __test_fn); } // general atomic<T> @@ -1526,78 +1535,78 @@ struct __atomic_base // false _LIBCPP_INLINE_VISIBILITY void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) - {__cxx_atomic_store(&__a_, __d, __m);} + {std::__cxx_atomic_store(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) - {__cxx_atomic_store(&__a_, __d, __m);} + {std::__cxx_atomic_store(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) - {return __cxx_atomic_load(&__a_, __m);} + {return std::__cxx_atomic_load(&__a_, __m);} _LIBCPP_INLINE_VISIBILITY _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) - {return __cxx_atomic_load(&__a_, __m);} + {return std::__cxx_atomic_load(&__a_, __m);} _LIBCPP_INLINE_VISIBILITY operator _Tp() const volatile _NOEXCEPT {return load();} _LIBCPP_INLINE_VISIBILITY operator _Tp() const _NOEXCEPT {return load();} _LIBCPP_INLINE_VISIBILITY _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_exchange(&__a_, __d, __m);} + {return std::__cxx_atomic_exchange(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_exchange(&__a_, __d, __m);} + {return std::__cxx_atomic_exchange(&__a_, __d, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} + {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} + {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} + {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} + {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} + {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} + {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} + {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} _LIBCPP_INLINE_VISIBILITY bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} + {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT - {__cxx_atomic_wait(&__a_, __v, __m);} + {std::__cxx_atomic_wait(&__a_, __v, __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT - {__cxx_atomic_wait(&__a_, __v, __m);} + {std::__cxx_atomic_wait(&__a_, __v, __m);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() volatile _NOEXCEPT - {__cxx_atomic_notify_one(&__a_);} + {std::__cxx_atomic_notify_one(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() _NOEXCEPT - {__cxx_atomic_notify_one(&__a_);} + {std::__cxx_atomic_notify_one(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() volatile _NOEXCEPT - {__cxx_atomic_notify_all(&__a_);} + {std::__cxx_atomic_notify_all(&__a_);} _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() _NOEXCEPT - {__cxx_atomic_notify_all(&__a_);} + {std::__cxx_atomic_notify_all(&__a_);} #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY constexpr @@ -1634,34 +1643,34 @@ struct __atomic_base<_Tp, true> _LIBCPP_INLINE_VISIBILITY _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_fetch_sub(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_fetch_and(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_and(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_fetch_and(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_and(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_fetch_or(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_or(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_fetch_or(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_or(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_fetch_xor(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_xor(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_fetch_xor(&this->__a_, __op, __m);} + {return std::__cxx_atomic_fetch_xor(&this->__a_, __op, __m);} _LIBCPP_INLINE_VISIBILITY _Tp operator++(int) volatile _NOEXCEPT {return fetch_add(_Tp(1));} @@ -1760,28 +1769,28 @@ struct atomic<_Tp*> _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return __cxx_atomic_fetch_add(&this->__a_, __op, __m); + return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return __cxx_atomic_fetch_add(&this->__a_, __op, __m); + return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return __cxx_atomic_fetch_sub(&this->__a_, __op, __m); + return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return __cxx_atomic_fetch_sub(&this->__a_, __op, __m); + return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m); } _LIBCPP_INLINE_VISIBILITY @@ -1838,7 +1847,7 @@ _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY void atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { - __cxx_atomic_init(&__o->__a_, __d); + std::__cxx_atomic_init(&__o->__a_, __d); } template <class _Tp> @@ -1846,7 +1855,7 @@ _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { - __cxx_atomic_init(&__o->__a_, __d); + std::__cxx_atomic_init(&__o->__a_, __d); } // atomic_store @@ -2099,7 +2108,7 @@ void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT __o->notify_one(); } -// atomic_notify_one +// atomic_notify_all template <class _Tp> _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY @@ -2655,13 +2664,10 @@ typedef atomic<__libcpp_unsigned_lock_free> atomic_unsigned_lock_free; _LIBCPP_END_NAMESPACE_STD -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 -# include <chrono> -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <cmath> # include <compare> +# include <type_traits> #endif #endif // _LIBCPP_ATOMIC diff --git a/contrib/libs/cxxsupp/libcxx/include/barrier b/contrib/libs/cxxsupp/libcxx/include/barrier index a2f753677b..2e8906b713 100644 --- a/contrib/libs/cxxsupp/libcxx/include/barrier +++ b/contrib/libs/cxxsupp/libcxx/include/barrier @@ -125,7 +125,7 @@ public: _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY __barrier_base(ptrdiff_t __expected, _CompletionF __completion = _CompletionF()) - : __expected_(__expected), __base_(__construct_barrier_algorithm_base(this->__expected_), + : __expected_(__expected), __base_(std::__construct_barrier_algorithm_base(this->__expected_), &__destroy_barrier_algorithm_base), __expected_adjustment_(0), __completion_(std::move(__completion)), __phase_(0) { @@ -150,7 +150,7 @@ public: auto const __test_fn = [this, __old_phase]() -> bool { return __phase_.load(memory_order_acquire) != __old_phase; }; - __libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy()); + std::__libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy()); } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void arrive_and_drop() diff --git a/contrib/libs/cxxsupp/libcxx/include/bit b/contrib/libs/cxxsupp/libcxx/include/bit index d2061d3e6f..d17a6e45f0 100644 --- a/contrib/libs/cxxsupp/libcxx/include/bit +++ b/contrib/libs/cxxsupp/libcxx/include/bit @@ -63,193 +63,29 @@ namespace std { #include <__assert> // all public C++ headers provide the assertion handler #include <__bit/bit_cast.h> +#include <__bit/bit_ceil.h> +#include <__bit/bit_floor.h> +#include <__bit/bit_log2.h> +#include <__bit/bit_width.h> +#include <__bit/blsr.h> #include <__bit/byteswap.h> -#include <__bits> // __libcpp_clz -#include <__concepts/arithmetic.h> +#include <__bit/countl.h> +#include <__bit/countr.h> +#include <__bit/endian.h> +#include <__bit/has_single_bit.h> +#include <__bit/popcount.h> +#include <__bit/rotate.h> #include <__config> -#include <limits> -#include <type_traits> #include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -_LIBCPP_BEGIN_NAMESPACE_STD - -template<class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -_Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT -{ - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type"); - const unsigned int __dig = numeric_limits<_Tp>::digits; - if ((__cnt % __dig) == 0) - return __t; - return (__t >> (__cnt % __dig)) | (__t << (__dig - (__cnt % __dig))); -} - -template<class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 -int __countl_zero(_Tp __t) _NOEXCEPT -{ - static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type"); - if (__t == 0) - return numeric_limits<_Tp>::digits; - - if (sizeof(_Tp) <= sizeof(unsigned int)) - return std::__libcpp_clz(static_cast<unsigned int>(__t)) - - (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits); - else if (sizeof(_Tp) <= sizeof(unsigned long)) - return std::__libcpp_clz(static_cast<unsigned long>(__t)) - - (numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits); - else if (sizeof(_Tp) <= sizeof(unsigned long long)) - return std::__libcpp_clz(static_cast<unsigned long long>(__t)) - - (numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits); - else - { - int __ret = 0; - int __iter = 0; - const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits; - while (true) { - __t = std::__rotr(__t, __ulldigits); - if ((__iter = std::__countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits) - break; - __ret += __iter; - } - return __ret + __iter; - } -} - -#if _LIBCPP_STD_VER > 17 - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { - const unsigned int __dig = numeric_limits<_Tp>::digits; - if ((__cnt % __dig) == 0) - return __t; - return (__t << (__cnt % __dig)) | (__t >> (__dig - (__cnt % __dig))); -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { - return std::__rotr(__t, __cnt); -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { - return std::__countl_zero(__t); -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { - return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { - if (__t == 0) - return numeric_limits<_Tp>::digits; - - if (sizeof(_Tp) <= sizeof(unsigned int)) - return std::__libcpp_ctz(static_cast<unsigned int>(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long)) - return std::__libcpp_ctz(static_cast<unsigned long>(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long long)) - return std::__libcpp_ctz(static_cast<unsigned long long>(__t)); - else { - int __ret = 0; - const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits; - while (static_cast<unsigned long long>(__t) == 0uLL) { - __ret += __ulldigits; - __t >>= __ulldigits; - } - return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t)); - } -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { - return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { - if (sizeof(_Tp) <= sizeof(unsigned int)) - return std::__libcpp_popcount(static_cast<unsigned int>(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long)) - return std::__libcpp_popcount(static_cast<unsigned long>(__t)); - else if (sizeof(_Tp) <= sizeof(unsigned long long)) - return std::__libcpp_popcount(static_cast<unsigned long long>(__t)); - else { - int __ret = 0; - while (__t != 0) { - __ret += std::__libcpp_popcount(static_cast<unsigned long long>(__t)); - __t >>= numeric_limits<unsigned long long>::digits; - } - return __ret; - } -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { - return __t != 0 && (((__t & (__t - 1)) == 0)); -} - -// integral log base 2 -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept { - return numeric_limits<_Tp>::digits - 1 - std::countl_zero(__t); -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { - return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { - if (__t < 2) - return 1; - const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u)); - _LIBCPP_ASSERT(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); - - if constexpr (sizeof(_Tp) >= sizeof(unsigned)) - return _Tp{1} << __n; - else { - const unsigned __extra = numeric_limits<unsigned>::digits - numeric_limits<_Tp>::digits; - const unsigned __retVal = 1u << (__n + __extra); - return (_Tp)(__retVal >> __extra); - } -} - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { - return __t == 0 ? 0 : std::__bit_log2(__t) + 1; -} - -enum class endian { - little = 0xDEAD, - big = 0xFACE, -# if defined(_LIBCPP_LITTLE_ENDIAN) - native = little -# elif defined(_LIBCPP_BIG_ENDIAN) - native = big -# else - native = 0xCAFE -# endif -}; - -#endif // _LIBCPP_STD_VER > 17 - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <iosfwd> +# include <limits> +# include <type_traits> #endif #endif // _LIBCPP_BIT diff --git a/contrib/libs/cxxsupp/libcxx/include/charconv b/contrib/libs/cxxsupp/libcxx/include/charconv index 4063117b30..9c74ce3c69 100644 --- a/contrib/libs/cxxsupp/libcxx/include/charconv +++ b/contrib/libs/cxxsupp/libcxx/include/charconv @@ -80,7 +80,7 @@ namespace std { #include <__algorithm/copy_n.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> -#include <__bits> +#include <__bit/countl.h> #include <__charconv/chars_format.h> #include <__charconv/from_chars_result.h> #include <__charconv/tables.h> @@ -231,7 +231,7 @@ template <typename _Tp, typename _Up> inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed(_Tp __a, _Up __b, _Tp& __r) { - return __mul_overflowed(__a, static_cast<_Tp>(__b), __r); + return __itoa::__mul_overflowed(__a, static_cast<_Tp>(__b), __r); } template <typename _Tp> @@ -257,7 +257,7 @@ struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1, __cprod[__i]); - if (__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) + if (__itoa::__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) --__p; return __p; } @@ -284,16 +284,20 @@ __complement(_Tp __x) template <typename _Tp> inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type); + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) { - auto __x = __to_unsigned_like(__value); + auto __x = std::__to_unsigned_like(__value); if (__value < 0 && __first != __last) { *__first++ = '-'; - __x = __complement(__x); + __x = std::__complement(__x); } - return __to_chars_itoa(__first, __last, __x, false_type()); + return std::__to_chars_itoa(__first, __last, __x, false_type()); } template <typename _Tp> @@ -331,19 +335,23 @@ __to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) } #endif +template <class _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type); + template <typename _Tp> inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, true_type) { - auto __x = __to_unsigned_like(__value); + auto __x = std::__to_unsigned_like(__value); if (__value < 0 && __first != __last) { *__first++ = '-'; - __x = __complement(__x); + __x = std::__complement(__x); } - return __to_chars_integral(__first, __last, __x, __base, false_type()); + return std::__to_chars_integral(__first, __last, __x, __base, false_type()); } namespace __itoa { @@ -521,19 +529,19 @@ __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type) { if (__base == 10) [[likely]] - return __to_chars_itoa(__first, __last, __value, false_type()); + return std::__to_chars_itoa(__first, __last, __value, false_type()); switch (__base) { case 2: - return __to_chars_integral<2>(__first, __last, __value); + return std::__to_chars_integral<2>(__first, __last, __value); case 8: - return __to_chars_integral<8>(__first, __last, __value); + return std::__to_chars_integral<8>(__first, __last, __value); case 16: - return __to_chars_integral<16>(__first, __last, __value); + return std::__to_chars_integral<16>(__first, __last, __value); } ptrdiff_t __cap = __last - __first; - int __n = __to_chars_integral_width(__value, __base); + int __n = std::__to_chars_integral_width(__value, __base); if (__n > __cap) return {__last, errc::value_too_large}; @@ -571,7 +579,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result __sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) { using __tl = numeric_limits<_Tp>; - decltype(__to_unsigned_like(__value)) __x; + decltype(std::__to_unsigned_like(__value)) __x; bool __neg = (__first != __last && *__first == '-'); auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...); @@ -587,16 +595,16 @@ __sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) if (__neg) { - if (__x <= __complement(__to_unsigned_like(__tl::min()))) + if (__x <= std::__complement(std::__to_unsigned_like(__tl::min()))) { - __x = __complement(__x); + __x = std::__complement(__x); std::copy_n(std::addressof(__x), 1, std::addressof(__value)); return __r; } } else { - if (__x <= __to_unsigned_like(__tl::max())) + if (__x <= std::__to_unsigned_like(__tl::max())) { __value = __x; return __r; @@ -627,7 +635,7 @@ __in_pattern(_Tp __c, int __base) { if (__base <= 10) return {'0' <= __c && __c < '0' + __base, __c - '0'}; - else if (__in_pattern(__c)) + else if (std::__in_pattern(__c)) return {true, __c - '0'}; else if ('a' <= __c && __c < 'a' + __base - 10) return {true, __c - 'a' + 10}; @@ -648,7 +656,7 @@ __subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, }; auto __p = __find_non_zero(__first, __last); - if (__p == __last || !__in_pattern(*__p, __args...)) + if (__p == __last || !std::__in_pattern(*__p, __args...)) { if (__p == __first) return {__first, errc::invalid_argument}; @@ -664,7 +672,7 @@ __subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, { for (; __r.ptr != __last; ++__r.ptr) { - if (!__in_pattern(*__r.ptr, __args...)) + if (!std::__in_pattern(*__r.ptr, __args...)) break; } } @@ -679,13 +687,13 @@ __from_chars_atoi(const char* __first, const char* __last, _Tp& __value) using __tx = __itoa::__traits<_Tp>; using __output_type = typename __tx::type; - return __subject_seq_combinator( + return std::__subject_seq_combinator( __first, __last, __value, [](const char* __f, const char* __l, _Tp& __val) -> from_chars_result { __output_type __a, __b; auto __p = __tx::__read(__f, __l, __a, __b); - if (__p == __l || !__in_pattern(*__p)) + if (__p == __l || !std::__in_pattern(*__p)) { __output_type __m = numeric_limits<_Tp>::max(); if (__m >= __a && __m - __a >= __b) @@ -702,8 +710,8 @@ template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result __from_chars_atoi(const char* __first, const char* __last, _Tp& __value) { - using __t = decltype(__to_unsigned_like(__value)); - return __sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); + using __t = decltype(std::__to_unsigned_like(__value)); + return std::__sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); } @@ -731,9 +739,9 @@ __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) { if (__base == 10) - return __from_chars_atoi(__first, __last, __value); + return std::__from_chars_atoi(__first, __last, __value); - return __subject_seq_combinator( + return std::__subject_seq_combinator( __first, __last, __value, [](const char* __p, const char* __lastp, _Tp& __val, int __b) -> from_chars_result { @@ -778,16 +786,16 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) { - using __t = decltype(__to_unsigned_like(__value)); - return __sign_combinator(__first, __last, __value, - __from_chars_integral<__t>, __base); + using __t = decltype(std::__to_unsigned_like(__value)); + return std::__sign_combinator(__first, __last, __value, + __from_chars_integral<__t>, __base); } template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result from_chars(const char* __first, const char* __last, _Tp& __value) { - return __from_chars_atoi(__first, __last, __value); + return std::__from_chars_atoi(__first, __last, __value); } template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> @@ -795,7 +803,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result from_chars(const char* __first, const char* __last, _Tp& __value, int __base) { _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]"); - return __from_chars_integral(__first, __last, __value, __base); + return std::__from_chars_integral(__first, __last, __value, __base); } _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS diff --git a/contrib/libs/cxxsupp/libcxx/include/chrono b/contrib/libs/cxxsupp/libcxx/include/chrono index 40fea6f336..604fdf3a3c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/chrono +++ b/contrib/libs/cxxsupp/libcxx/include/chrono @@ -385,18 +385,29 @@ class weekday_indexed; constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const weekday_indexed& wdi); + // 25.8.8, class weekday_last // C++20 class weekday_last; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const weekday_last& wdl); + // 25.8.9, class month_day // C++20 class month_day; constexpr bool operator==(const month_day& x, const month_day& y) noexcept; constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const month_day& md); // 25.8.10, class month_day_last // C++20 class month_day_last; @@ -404,18 +415,30 @@ class month_day_last; constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; constexpr strong_ordering operator<=>(const month_day_last& x, const month_day_last& y) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const month_day_last& mdl); + // 25.8.11, class month_weekday // C++20 class month_weekday; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const month_weekday& mwd); + // 25.8.12, class month_weekday_last // C++20 class month_weekday_last; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const month_weekday_last& mwdl); + // 25.8.13, class year_month // C++20 class year_month; @@ -431,6 +454,10 @@ constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const year_month& ym); + // 25.8.14, class year_month_day class // C++20 year_month_day; @@ -444,6 +471,9 @@ constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) n constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const year_month_day& ymd); // 25.8.15, class year_month_day_last // C++20 class year_month_day_last; @@ -464,6 +494,10 @@ constexpr year_month_day_last constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const year_month_day_last& ymdl); + // 25.8.16, class year_month_weekday // C++20 class year_month_weekday; @@ -485,6 +519,10 @@ constexpr year_month_weekday constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const year_month_weekday& ymwd); + // 25.8.17, class year_month_weekday_last // C++20 class year_month_weekday_last; @@ -505,6 +543,10 @@ constexpr year_month_weekday_last constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; +template<class charT, class traits> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const year_month_weekday_last& ymwdl); + // 25.8.18, civil calendar conventional syntax operators // C++20 constexpr year_month operator/(const year& y, const month& m) noexcept; @@ -638,6 +680,17 @@ namespace std { template<class charT> struct formatter<chrono::month, charT>; // C++20 template<class charT> struct formatter<chrono::year, charT>; // C++20 template<class charT> struct formatter<chrono::weekday, charT>; // C++20 + template<class charT> struct formatter<chrono::weekday_indexed, charT>; // C++20 + template<class charT> struct formatter<chrono::weekday_last, charT>; // C++20 + template<class charT> struct formatter<chrono::month_day, charT>; // C++20 + template<class charT> struct formatter<chrono::month_day_last, charT>; // C++20 + template<class charT> struct formatter<chrono::month_weekday, charT>; // C++20 + template<class charT> struct formatter<chrono::month_weekday_last, charT>; // C++20 + template<class charT> struct formatter<chrono::year_month, charT>; // C++20 + template<class charT> struct formatter<chrono::year_month_day, charT>; // C++20 + template<class charT> struct formatter<chrono::year_month_day_last, charT>; // C++20 + template<class charT> struct formatter<chrono::year_month_weekday, charT>; // C++20 + template<class charT> struct formatter<chrono::year_month_weekday_last, charT>; // C++20 } // namespace std namespace chrono { diff --git a/contrib/libs/cxxsupp/libcxx/include/cmath b/contrib/libs/cxxsupp/libcxx/include/cmath index ef3a67843e..a27d0ebceb 100644 --- a/contrib/libs/cxxsupp/libcxx/include/cmath +++ b/contrib/libs/cxxsupp/libcxx/include/cmath @@ -306,7 +306,12 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <type_traits> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> #include <version> #include <math.h> @@ -558,14 +563,14 @@ hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT static_assert((!(is_same<_A1, __result_type>::value && is_same<_A2, __result_type>::value && is_same<_A3, __result_type>::value)), ""); - return hypot((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z); + return std::hypot((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z); } #endif template <class _A1> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type -__libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT +__constexpr_isnan(_A1 __lcpp_x) _NOEXCEPT { #if __has_builtin(__builtin_isnan) return __builtin_isnan(__lcpp_x); @@ -577,15 +582,15 @@ __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT template <class _A1> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type -__libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT +__constexpr_isnan(_A1 __lcpp_x) _NOEXCEPT { - return isnan(__lcpp_x); + return std::isnan(__lcpp_x); } template <class _A1> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type -__libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT +__constexpr_isinf(_A1 __lcpp_x) _NOEXCEPT { #if __has_builtin(__builtin_isinf) return __builtin_isinf(__lcpp_x); @@ -597,15 +602,15 @@ __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT template <class _A1> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type -__libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT +__constexpr_isinf(_A1 __lcpp_x) _NOEXCEPT { - return isinf(__lcpp_x); + return std::isinf(__lcpp_x); } template <class _A1> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type -__libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT +__constexpr_isfinite(_A1 __lcpp_x) _NOEXCEPT { #if __has_builtin(__builtin_isfinite) return __builtin_isfinite(__lcpp_x); @@ -617,9 +622,164 @@ __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT template <class _A1> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type -__libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT +__constexpr_isfinite(_A1 __lcpp_x) _NOEXCEPT { - return isfinite(__lcpp_x); + return __builtin_isfinite(__lcpp_x); +} + +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI float __constexpr_copysign(float __x, float __y) _NOEXCEPT { + return __builtin_copysignf(__x, __y); +} + +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI double __constexpr_copysign(double __x, double __y) _NOEXCEPT { + return __builtin_copysign(__x, __y); +} + +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI long double +__constexpr_copysign(long double __x, long double __y) _NOEXCEPT { + return __builtin_copysignl(__x, __y); +} + +template <class _A1, class _A2> +_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI + typename std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, + std::__promote<_A1, _A2> >::type + __constexpr_copysign(_A1 __x, _A2 __y) _NOEXCEPT { + typedef typename std::__promote<_A1, _A2>::type __result_type; + static_assert((!(std::_IsSame<_A1, __result_type>::value && std::_IsSame<_A2, __result_type>::value)), ""); + return __builtin_copysign((__result_type)__x, (__result_type)__y); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float __constexpr_fabs(float __x) _NOEXCEPT { + return __builtin_fabsf(__x); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(double __x) _NOEXCEPT { + return __builtin_fabs(__x); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double __constexpr_fabs(long double __x) _NOEXCEPT { + return __builtin_fabsl(__x); +} + +template <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(_Tp __x) _NOEXCEPT { + return __builtin_fabs(static_cast<double>(__x)); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 float __constexpr_fmax(float __x, float __y) _NOEXCEPT { +#if !__has_constexpr_builtin(__builtin_fmaxf) + if (__libcpp_is_constant_evaluated()) { + if (std::__constexpr_isnan(__x)) + return __y; + if (std::__constexpr_isnan(__y)) + return __x; + return __x < __y ? __y : __x; + } +#endif + return __builtin_fmaxf(__x, __y); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 double __constexpr_fmax(double __x, double __y) _NOEXCEPT { +#if !__has_constexpr_builtin(__builtin_fmax) + if (__libcpp_is_constant_evaluated()) { + if (std::__constexpr_isnan(__x)) + return __y; + if (std::__constexpr_isnan(__y)) + return __x; + return __x < __y ? __y : __x; + } +#endif + return __builtin_fmax(__x, __y); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 long double +__constexpr_fmax(long double __x, long double __y) _NOEXCEPT { +#if !__has_constexpr_builtin(__builtin_fmaxl) + if (__libcpp_is_constant_evaluated()) { + if (std::__constexpr_isnan(__x)) + return __y; + if (std::__constexpr_isnan(__y)) + return __x; + return __x < __y ? __y : __x; + } +#endif + return __builtin_fmaxl(__x, __y); +} + +template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value && is_arithmetic<_Up>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __promote<_Tp, _Up>::type +__constexpr_fmax(_Tp __x, _Up __y) _NOEXCEPT { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::__constexpr_fmax(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __constexpr_logb(_Tp __x) { +#if !__has_constexpr_builtin(__builtin_logb) + if (__libcpp_is_constant_evaluated()) { + if (__x == _Tp(0)) { + // raise FE_DIVBYZERO + return -numeric_limits<_Tp>::infinity(); + } + + if (std::__constexpr_isinf(__x)) + return numeric_limits<_Tp>::infinity(); + + if (std::__constexpr_isnan(__x)) + return numeric_limits<_Tp>::quiet_NaN(); + + __x = std::__constexpr_fabs(__x); + unsigned long long __exp = 0; + while (__x >= numeric_limits<_Tp>::radix) { + __x /= numeric_limits<_Tp>::radix; + __exp += 1; + } + return _Tp(__exp); + } +#endif // !__has_constexpr_builtin(__builtin_logb) + return __builtin_logb(__x); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp __x, int __exp) { +#if !__has_constexpr_builtin(__builtin_scalbln) + if (__libcpp_is_constant_evaluated()) { + if (__x == _Tp(0)) + return __x; + + if (std::__constexpr_isinf(__x)) + return __x; + + if (__exp == _Tp(0)) + return __x; + + if (std::__constexpr_isnan(__x)) + return numeric_limits<_Tp>::quiet_NaN(); + + _Tp __mult(1); + if (__exp > 0) { + __mult = numeric_limits<_Tp>::radix; + --__exp; + } else { + ++__exp; + __exp = -__exp; + __mult /= numeric_limits<_Tp>::radix; + } + + while (__exp > 0) { + if (!(__exp & 1)) { + __mult *= __mult; + __exp >>= 1; + } else { + __x *= __mult; + --__exp; + } + } + return __x; + } +#endif // !__has_constexpr_builtin(__builtin_scalbln) + return __builtin_scalbn(__x, __exp); } #if _LIBCPP_STD_VER > 17 @@ -661,7 +821,7 @@ lerp(_A1 __a, _A2 __b, _A3 __t) noexcept static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value && _IsSame<_A3, __result_type>::value)); - return __lerp((__result_type)__a, (__result_type)__b, (__result_type)__t); + return std::__lerp((__result_type)__a, (__result_type)__b, (__result_type)__t); } #endif // _LIBCPP_STD_VER > 17 @@ -669,4 +829,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_CMATH diff --git a/contrib/libs/cxxsupp/libcxx/include/compare b/contrib/libs/cxxsupp/libcxx/include/compare index 6aa1abefd3..9272dbf62b 100644 --- a/contrib/libs/cxxsupp/libcxx/include/compare +++ b/contrib/libs/cxxsupp/libcxx/include/compare @@ -160,4 +160,8 @@ namespace std { # pragma GCC system_header #endif +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_COMPARE diff --git a/contrib/libs/cxxsupp/libcxx/include/complex b/contrib/libs/cxxsupp/libcxx/include/complex index 293ec3d439..cac901af46 100644 --- a/contrib/libs/cxxsupp/libcxx/include/complex +++ b/contrib/libs/cxxsupp/libcxx/include/complex @@ -29,21 +29,21 @@ public: T real() const; // constexpr in C++14 T imag() const; // constexpr in C++14 - void real(T); - void imag(T); - - complex<T>& operator= (const T&); - complex<T>& operator+=(const T&); - complex<T>& operator-=(const T&); - complex<T>& operator*=(const T&); - complex<T>& operator/=(const T&); - - complex& operator=(const complex&); - template<class X> complex<T>& operator= (const complex<X>&); - template<class X> complex<T>& operator+=(const complex<X>&); - template<class X> complex<T>& operator-=(const complex<X>&); - template<class X> complex<T>& operator*=(const complex<X>&); - template<class X> complex<T>& operator/=(const complex<X>&); + void real(T); // constexpr in C++20 + void imag(T); // constexpr in C++20 + + complex<T>& operator= (const T&); // constexpr in C++20 + complex<T>& operator+=(const T&); // constexpr in C++20 + complex<T>& operator-=(const T&); // constexpr in C++20 + complex<T>& operator*=(const T&); // constexpr in C++20 + complex<T>& operator/=(const T&); // constexpr in C++20 + + complex& operator=(const complex&); // constexpr in C++20 + template<class X> complex<T>& operator= (const complex<X>&); // constexpr in C++20 + template<class X> complex<T>& operator+=(const complex<X>&); // constexpr in C++20 + template<class X> complex<T>& operator-=(const complex<X>&); // constexpr in C++20 + template<class X> complex<T>& operator*=(const complex<X>&); // constexpr in C++20 + template<class X> complex<T>& operator/=(const complex<X>&); // constexpr in C++20 }; template<> @@ -57,22 +57,22 @@ public: explicit constexpr complex(const complex<long double>&); constexpr float real() const; - void real(float); + void real(float); // constexpr in C++20 constexpr float imag() const; - void imag(float); - - complex<float>& operator= (float); - complex<float>& operator+=(float); - complex<float>& operator-=(float); - complex<float>& operator*=(float); - complex<float>& operator/=(float); - - complex<float>& operator=(const complex<float>&); - template<class X> complex<float>& operator= (const complex<X>&); - template<class X> complex<float>& operator+=(const complex<X>&); - template<class X> complex<float>& operator-=(const complex<X>&); - template<class X> complex<float>& operator*=(const complex<X>&); - template<class X> complex<float>& operator/=(const complex<X>&); + void imag(float); // constexpr in C++20 + + complex<float>& operator= (float); // constexpr in C++20 + complex<float>& operator+=(float); // constexpr in C++20 + complex<float>& operator-=(float); // constexpr in C++20 + complex<float>& operator*=(float); // constexpr in C++20 + complex<float>& operator/=(float); // constexpr in C++20 + + complex<float>& operator=(const complex<float>&); // constexpr in C++20 + template<class X> complex<float>& operator= (const complex<X>&); // constexpr in C++20 + template<class X> complex<float>& operator+=(const complex<X>&); // constexpr in C++20 + template<class X> complex<float>& operator-=(const complex<X>&); // constexpr in C++20 + template<class X> complex<float>& operator*=(const complex<X>&); // constexpr in C++20 + template<class X> complex<float>& operator/=(const complex<X>&); // constexpr in C++20 }; template<> @@ -86,22 +86,22 @@ public: explicit constexpr complex(const complex<long double>&); constexpr double real() const; - void real(double); + void real(double); // constexpr in C++20 constexpr double imag() const; - void imag(double); - - complex<double>& operator= (double); - complex<double>& operator+=(double); - complex<double>& operator-=(double); - complex<double>& operator*=(double); - complex<double>& operator/=(double); - complex<double>& operator=(const complex<double>&); - - template<class X> complex<double>& operator= (const complex<X>&); - template<class X> complex<double>& operator+=(const complex<X>&); - template<class X> complex<double>& operator-=(const complex<X>&); - template<class X> complex<double>& operator*=(const complex<X>&); - template<class X> complex<double>& operator/=(const complex<X>&); + void imag(double); // constexpr in C++20 + + complex<double>& operator= (double); // constexpr in C++20 + complex<double>& operator+=(double); // constexpr in C++20 + complex<double>& operator-=(double); // constexpr in C++20 + complex<double>& operator*=(double); // constexpr in C++20 + complex<double>& operator/=(double); // constexpr in C++20 + complex<double>& operator=(const complex<double>&); // constexpr in C++20 + + template<class X> complex<double>& operator= (const complex<X>&); // constexpr in C++20 + template<class X> complex<double>& operator+=(const complex<X>&); // constexpr in C++20 + template<class X> complex<double>& operator-=(const complex<X>&); // constexpr in C++20 + template<class X> complex<double>& operator*=(const complex<X>&); // constexpr in C++20 + template<class X> complex<double>& operator/=(const complex<X>&); // constexpr in C++20 }; template<> @@ -115,39 +115,39 @@ public: constexpr complex(const complex<double>&); constexpr long double real() const; - void real(long double); + void real(long double); // constexpr in C++20 constexpr long double imag() const; - void imag(long double); - - complex<long double>& operator=(const complex<long double>&); - complex<long double>& operator= (long double); - complex<long double>& operator+=(long double); - complex<long double>& operator-=(long double); - complex<long double>& operator*=(long double); - complex<long double>& operator/=(long double); - - template<class X> complex<long double>& operator= (const complex<X>&); - template<class X> complex<long double>& operator+=(const complex<X>&); - template<class X> complex<long double>& operator-=(const complex<X>&); - template<class X> complex<long double>& operator*=(const complex<X>&); - template<class X> complex<long double>& operator/=(const complex<X>&); + void imag(long double); // constexpr in C++20 + + complex<long double>& operator=(const complex<long double>&); // constexpr in C++20 + complex<long double>& operator= (long double); // constexpr in C++20 + complex<long double>& operator+=(long double); // constexpr in C++20 + complex<long double>& operator-=(long double); // constexpr in C++20 + complex<long double>& operator*=(long double); // constexpr in C++20 + complex<long double>& operator/=(long double); // constexpr in C++20 + + template<class X> complex<long double>& operator= (const complex<X>&); // constexpr in C++20 + template<class X> complex<long double>& operator+=(const complex<X>&); // constexpr in C++20 + template<class X> complex<long double>& operator-=(const complex<X>&); // constexpr in C++20 + template<class X> complex<long double>& operator*=(const complex<X>&); // constexpr in C++20 + template<class X> complex<long double>& operator/=(const complex<X>&); // constexpr in C++20 }; // 26.3.6 operators: -template<class T> complex<T> operator+(const complex<T>&, const complex<T>&); -template<class T> complex<T> operator+(const complex<T>&, const T&); -template<class T> complex<T> operator+(const T&, const complex<T>&); -template<class T> complex<T> operator-(const complex<T>&, const complex<T>&); -template<class T> complex<T> operator-(const complex<T>&, const T&); -template<class T> complex<T> operator-(const T&, const complex<T>&); -template<class T> complex<T> operator*(const complex<T>&, const complex<T>&); -template<class T> complex<T> operator*(const complex<T>&, const T&); -template<class T> complex<T> operator*(const T&, const complex<T>&); -template<class T> complex<T> operator/(const complex<T>&, const complex<T>&); -template<class T> complex<T> operator/(const complex<T>&, const T&); -template<class T> complex<T> operator/(const T&, const complex<T>&); -template<class T> complex<T> operator+(const complex<T>&); -template<class T> complex<T> operator-(const complex<T>&); +template<class T> complex<T> operator+(const complex<T>&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator+(const complex<T>&, const T&); // constexpr in C++20 +template<class T> complex<T> operator+(const T&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator-(const complex<T>&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator-(const complex<T>&, const T&); // constexpr in C++20 +template<class T> complex<T> operator-(const T&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator*(const complex<T>&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator*(const complex<T>&, const T&); // constexpr in C++20 +template<class T> complex<T> operator*(const T&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator/(const complex<T>&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator/(const complex<T>&, const T&); // constexpr in C++20 +template<class T> complex<T> operator/(const T&, const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator+(const complex<T>&); // constexpr in C++20 +template<class T> complex<T> operator-(const complex<T>&); // constexpr in C++20 template<class T> bool operator==(const complex<T>&, const complex<T>&); // constexpr in C++14 template<class T> bool operator==(const complex<T>&, const T&); // constexpr in C++14 template<class T> bool operator==(const T&, const complex<T>&); // constexpr in C++14 @@ -184,17 +184,17 @@ template<class T> T arg(const complex<T>&); template<Integral T> double arg(T); float arg(float); -template<class T> T norm(const complex<T>&); - long double norm(long double); - double norm(double); -template<Integral T> double norm(T); - float norm(float); +template<class T> T norm(const complex<T>&); // constexpr in C++20 + long double norm(long double); // constexpr in C++20 + double norm(double); // constexpr in C++20 +template<Integral T> double norm(T); // constexpr in C++20 + float norm(float); // constexpr in C++20 -template<class T> complex<T> conj(const complex<T>&); - complex<long double> conj(long double); - complex<double> conj(double); -template<Integral T> complex<double> conj(T); - complex<float> conj(float); +template<class T> complex<T> conj(const complex<T>&); // constexpr in C++20 + complex<long double> conj(long double); // constexpr in C++20 + complex<double> conj(double); // constexpr in C++20 +template<Integral T> complex<double> conj(T); // constexpr in C++20 + complex<float> conj(float); // constexpr in C++20 template<class T> complex<T> proj(const complex<T>&); complex<long double> proj(long double); @@ -251,8 +251,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD template<class _Tp> class _LIBCPP_TEMPLATE_VIS complex; -template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); -template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); +template<class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); +template<class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); template<class _Tp> class _LIBCPP_TEMPLATE_VIS complex @@ -273,40 +273,40 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (const value_type& __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const value_type& __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -334,40 +334,40 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (float __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (float __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(float __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(float __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(float __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(float __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -392,40 +392,40 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (double __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (double __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(double __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(double __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -450,40 +450,40 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (long double __re) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (long double __re) {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(long double __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(long double __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(long double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(long double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + template<class _Xp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -523,7 +523,7 @@ complex<long double>::complex(const complex<double>& __c) // 26.3.6 operators: template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -533,7 +533,7 @@ operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x, const _Tp& __y) { @@ -543,7 +543,7 @@ operator+(const complex<_Tp>& __x, const _Tp& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const _Tp& __x, const complex<_Tp>& __y) { @@ -553,7 +553,7 @@ operator+(const _Tp& __x, const complex<_Tp>& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -563,7 +563,7 @@ operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x, const _Tp& __y) { @@ -573,7 +573,7 @@ operator-(const complex<_Tp>& __x, const _Tp& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const _Tp& __x, const complex<_Tp>& __y) { @@ -583,53 +583,86 @@ operator-(const _Tp& __x, const complex<_Tp>& __y) } template<class _Tp> -_LIBCPP_HIDE_FROM_ABI complex<_Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) { _Tp __a = __z.real(); _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); + + // Avoid floating point operations that are invalid during constant evaluation + if (__libcpp_is_constant_evaluated()) { + bool __z_zero = __a == _Tp(0) && __b == _Tp(0); + bool __w_zero = __c == _Tp(0) && __d == _Tp(0); + bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b); + bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d); + bool __z_nan = !__z_inf && ( + (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) + || (std::__constexpr_isnan(__a) && __b == _Tp(0)) + || (__a == _Tp(0) && std::__constexpr_isnan(__b)) + ); + bool __w_nan = !__w_inf && ( + (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) + || (std::__constexpr_isnan(__c) && __d == _Tp(0)) + || (__c == _Tp(0) && std::__constexpr_isnan(__d)) + ); + if (__z_nan || __w_nan) { + return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); + } + if (__z_inf || __w_inf) { + if (__z_zero || __w_zero) { + return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); + } + return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); + } + bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b)); + bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d)); + if (__z_nonzero_nan || __w_nonzero_nan) { + return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); + } + } + _Tp __ac = __a * __c; _Tp __bd = __b * __d; _Tp __ad = __a * __d; _Tp __bc = __b * __c; _Tp __x = __ac - __bd; _Tp __y = __ad + __bc; - if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y)) + if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) { bool __recalc = false; - if (__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) + if (std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) { - __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); - if (__libcpp_isnan_or_builtin(__c)) - __c = copysign(_Tp(0), __c); - if (__libcpp_isnan_or_builtin(__d)) - __d = copysign(_Tp(0), __d); + __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); + __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); + if (std::__constexpr_isnan(__c)) + __c = std::__constexpr_copysign(_Tp(0), __c); + if (std::__constexpr_isnan(__d)) + __d = std::__constexpr_copysign(_Tp(0), __d); __recalc = true; } - if (__libcpp_isinf_or_builtin(__c) || __libcpp_isinf_or_builtin(__d)) + if (std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d)) { - __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); - if (__libcpp_isnan_or_builtin(__a)) - __a = copysign(_Tp(0), __a); - if (__libcpp_isnan_or_builtin(__b)) - __b = copysign(_Tp(0), __b); + __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); + __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); + if (std::__constexpr_isnan(__a)) + __a = std::__constexpr_copysign(_Tp(0), __a); + if (std::__constexpr_isnan(__b)) + __b = std::__constexpr_copysign(_Tp(0), __b); __recalc = true; } - if (!__recalc && (__libcpp_isinf_or_builtin(__ac) || __libcpp_isinf_or_builtin(__bd) || - __libcpp_isinf_or_builtin(__ad) || __libcpp_isinf_or_builtin(__bc))) + if (!__recalc && (std::__constexpr_isinf(__ac) || std::__constexpr_isinf(__bd) || + std::__constexpr_isinf(__ad) || std::__constexpr_isinf(__bc))) { - if (__libcpp_isnan_or_builtin(__a)) - __a = copysign(_Tp(0), __a); - if (__libcpp_isnan_or_builtin(__b)) - __b = copysign(_Tp(0), __b); - if (__libcpp_isnan_or_builtin(__c)) - __c = copysign(_Tp(0), __c); - if (__libcpp_isnan_or_builtin(__d)) - __d = copysign(_Tp(0), __d); + if (std::__constexpr_isnan(__a)) + __a = std::__constexpr_copysign(_Tp(0), __a); + if (std::__constexpr_isnan(__b)) + __b = std::__constexpr_copysign(_Tp(0), __b); + if (std::__constexpr_isnan(__c)) + __c = std::__constexpr_copysign(_Tp(0), __c); + if (std::__constexpr_isnan(__d)) + __d = std::__constexpr_copysign(_Tp(0), __d); __recalc = true; } if (__recalc) @@ -642,7 +675,7 @@ operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const complex<_Tp>& __x, const _Tp& __y) { @@ -652,7 +685,7 @@ operator*(const complex<_Tp>& __x, const _Tp& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator*(const _Tp& __x, const complex<_Tp>& __y) { @@ -662,7 +695,7 @@ operator*(const _Tp& __x, const complex<_Tp>& __y) } template<class _Tp> -_LIBCPP_HIDE_FROM_ABI complex<_Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) { int __ilogbw = 0; @@ -670,34 +703,74 @@ operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); - _Tp __logbw = logb(fmax(fabs(__c), fabs(__d))); - if (__libcpp_isfinite_or_builtin(__logbw)) + _Tp __logbw = std::__constexpr_logb(std::__constexpr_fmax(std::__constexpr_fabs(__c), std::__constexpr_fabs(__d))); + if (std::__constexpr_isfinite(__logbw)) { __ilogbw = static_cast<int>(__logbw); - __c = scalbn(__c, -__ilogbw); - __d = scalbn(__d, -__ilogbw); + __c = std::__constexpr_scalbn(__c, -__ilogbw); + __d = std::__constexpr_scalbn(__d, -__ilogbw); } + + // Avoid floating point operations that are invalid during constant evaluation + if (__libcpp_is_constant_evaluated()) { + bool __z_zero = __a == _Tp(0) && __b == _Tp(0); + bool __w_zero = __c == _Tp(0) && __d == _Tp(0); + bool __z_inf = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b); + bool __w_inf = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d); + bool __z_nan = !__z_inf && ( + (std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) + || (std::__constexpr_isnan(__a) && __b == _Tp(0)) + || (__a == _Tp(0) && std::__constexpr_isnan(__b)) + ); + bool __w_nan = !__w_inf && ( + (std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) + || (std::__constexpr_isnan(__c) && __d == _Tp(0)) + || (__c == _Tp(0) && std::__constexpr_isnan(__d)) + ); + if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) { + return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); + } + bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b)); + bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d)); + if (__z_nonzero_nan || __w_nonzero_nan) { + if (__w_zero) { + return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); + } + return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); + } + if (__w_inf) { + return complex<_Tp>(_Tp(0), _Tp(0)); + } + if (__z_inf) { + return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); + } + if (__w_zero) { + if (__z_zero) { + return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0)); + } + return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity())); + } + } + _Tp __denom = __c * __c + __d * __d; - _Tp __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); - _Tp __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); - if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y)) + _Tp __x = std::__constexpr_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); + _Tp __y = std::__constexpr_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); + if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) { - if ((__denom == _Tp(0)) && (!__libcpp_isnan_or_builtin(__a) || !__libcpp_isnan_or_builtin(__b))) - { - __x = copysign(_Tp(INFINITY), __c) * __a; - __y = copysign(_Tp(INFINITY), __c) * __b; - } - else if ((__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) && __libcpp_isfinite_or_builtin(__c) && __libcpp_isfinite_or_builtin(__d)) + if ((__denom == _Tp(0)) && (!std::__constexpr_isnan(__a) || !std::__constexpr_isnan(__b))) { - __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); + __x = std::__constexpr_copysign(_Tp(INFINITY), __c) * __a; + __y = std::__constexpr_copysign(_Tp(INFINITY), __c) * __b; + } else if ((std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) && std::__constexpr_isfinite(__c) && + std::__constexpr_isfinite(__d)) { + __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a); + __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b); __x = _Tp(INFINITY) * (__a * __c + __b * __d); __y = _Tp(INFINITY) * (__b * __c - __a * __d); - } - else if (__libcpp_isinf_or_builtin(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite_or_builtin(__a) && __libcpp_isfinite_or_builtin(__b)) - { - __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); + } else if (std::__constexpr_isinf(__logbw) && __logbw > _Tp(0) && std::__constexpr_isfinite(__a) && + std::__constexpr_isfinite(__b)) { + __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c); + __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d); __x = _Tp(0) * (__a * __c + __b * __d); __y = _Tp(0) * (__b * __c - __a * __d); } @@ -706,7 +779,7 @@ operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const complex<_Tp>& __x, const _Tp& __y) { @@ -714,7 +787,7 @@ operator/(const complex<_Tp>& __x, const _Tp& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator/(const _Tp& __x, const complex<_Tp>& __y) { @@ -724,7 +797,7 @@ operator/(const _Tp& __x, const complex<_Tp>& __y) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x) { @@ -732,7 +805,7 @@ operator+(const complex<_Tp>& __x) } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x) { @@ -853,7 +926,7 @@ inline _LIBCPP_INLINE_VISIBILITY _Tp abs(const complex<_Tp>& __c) { - return hypot(__c.real(), __c.imag()); + return std::hypot(__c.real(), __c.imag()); } // arg @@ -863,7 +936,7 @@ inline _LIBCPP_INLINE_VISIBILITY _Tp arg(const complex<_Tp>& __c) { - return atan2(__c.imag(), __c.real()); + return std::atan2(__c.imag(), __c.real()); } template <class _Tp> @@ -874,7 +947,7 @@ typename enable_if< >::type arg(_Tp __re) { - return atan2l(0.L, __re); + return std::atan2l(0.L, __re); } template<class _Tp> @@ -886,7 +959,7 @@ typename enable_if >::type arg(_Tp __re) { - return atan2(0., __re); + return std::atan2(0., __re); } template <class _Tp> @@ -897,25 +970,25 @@ typename enable_if< >::type arg(_Tp __re) { - return atan2f(0.F, __re); + return std::atan2f(0.F, __re); } // norm template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp norm(const complex<_Tp>& __c) { - if (__libcpp_isinf_or_builtin(__c.real())) - return abs(__c.real()); - if (__libcpp_isinf_or_builtin(__c.imag())) - return abs(__c.imag()); + if (std::__constexpr_isinf(__c.real())) + return std::abs(__c.real()); + if (std::__constexpr_isinf(__c.imag())) + return std::abs(__c.imag()); return __c.real() * __c.real() + __c.imag() * __c.imag(); } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ValueType norm(_Tp __re) { @@ -926,7 +999,7 @@ norm(_Tp __re) // conj template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> conj(const complex<_Tp>& __c) { @@ -934,7 +1007,7 @@ conj(const complex<_Tp>& __c) } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ComplexType conj(_Tp __re) { @@ -952,8 +1025,8 @@ complex<_Tp> proj(const complex<_Tp>& __c) { complex<_Tp> __r = __c; - if (__libcpp_isinf_or_builtin(__c.real()) || __libcpp_isinf_or_builtin(__c.imag())) - __r = complex<_Tp>(INFINITY, copysign(_Tp(0), __c.imag())); + if (std::__constexpr_isinf(__c.real()) || std::__constexpr_isinf(__c.imag())) + __r = complex<_Tp>(INFINITY, std::copysign(_Tp(0), __c.imag())); return __r; } @@ -966,8 +1039,8 @@ typename enable_if >::type proj(_Tp __re) { - if (__libcpp_isinf_or_builtin(__re)) - __re = abs(__re); + if (std::__constexpr_isinf(__re)) + __re = std::abs(__re); return complex<_Tp>(__re); } @@ -990,25 +1063,25 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> polar(const _Tp& __rho, const _Tp& __theta = _Tp()) { - if (__libcpp_isnan_or_builtin(__rho) || signbit(__rho)) + if (std::__constexpr_isnan(__rho) || std::signbit(__rho)) return complex<_Tp>(_Tp(NAN), _Tp(NAN)); - if (__libcpp_isnan_or_builtin(__theta)) + if (std::__constexpr_isnan(__theta)) { - if (__libcpp_isinf_or_builtin(__rho)) + if (std::__constexpr_isinf(__rho)) return complex<_Tp>(__rho, __theta); return complex<_Tp>(__theta, __theta); } - if (__libcpp_isinf_or_builtin(__theta)) + if (std::__constexpr_isinf(__theta)) { - if (__libcpp_isinf_or_builtin(__rho)) + if (std::__constexpr_isinf(__rho)) return complex<_Tp>(__rho, _Tp(NAN)); return complex<_Tp>(_Tp(NAN), _Tp(NAN)); } - _Tp __x = __rho * cos(__theta); - if (__libcpp_isnan_or_builtin(__x)) + _Tp __x = __rho * std::cos(__theta); + if (std::__constexpr_isnan(__x)) __x = 0; - _Tp __y = __rho * sin(__theta); - if (__libcpp_isnan_or_builtin(__y)) + _Tp __y = __rho * std::sin(__theta); + if (std::__constexpr_isnan(__y)) __y = 0; return complex<_Tp>(__x, __y); } @@ -1020,7 +1093,7 @@ inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> log(const complex<_Tp>& __x) { - return complex<_Tp>(log(abs(__x)), arg(__x)); + return complex<_Tp>(std::log(std::abs(__x)), std::arg(__x)); } // log10 @@ -1030,7 +1103,7 @@ inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> log10(const complex<_Tp>& __x) { - return log(__x) / log(_Tp(10)); + return std::log(__x) / std::log(_Tp(10)); } // sqrt @@ -1039,15 +1112,15 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) { - if (__libcpp_isinf_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.imag())) return complex<_Tp>(_Tp(INFINITY), __x.imag()); - if (__libcpp_isinf_or_builtin(__x.real())) + if (std::__constexpr_isinf(__x.real())) { if (__x.real() > _Tp(0)) - return complex<_Tp>(__x.real(), __libcpp_isnan_or_builtin(__x.imag()) ? __x.imag() : copysign(_Tp(0), __x.imag())); - return complex<_Tp>(__libcpp_isnan_or_builtin(__x.imag()) ? __x.imag() : _Tp(0), copysign(__x.real(), __x.imag())); + return complex<_Tp>(__x.real(), std::__constexpr_isnan(__x.imag()) ? __x.imag() : std::copysign(_Tp(0), __x.imag())); + return complex<_Tp>(std::__constexpr_isnan(__x.imag()) ? __x.imag() : _Tp(0), std::copysign(__x.real(), __x.imag())); } - return polar(sqrt(abs(__x)), arg(__x) / _Tp(2)); + return std::polar(std::sqrt(std::abs(__x)), std::arg(__x) / _Tp(2)); } // exp @@ -1058,24 +1131,24 @@ exp(const complex<_Tp>& __x) { _Tp __i = __x.imag(); if (__i == 0) { - return complex<_Tp>(exp(__x.real()), copysign(_Tp(0), __x.imag())); + return complex<_Tp>(std::exp(__x.real()), std::copysign(_Tp(0), __x.imag())); } - if (__libcpp_isinf_or_builtin(__x.real())) + if (std::__constexpr_isinf(__x.real())) { if (__x.real() < _Tp(0)) { - if (!__libcpp_isfinite_or_builtin(__i)) + if (!std::__constexpr_isfinite(__i)) __i = _Tp(1); } - else if (__i == 0 || !__libcpp_isfinite_or_builtin(__i)) + else if (__i == 0 || !std::__constexpr_isfinite(__i)) { - if (__libcpp_isinf_or_builtin(__i)) + if (std::__constexpr_isinf(__i)) __i = _Tp(NAN); return complex<_Tp>(__x.real(), __i); } } - _Tp __e = exp(__x.real()); - return complex<_Tp>(__e * cos(__i), __e * sin(__i)); + _Tp __e = std::exp(__x.real()); + return complex<_Tp>(__e * std::cos(__i), __e * std::sin(__i)); } // pow @@ -1085,7 +1158,7 @@ inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> pow(const complex<_Tp>& __x, const complex<_Tp>& __y) { - return exp(__y * log(__x)); + return std::exp(__y * std::log(__x)); } template<class _Tp, class _Up> @@ -1141,26 +1214,26 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf_or_builtin(__x.real())) + if (std::__constexpr_isinf(__x.real())) { - if (__libcpp_isnan_or_builtin(__x.imag())) + if (std::__constexpr_isnan(__x.imag())) return __x; - if (__libcpp_isinf_or_builtin(__x.imag())) - return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); - return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); + if (std::__constexpr_isinf(__x.imag())) + return complex<_Tp>(__x.real(), std::copysign(__pi * _Tp(0.25), __x.imag())); + return complex<_Tp>(__x.real(), std::copysign(_Tp(0), __x.imag())); } - if (__libcpp_isnan_or_builtin(__x.real())) + if (std::__constexpr_isnan(__x.real())) { - if (__libcpp_isinf_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.imag())) return complex<_Tp>(__x.imag(), __x.real()); if (__x.imag() == 0) return __x; return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf_or_builtin(__x.imag())) - return complex<_Tp>(copysign(__x.imag(), __x.real()), copysign(__pi/_Tp(2), __x.imag())); - complex<_Tp> __z = log(__x + sqrt(__sqr(__x) + _Tp(1))); - return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag())); + if (std::__constexpr_isinf(__x.imag())) + return complex<_Tp>(std::copysign(__x.imag(), __x.real()), std::copysign(__pi/_Tp(2), __x.imag())); + complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) + _Tp(1))); + return complex<_Tp>(std::copysign(__z.real(), __x.real()), std::copysign(__z.imag(), __x.imag())); } // acosh @@ -1170,31 +1243,31 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf_or_builtin(__x.real())) + if (std::__constexpr_isinf(__x.real())) { - if (__libcpp_isnan_or_builtin(__x.imag())) - return complex<_Tp>(abs(__x.real()), __x.imag()); - if (__libcpp_isinf_or_builtin(__x.imag())) + if (std::__constexpr_isnan(__x.imag())) + return complex<_Tp>(std::abs(__x.real()), __x.imag()); + if (std::__constexpr_isinf(__x.imag())) { if (__x.real() > 0) - return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); + return complex<_Tp>(__x.real(), std::copysign(__pi * _Tp(0.25), __x.imag())); else - return complex<_Tp>(-__x.real(), copysign(__pi * _Tp(0.75), __x.imag())); + return complex<_Tp>(-__x.real(), std::copysign(__pi * _Tp(0.75), __x.imag())); } if (__x.real() < 0) - return complex<_Tp>(-__x.real(), copysign(__pi, __x.imag())); - return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); + return complex<_Tp>(-__x.real(), std::copysign(__pi, __x.imag())); + return complex<_Tp>(__x.real(), std::copysign(_Tp(0), __x.imag())); } - if (__libcpp_isnan_or_builtin(__x.real())) + if (std::__constexpr_isnan(__x.real())) { - if (__libcpp_isinf_or_builtin(__x.imag())) - return complex<_Tp>(abs(__x.imag()), __x.real()); + if (std::__constexpr_isinf(__x.imag())) + return complex<_Tp>(std::abs(__x.imag()), __x.real()); return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf_or_builtin(__x.imag())) - return complex<_Tp>(abs(__x.imag()), copysign(__pi/_Tp(2), __x.imag())); - complex<_Tp> __z = log(__x + sqrt(__sqr(__x) - _Tp(1))); - return complex<_Tp>(copysign(__z.real(), _Tp(0)), copysign(__z.imag(), __x.imag())); + if (std::__constexpr_isinf(__x.imag())) + return complex<_Tp>(std::abs(__x.imag()), std::copysign(__pi/_Tp(2), __x.imag())); + complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) - _Tp(1))); + return complex<_Tp>(std::copysign(__z.real(), _Tp(0)), std::copysign(__z.imag(), __x.imag())); } // atanh @@ -1204,30 +1277,30 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.imag())) { - return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); + return complex<_Tp>(std::copysign(_Tp(0), __x.real()), std::copysign(__pi/_Tp(2), __x.imag())); } - if (__libcpp_isnan_or_builtin(__x.imag())) + if (std::__constexpr_isnan(__x.imag())) { - if (__libcpp_isinf_or_builtin(__x.real()) || __x.real() == 0) - return complex<_Tp>(copysign(_Tp(0), __x.real()), __x.imag()); + if (std::__constexpr_isinf(__x.real()) || __x.real() == 0) + return complex<_Tp>(std::copysign(_Tp(0), __x.real()), __x.imag()); return complex<_Tp>(__x.imag(), __x.imag()); } - if (__libcpp_isnan_or_builtin(__x.real())) + if (std::__constexpr_isnan(__x.real())) { return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf_or_builtin(__x.real())) + if (std::__constexpr_isinf(__x.real())) { - return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); + return complex<_Tp>(std::copysign(_Tp(0), __x.real()), std::copysign(__pi/_Tp(2), __x.imag())); } - if (abs(__x.real()) == _Tp(1) && __x.imag() == _Tp(0)) + if (std::abs(__x.real()) == _Tp(1) && __x.imag() == _Tp(0)) { - return complex<_Tp>(copysign(_Tp(INFINITY), __x.real()), copysign(_Tp(0), __x.imag())); + return complex<_Tp>(std::copysign(_Tp(INFINITY), __x.real()), std::copysign(_Tp(0), __x.imag())); } - complex<_Tp> __z = log((_Tp(1) + __x) / (_Tp(1) - __x)) / _Tp(2); - return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag())); + complex<_Tp> __z = std::log((_Tp(1) + __x) / (_Tp(1) - __x)) / _Tp(2); + return complex<_Tp>(std::copysign(__z.real(), __x.real()), std::copysign(__z.imag(), __x.imag())); } // sinh @@ -1236,13 +1309,13 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> sinh(const complex<_Tp>& __x) { - if (__libcpp_isinf_or_builtin(__x.real()) && !__libcpp_isfinite_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.real()) && !std::__constexpr_isfinite(__x.imag())) return complex<_Tp>(__x.real(), _Tp(NAN)); - if (__x.real() == 0 && !__libcpp_isfinite_or_builtin(__x.imag())) + if (__x.real() == 0 && !std::__constexpr_isfinite(__x.imag())) return complex<_Tp>(__x.real(), _Tp(NAN)); - if (__x.imag() == 0 && !__libcpp_isfinite_or_builtin(__x.real())) + if (__x.imag() == 0 && !std::__constexpr_isfinite(__x.real())) return __x; - return complex<_Tp>(sinh(__x.real()) * cos(__x.imag()), cosh(__x.real()) * sin(__x.imag())); + return complex<_Tp>(std::sinh(__x.real()) * std::cos(__x.imag()), std::cosh(__x.real()) * std::sin(__x.imag())); } // cosh @@ -1251,15 +1324,15 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> cosh(const complex<_Tp>& __x) { - if (__libcpp_isinf_or_builtin(__x.real()) && !__libcpp_isfinite_or_builtin(__x.imag())) - return complex<_Tp>(abs(__x.real()), _Tp(NAN)); - if (__x.real() == 0 && !__libcpp_isfinite_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.real()) && !std::__constexpr_isfinite(__x.imag())) + return complex<_Tp>(std::abs(__x.real()), _Tp(NAN)); + if (__x.real() == 0 && !std::__constexpr_isfinite(__x.imag())) return complex<_Tp>(_Tp(NAN), __x.real()); if (__x.real() == 0 && __x.imag() == 0) return complex<_Tp>(_Tp(1), __x.imag()); - if (__x.imag() == 0 && !__libcpp_isfinite_or_builtin(__x.real())) - return complex<_Tp>(abs(__x.real()), __x.imag()); - return complex<_Tp>(cosh(__x.real()) * cos(__x.imag()), sinh(__x.real()) * sin(__x.imag())); + if (__x.imag() == 0 && !std::__constexpr_isfinite(__x.real())) + return complex<_Tp>(std::abs(__x.real()), __x.imag()); + return complex<_Tp>(std::cosh(__x.real()) * std::cos(__x.imag()), std::sinh(__x.real()) * std::sin(__x.imag())); } // tanh @@ -1268,22 +1341,22 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> tanh(const complex<_Tp>& __x) { - if (__libcpp_isinf_or_builtin(__x.real())) + if (std::__constexpr_isinf(__x.real())) { - if (!__libcpp_isfinite_or_builtin(__x.imag())) - return complex<_Tp>(copysign(_Tp(1), __x.real()), _Tp(0)); - return complex<_Tp>(copysign(_Tp(1), __x.real()), copysign(_Tp(0), sin(_Tp(2) * __x.imag()))); + if (!std::__constexpr_isfinite(__x.imag())) + return complex<_Tp>(std::copysign(_Tp(1), __x.real()), _Tp(0)); + return complex<_Tp>(std::copysign(_Tp(1), __x.real()), std::copysign(_Tp(0), std::sin(_Tp(2) * __x.imag()))); } - if (__libcpp_isnan_or_builtin(__x.real()) && __x.imag() == 0) + if (std::__constexpr_isnan(__x.real()) && __x.imag() == 0) return __x; _Tp __2r(_Tp(2) * __x.real()); _Tp __2i(_Tp(2) * __x.imag()); - _Tp __d(cosh(__2r) + cos(__2i)); - _Tp __2rsh(sinh(__2r)); - if (__libcpp_isinf_or_builtin(__2rsh) && __libcpp_isinf_or_builtin(__d)) + _Tp __d(std::cosh(__2r) + std::cos(__2i)); + _Tp __2rsh(std::sinh(__2r)); + if (std::__constexpr_isinf(__2rsh) && std::__constexpr_isinf(__d)) return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1), __2i > _Tp(0) ? _Tp(0) : _Tp(-0.)); - return complex<_Tp>(__2rsh/__d, sin(__2i)/__d); + return complex<_Tp>(__2rsh/__d, std::sin(__2i)/__d); } // asin @@ -1292,7 +1365,7 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> asin(const complex<_Tp>& __x) { - complex<_Tp> __z = asinh(complex<_Tp>(-__x.imag(), __x.real())); + complex<_Tp> __z = std::asinh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } @@ -1303,34 +1376,35 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> acos(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf_or_builtin(__x.real())) + if (std::__constexpr_isinf(__x.real())) { - if (__libcpp_isnan_or_builtin(__x.imag())) + if (std::__constexpr_isnan(__x.imag())) return complex<_Tp>(__x.imag(), __x.real()); - if (__libcpp_isinf_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.imag())) { if (__x.real() < _Tp(0)) return complex<_Tp>(_Tp(0.75) * __pi, -__x.imag()); return complex<_Tp>(_Tp(0.25) * __pi, -__x.imag()); } if (__x.real() < _Tp(0)) - return complex<_Tp>(__pi, signbit(__x.imag()) ? -__x.real() : __x.real()); - return complex<_Tp>(_Tp(0), signbit(__x.imag()) ? __x.real() : -__x.real()); + return complex<_Tp>(__pi, std::signbit(__x.imag()) ? -__x.real() : __x.real()); + return complex<_Tp>(_Tp(0), std::signbit(__x.imag()) ? __x.real() : -__x.real()); } - if (__libcpp_isnan_or_builtin(__x.real())) + if (std::__constexpr_isnan(__x.real())) { - if (__libcpp_isinf_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.imag())) return complex<_Tp>(__x.real(), -__x.imag()); return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf_or_builtin(__x.imag())) + if (std::__constexpr_isinf(__x.imag())) return complex<_Tp>(__pi/_Tp(2), -__x.imag()); - if (__x.real() == 0 && (__x.imag() == 0 || isnan(__x.imag()))) + // Somehow isnan can be a macro, so we use __constexpr_isnan + if (__x.real() == 0 && (__x.imag() == 0 || std::__constexpr_isnan(__x.imag()))) return complex<_Tp>(__pi/_Tp(2), -__x.imag()); - complex<_Tp> __z = log(__x + sqrt(__sqr(__x) - _Tp(1))); - if (signbit(__x.imag())) - return complex<_Tp>(abs(__z.imag()), abs(__z.real())); - return complex<_Tp>(abs(__z.imag()), -abs(__z.real())); + complex<_Tp> __z = std::log(__x + std::sqrt(std::__sqr(__x) - _Tp(1))); + if (std::signbit(__x.imag())) + return complex<_Tp>(std::abs(__z.imag()), std::abs(__z.real())); + return complex<_Tp>(std::abs(__z.imag()), -std::abs(__z.real())); } // atan @@ -1339,7 +1413,7 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> atan(const complex<_Tp>& __x) { - complex<_Tp> __z = atanh(complex<_Tp>(-__x.imag(), __x.real())); + complex<_Tp> __z = std::atanh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } @@ -1349,7 +1423,7 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> sin(const complex<_Tp>& __x) { - complex<_Tp> __z = sinh(complex<_Tp>(-__x.imag(), __x.real())); + complex<_Tp> __z = std::sinh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } @@ -1360,7 +1434,7 @@ inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> cos(const complex<_Tp>& __x) { - return cosh(complex<_Tp>(-__x.imag(), __x.real())); + return std::cosh(complex<_Tp>(-__x.imag(), __x.real())); } // tan @@ -1369,17 +1443,18 @@ template<class _Tp> _LIBCPP_HIDE_FROM_ABI complex<_Tp> tan(const complex<_Tp>& __x) { - complex<_Tp> __z = tanh(complex<_Tp>(-__x.imag(), __x.real())); + complex<_Tp> __z = std::tanh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) template<class _Tp, class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) { if (__is.good()) { - ws(__is); + std::ws(__is); if (__is.peek() == _CharT('(')) { __is.get(); @@ -1387,7 +1462,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) __is >> __r; if (!__is.fail()) { - ws(__is); + std::ws(__is); _CharT __c = __is.peek(); if (__c == _CharT(',')) { @@ -1396,7 +1471,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) __is >> __i; if (!__is.fail()) { - ws(__is); + std::ws(__is); __c = __is.peek(); if (__c == _CharT(')')) { @@ -1435,7 +1510,6 @@ operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) return __is; } -#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) template<class _Tp, class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) diff --git a/contrib/libs/cxxsupp/libcxx/include/concepts b/contrib/libs/cxxsupp/libcxx/include/concepts index 301256ca7e..196fa2e0ea 100644 --- a/contrib/libs/cxxsupp/libcxx/include/concepts +++ b/contrib/libs/cxxsupp/libcxx/include/concepts @@ -155,6 +155,10 @@ namespace std { #include <__config> #include <version> +#if _LIBCPP_STD_VER <= 20 && !defined(_LIPCPP_REMOVE_TRANSITIVE_INCLUDES) +# include <type_traits> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/condition_variable b/contrib/libs/cxxsupp/libcxx/include/condition_variable index 6b4d506939..f13df1c012 100644 --- a/contrib/libs/cxxsupp/libcxx/include/condition_variable +++ b/contrib/libs/cxxsupp/libcxx/include/condition_variable @@ -270,6 +270,7 @@ _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <type_traits> #endif #endif // _LIBCPP_CONDITION_VARIABLE diff --git a/contrib/libs/cxxsupp/libcxx/include/coroutine b/contrib/libs/cxxsupp/libcxx/include/coroutine index e0ce323843..f264570128 100644 --- a/contrib/libs/cxxsupp/libcxx/include/coroutine +++ b/contrib/libs/cxxsupp/libcxx/include/coroutine @@ -57,6 +57,7 @@ struct suspend_always; #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <iosfwd> +# include <type_traits> #endif #endif // _LIBCPP_COROUTINE diff --git a/contrib/libs/cxxsupp/libcxx/include/cstring b/contrib/libs/cxxsupp/libcxx/include/cstring index 42bbe73924..c88d97739f 100644 --- a/contrib/libs/cxxsupp/libcxx/include/cstring +++ b/contrib/libs/cxxsupp/libcxx/include/cstring @@ -58,6 +58,7 @@ size_t strlen(const char* s); #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__type_traits/is_constant_evaluated.h> #include <string.h> @@ -99,6 +100,53 @@ using ::memset _LIBCPP_USING_IF_EXISTS; using ::strerror _LIBCPP_USING_IF_EXISTS; using ::strlen _LIBCPP_USING_IF_EXISTS; +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) { + // GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 +#ifdef _LIBCPP_COMPILER_GCC + if (__libcpp_is_constant_evaluated()) { + size_t __i = 0; + for (; __str[__i] != '\0'; ++__i) + ; + return __i; + } +#endif + return __builtin_strlen(__str); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int +__constexpr_memcmp(const _Tp* __lhs, const _Tp* __rhs, size_t __count) { +#ifdef _LIBCPP_COMPILER_GCC + if (__libcpp_is_constant_evaluated()) { + for (; __count; --__count, ++__lhs, ++__rhs) { + if (*__lhs < *__rhs) + return -1; + if (*__rhs < *__lhs) + return 1; + } + return 0; + } +#endif + return __builtin_memcmp(__lhs, __rhs, __count); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const char* +__constexpr_char_memchr(const char* __str, int __char, size_t __count) { +#if __has_builtin(__builtin_char_memchr) + return __builtin_char_memchr(__str, __char, __count); +#else + if (!__libcpp_is_constant_evaluated()) + return static_cast<const char*>(std::memchr(__str, __char, __count)); + for (; __count; --__count) { + if (*__str == __char) + return __str; + ++__str; + } + return nullptr; +#endif +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_CSTRING diff --git a/contrib/libs/cxxsupp/libcxx/include/cwchar b/contrib/libs/cxxsupp/libcxx/include/cwchar index 220c817072..fb7b92b760 100644 --- a/contrib/libs/cxxsupp/libcxx/include/cwchar +++ b/contrib/libs/cxxsupp/libcxx/include/cwchar @@ -104,6 +104,7 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len, #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__type_traits/is_constant_evaluated.h> #include <cwctype> #include <wchar.h> @@ -189,6 +190,55 @@ using ::putwchar _LIBCPP_USING_IF_EXISTS; using ::vwprintf _LIBCPP_USING_IF_EXISTS; using ::wprintf _LIBCPP_USING_IF_EXISTS; +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_wcslen(const wchar_t* __str) { +#if __has_builtin(__builtin_wcslen) + return __builtin_wcslen(__str); +#else + if (!__libcpp_is_constant_evaluated()) + return std::wcslen(__str); + + size_t __len = 0; + for (; *__str != L'\0'; ++__str) + ++__len; + return __len; +#endif +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int +__constexpr_wmemcmp(const wchar_t* __lhs, const wchar_t* __rhs, size_t __count) { +#if __has_builtin(__builtin_wmemcmp) + return __builtin_wmemcmp(__lhs, __rhs, __count); +#else + if (!__libcpp_is_constant_evaluated()) + return std::wmemcmp(__lhs, __rhs, __count); + + for (; __count; --__count, ++__lhs, ++__rhs) { + if (*__lhs < *__rhs) + return -1; + if (*__rhs < *__lhs) + return 1; + } + return 0; +#endif +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const wchar_t* +__constexpr_wmemchr(const wchar_t* __str, wchar_t __char, size_t __count) { +#if __has_feature(cxx_constexpr_string_builtins) + return __builtin_wmemchr(__str, __char, __count); +#else + if (!__libcpp_is_constant_evaluated()) + return std::wmemchr(__str, __char, __count); + + for (; __count; --__count) { + if (*__str == __char) + return __str; + ++__str; + } + return nullptr; +#endif +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_CWCHAR diff --git a/contrib/libs/cxxsupp/libcxx/include/deque b/contrib/libs/cxxsupp/libcxx/include/deque index 40b9eff155..0cd09040a8 100644 --- a/contrib/libs/cxxsupp/libcxx/include/deque +++ b/contrib/libs/cxxsupp/libcxx/include/deque @@ -176,6 +176,7 @@ template <class T, class Allocator, class Predicate> #include <__iterator/next.h> #include <__iterator/prev.h> #include <__iterator/reverse_iterator.h> +#include <__iterator/segmented_iterator.h> #include <__memory/allocator_destructor.h> #include <__memory/pointer_traits.h> #include <__memory/temp_value.h> @@ -216,98 +217,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, class _Allocator = allocator<_Tp> > class _LIBCPP_TEMPLATE_VIS deque; -template <class _ValueType, class _Pointer, class _Reference, class _MapPointer, - class _DiffType, _DiffType _BlockSize> -class _LIBCPP_TEMPLATE_VIS __deque_iterator; - -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - template <class _ValueType, class _DiffType> struct __deque_block_size { static const _DiffType __buf_size = 64 * sizeof(void*); @@ -480,464 +389,43 @@ private: template <class _Vp, class _Pp, class _Rp, class _MP, class _Dp, _Dp> friend class _LIBCPP_TEMPLATE_VIS __deque_iterator; - template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> - friend - _OutputIterator - copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - - template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> - friend - _OutputIterator - copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - - template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> - friend - _OutputIterator - move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); - - template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> - friend - _OutputIterator - move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r); - - template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> - friend - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> - move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r); + template <class> + friend struct __segmented_iterator_traits; }; -template <class _ValueType, class _Pointer, class _Reference, class _MapPointer, - class _DiffType, _DiffType _BlockSize> -const _DiffType __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer, - _DiffType, _BlockSize>::__block_size = - __deque_block_size<_ValueType, _DiffType>::value; - -// copy - -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size; - while (__f != __l) - { - pointer __rb = __r.__ptr_; - pointer __re = *__r.__m_iter_ + __block_size; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __l; - if (__n > __bs) - { - __n = __bs; - __m = __f + __n; - } - _VSTD::copy(__f, __m, __rb); - __f = __m; - __r += __n; - } - return __r; -} - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::copy(__fb, __fe, __r); - __n -= __bs; - __f += __bs; - } - return __r; -} - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::copy(__fb, __fe, __r); - __n -= __bs; - __f += __bs; - } - return __r; -} - -// copy_backward - -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - while (__f != __l) - { - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __rp = _VSTD::prev(__r); - pointer __rb = *__rp.__m_iter_; - pointer __re = __rp.__ptr_ + 1; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __f; - if (__n > __bs) - { - __n = __bs; - __m = __l - __n; - } - _VSTD::copy_backward(__m, __l, __re); - __l = __m; - __r -= __n; - } - return __r; -} - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; - } - __r = _VSTD::copy_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; - } - return __r; -} - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -copy_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; - } - __r = _VSTD::copy_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; - } - return __r; -} - -// move - -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size; - while (__f != __l) - { - pointer __rb = __r.__ptr_; - pointer __re = *__r.__m_iter_ + __block_size; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __l; - if (__n > __bs) - { - __n = __bs; - __m = __f + __n; - } - _VSTD::move(__f, __m, __rb); - __f = __m; - __r += __n; - } - return __r; -} - -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::move(__fb, __fe, __r); - __n -= __bs; - __f += __bs; - } - return __r; -} +template <class _ValueType, class _Pointer, class _Reference, class _MapPointer, class _DiffType, _DiffType _BlockSize> +struct __segmented_iterator_traits< + __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer, _DiffType, _BlockSize> > { +private: + using _Iterator = __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer, _DiffType, _BlockSize>; -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size; - difference_type __n = __l - __f; - while (__n > 0) - { - pointer __fb = __f.__ptr_; - pointer __fe = *__f.__m_iter_ + __block_size; - difference_type __bs = __fe - __fb; - if (__bs > __n) - { - __bs = __n; - __fe = __fb + __bs; - } - __r = _VSTD::move(__fb, __fe, __r); - __n -= __bs; - __f += __bs; - } - return __r; -} +public: + using __is_segmented_iterator = true_type; + using __segment_iterator = _MapPointer; + using __local_iterator = _Pointer; -// move_backward + static _LIBCPP_HIDE_FROM_ABI __segment_iterator __segment(_Iterator __iter) { return __iter.__m_iter_; } + static _LIBCPP_HIDE_FROM_ABI __local_iterator __local(_Iterator __iter) { return __iter.__ptr_; } + static _LIBCPP_HIDE_FROM_ABI __local_iterator __begin(__segment_iterator __iter) { return *__iter; } -template <class _RAIter, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(_RAIter __f, - _RAIter __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) -{ - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type; - typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer; - while (__f != __l) - { - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __rp = _VSTD::prev(__r); - pointer __rb = *__rp.__m_iter_; - pointer __re = __rp.__ptr_ + 1; - difference_type __bs = __re - __rb; - difference_type __n = __l - __f; - _RAIter __m = __f; - if (__n > __bs) - { - __n = __bs; - __m = __l - __n; - } - _VSTD::move_backward(__m, __l, __re); - __l = __m; - __r -= __n; - } - return __r; -} + static _LIBCPP_HIDE_FROM_ABI __local_iterator __end(__segment_iterator __iter) { + return *__iter + _Iterator::__block_size; + } -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _OutputIterator> -_LIBCPP_HIDE_FROM_ABI _OutputIterator -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - _OutputIterator __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; + static _LIBCPP_HIDE_FROM_ABI _Iterator __compose(__segment_iterator __segment, __local_iterator __local) { + if (__local == __end(__segment)) { + ++__segment; + return _Iterator(__segment, *__segment); } - __r = _VSTD::move_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; - } - return __r; -} + return _Iterator(__segment, __local); + } +}; -template <class _V1, class _P1, class _R1, class _M1, class _D1, _D1 _B1, - class _V2, class _P2, class _R2, class _M2, class _D2, _D2 _B2> -_LIBCPP_HIDE_FROM_ABI __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> -move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f, - __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l, - __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r) -{ - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type; - typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer; - difference_type __n = __l - __f; - while (__n > 0) - { - --__l; - pointer __lb = *__l.__m_iter_; - pointer __le = __l.__ptr_ + 1; - difference_type __bs = __le - __lb; - if (__bs > __n) - { - __bs = __n; - __lb = __le - __bs; - } - __r = _VSTD::move_backward(__lb, __le, __r); - __n -= __bs; - __l -= __bs - 1; - } - return __r; -} +template <class _ValueType, class _Pointer, class _Reference, class _MapPointer, + class _DiffType, _DiffType _BlockSize> +const _DiffType __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer, + _DiffType, _BlockSize>::__block_size = + __deque_block_size<_ValueType, _DiffType>::value; template <class _Tp, class _Allocator /*= allocator<_Tp>*/> class _LIBCPP_TEMPLATE_VIS deque @@ -2317,7 +1805,7 @@ deque<_Tp, _Allocator>::__add_front_capacity() else { __split_buffer<pointer, __pointer_allocator&> - __buf(max<size_type>(2 * __map_.capacity(), 1), + __buf(std::max<size_type>(2 * __map_.capacity(), 1), 0, __map_.__alloc()); typedef __allocator_destructor<_Allocator> _Dp; @@ -2390,8 +1878,8 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { size_type __ds = (__nb + __back_capacity) * __block_size - __map_.empty(); __split_buffer<pointer, __pointer_allocator&> - __buf(max<size_type>(2* __map_.capacity(), - __nb + __map_.size()), + __buf(std::max<size_type>(2* __map_.capacity(), + __nb + __map_.size()), 0, __map_.__alloc()); #ifndef _LIBCPP_NO_EXCEPTIONS try @@ -2459,7 +1947,7 @@ deque<_Tp, _Allocator>::__add_back_capacity() else { __split_buffer<pointer, __pointer_allocator&> - __buf(max<size_type>(2* __map_.capacity(), 1), + __buf(std::max<size_type>(2* __map_.capacity(), 1), __map_.size(), __map_.__alloc()); @@ -2531,8 +2019,8 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { size_type __ds = __front_capacity * __block_size; __split_buffer<pointer, __pointer_allocator&> - __buf(max<size_type>(2* __map_.capacity(), - __nb + __map_.size()), + __buf(std::max<size_type>(2* __map_.capacity(), + __nb + __map_.size()), __map_.size() - __front_capacity, __map_.__alloc()); #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/contrib/libs/cxxsupp/libcxx/include/exception b/contrib/libs/cxxsupp/libcxx/include/exception index 2d37d7ab09..d63bb8f858 100644 --- a/contrib/libs/cxxsupp/libcxx/include/exception +++ b/contrib/libs/cxxsupp/libcxx/include/exception @@ -80,9 +80,15 @@ template <class E> void rethrow_if_nested(const E& e); #include <__availability> #include <__config> #include <__memory/addressof.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_class.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_final.h> +#include <__type_traits/is_polymorphic.h> #include <cstddef> #include <cstdlib> -#include <type_traits> #include <version> // <vcruntime_exception.h> defines its own std::exception and std::bad_exception types, @@ -350,4 +356,8 @@ rethrow_if_nested(const _Ep&, } // namespace std +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_EXCEPTION diff --git a/contrib/libs/cxxsupp/libcxx/include/format b/contrib/libs/cxxsupp/libcxx/include/format index 8817dceb1e..2c583c1065 100644 --- a/contrib/libs/cxxsupp/libcxx/include/format +++ b/contrib/libs/cxxsupp/libcxx/include/format @@ -112,6 +112,40 @@ namespace std { using format_parse_context = basic_format_parse_context<char>; using wformat_parse_context = basic_format_parse_context<wchar_t>; + // [format.range], formatting of ranges + // [format.range.fmtkind], variable template format_kind + enum class range_format { // since C++23 + disabled, + map, + set, + sequence, + string, + debug_string + }; + + template<class R> + constexpr unspecified format_kind = unspecified; // since C++23 + + template<ranges::input_range R> + requires same_as<R, remove_cvref_t<R>> + constexpr range_format format_kind<R> = see below; // since C++23 + + // [format.range.formatter], class template range_formatter + template<class T, class charT = char> + requires same_as<remove_cvref_t<T>, T> && formattable<T, charT> + class range_formatter; // since C++23 + + // [format.range.fmtdef], class template range-default-formatter + template<range_format K, ranges::input_range R, class charT> + struct range-default-formatter; // exposition only, since C++23 + + // [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr], + // specializations for maps, sets, and strings + template<ranges::input_range R, class charT> + requires (format_kind<R> != range_format::disabled) && + formattable<ranges::range_reference_t<R>, charT> + struct formatter<R, charT> : range-default-formatter<format_kind<R>, R, charT> { }; // since C++23 + // [format.arguments], arguments // [format.arg], class template basic_format_arg template<class Context> class basic_format_arg; @@ -144,6 +178,7 @@ namespace std { #include <__config> #include <__format/buffer.h> #include <__format/concepts.h> +#include <__format/container_adaptor.h> #include <__format/enable_insertable.h> #include <__format/format_arg.h> #include <__format/format_arg_store.h> @@ -162,7 +197,10 @@ namespace std { #include <__format/formatter_integer.h> #include <__format/formatter_pointer.h> #include <__format/formatter_string.h> +#include <__format/formatter_tuple.h> #include <__format/parser_std_format_spec.h> +#include <__format/range_default_formatter.h> +#include <__format/range_formatter.h> #include <__format/unicode.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/contrib/libs/cxxsupp/libcxx/include/fstream b/contrib/libs/cxxsupp/libcxx/include/fstream index 62c6f53e9f..41e95bf3dc 100644 --- a/contrib/libs/cxxsupp/libcxx/include/fstream +++ b/contrib/libs/cxxsupp/libcxx/include/fstream @@ -313,9 +313,9 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf() __owns_ib_(false), __always_noconv_(false) { - if (has_facet<codecvt<char_type, char, state_type> >(this->getloc())) + if (std::has_facet<codecvt<char_type, char, state_type> >(this->getloc())) { - __cv_ = &use_facet<codecvt<char_type, char, state_type> >(this->getloc()); + __cv_ = &std::use_facet<codecvt<char_type, char, state_type> >(this->getloc()); __always_noconv_ = __cv_->always_noconv(); } setbuf(nullptr, 4096); @@ -734,7 +734,7 @@ basic_filebuf<_CharT, _Traits>::underflow() char_type __1buf; if (this->gptr() == nullptr) this->setg(&__1buf, &__1buf+1, &__1buf+1); - const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4); + const size_t __unget_sz = __initial ? 0 : std::min<size_t>((this->egptr() - this->eback()) / 2, 4); int_type __c = traits_type::eof(); if (this->gptr() == this->egptr()) { @@ -742,7 +742,7 @@ basic_filebuf<_CharT, _Traits>::underflow() if (__always_noconv_) { size_t __nmemb = static_cast<size_t>(this->egptr() - this->eback() - __unget_sz); - __nmemb = fread(this->eback() + __unget_sz, 1, __nmemb, __file_); + __nmemb = ::fread(this->eback() + __unget_sz, 1, __nmemb, __file_); if (__nmemb != 0) { this->setg(this->eback(), @@ -840,7 +840,7 @@ basic_filebuf<_CharT, _Traits>::overflow(int_type __c) if (__always_noconv_) { size_t __nmemb = static_cast<size_t>(this->pptr() - this->pbase()); - if (fwrite(this->pbase(), sizeof(char_type), __nmemb, __file_) != __nmemb) + if (std::fwrite(this->pbase(), sizeof(char_type), __nmemb, __file_) != __nmemb) return traits_type::eof(); } else @@ -860,7 +860,7 @@ basic_filebuf<_CharT, _Traits>::overflow(int_type __c) if (__r == codecvt_base::noconv) { size_t __nmemb = static_cast<size_t>(this->pptr() - this->pbase()); - if (fwrite(this->pbase(), 1, __nmemb, __file_) != __nmemb) + if (std::fwrite(this->pbase(), 1, __nmemb, __file_) != __nmemb) return traits_type::eof(); } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) @@ -968,7 +968,7 @@ basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __way, return pos_type(off_type(-1)); pos_type __r = ftell(__file_); #else - if (fseeko(__file_, __width > 0 ? __width * __off : 0, __whence)) + if (::fseeko(__file_, __width > 0 ? __width * __off : 0, __whence)) return pos_type(off_type(-1)); pos_type __r = ftello(__file_); #endif @@ -986,7 +986,7 @@ basic_filebuf<_CharT, _Traits>::seekpos(pos_type __sp, ios_base::openmode) if (fseek(__file_, __sp, SEEK_SET)) return pos_type(off_type(-1)); #else - if (fseeko(__file_, __sp, SEEK_SET)) + if (::fseeko(__file_, __sp, SEEK_SET)) return pos_type(off_type(-1)); #endif __st_ = __sp.state(); @@ -1050,7 +1050,7 @@ basic_filebuf<_CharT, _Traits>::sync() if (fseek(__file_, -__c, SEEK_CUR)) return -1; #else - if (fseeko(__file_, -__c, SEEK_CUR)) + if (::fseeko(__file_, -__c, SEEK_CUR)) return -1; #endif if (__update_st) @@ -1067,7 +1067,7 @@ void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) { sync(); - __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); + __cv_ = &std::use_facet<codecvt<char_type, char, state_type> >(__loc); bool __old_anc = __always_noconv_; __always_noconv_ = __cv_->always_noconv(); if (__old_anc != __always_noconv_) @@ -1757,6 +1757,7 @@ _LIBCPP_POP_MACROS # include <limits> # include <new> # include <stdexcept> +# include <type_traits> #endif #endif // _LIBCPP_FSTREAM diff --git a/contrib/libs/cxxsupp/libcxx/include/future b/contrib/libs/cxxsupp/libcxx/include/future index e317e8d636..2f14a471c4 100644 --- a/contrib/libs/cxxsupp/libcxx/include/future +++ b/contrib/libs/cxxsupp/libcxx/include/future @@ -369,6 +369,7 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; #include <__memory/allocator_arg_t.h> #include <__memory/allocator_destructor.h> #include <__memory/uses_allocator.h> +#include <__type_traits/strip_signature.h> #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> @@ -624,7 +625,9 @@ class _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_HIDDEN __assoc_state : public __assoc_sub_state { typedef __assoc_sub_state base; +_LIBCPP_SUPPRESS_DEPRECATED_PUSH typedef typename aligned_storage<sizeof(_Rp), alignment_of<_Rp>::value>::type _Up; +_LIBCPP_SUPPRESS_DEPRECATED_POP protected: _Up __value_; @@ -684,7 +687,7 @@ __assoc_state<_Rp>::move() unique_lock<mutex> __lk(this->__mut_); this->__sub_wait(__lk); if (this->__exception_ != nullptr) - rethrow_exception(this->__exception_); + std::rethrow_exception(this->__exception_); return _VSTD::move(*reinterpret_cast<_Rp*>(&__value_)); } @@ -695,7 +698,7 @@ __assoc_state<_Rp>::copy() unique_lock<mutex> __lk(this->__mut_); this->__sub_wait(__lk); if (this->__exception_ != nullptr) - rethrow_exception(this->__exception_); + std::rethrow_exception(this->__exception_); return *reinterpret_cast<_Rp*>(&__value_); } @@ -755,7 +758,7 @@ __assoc_state<_Rp&>::copy() unique_lock<mutex> __lk(this->__mut_); this->__sub_wait(__lk); if (this->__exception_ != nullptr) - rethrow_exception(this->__exception_); + std::rethrow_exception(this->__exception_); return *__value_; } @@ -1625,7 +1628,7 @@ class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_base<_Rp(_ArgTypes...)> public: _LIBCPP_INLINE_VISIBILITY __packaged_task_base() {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~__packaged_task_base() {} virtual void __move_to(__packaged_task_base*) _NOEXCEPT = 0; virtual void destroy() = 0; @@ -1701,7 +1704,9 @@ class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_function<_Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY _LIBCPP_NO_CFI __base* __get_buf() { return (__base*)&__buf_; } + _LIBCPP_SUPPRESS_DEPRECATED_PUSH typename aligned_storage<3*sizeof(void*)>::type __buf_; + _LIBCPP_SUPPRESS_DEPRECATED_POP __base* __f_; public: @@ -1834,7 +1839,9 @@ __packaged_task_function<_Rp(_ArgTypes...)>::swap(__packaged_task_function& __f) { if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) { + _LIBCPP_SUPPRESS_DEPRECATED_PUSH typename aligned_storage<sizeof(__buf_)>::type __tempbuf; + _LIBCPP_SUPPRESS_DEPRECATED_POP __base* __t = (__base*)&__tempbuf; __f_->__move_to(__t); __f_->destroy(); @@ -2050,6 +2057,16 @@ public: void reset(); }; +#if _LIBCPP_STD_VER >= 17 + +template <class _Rp, class... _Args> +packaged_task(_Rp(*)(_Args...)) -> packaged_task<_Rp(_Args...)>; + +template <class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type> +packaged_task(_Fp) -> packaged_task<_Stripped>; + +#endif + template<class ..._ArgTypes> void packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) diff --git a/contrib/libs/cxxsupp/libcxx/include/iomanip b/contrib/libs/cxxsupp/libcxx/include/iomanip index 76229fcaa2..38c5c9b9c6 100644 --- a/contrib/libs/cxxsupp/libcxx/include/iomanip +++ b/contrib/libs/cxxsupp/libcxx/include/iomanip @@ -311,7 +311,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t7<_MoneyT>& __x) typedef istreambuf_iterator<_CharT, _Traits> _Ip; typedef money_get<_CharT, _Ip> _Fp; ios_base::iostate __err = ios_base::goodbit; - const _Fp& __mf = use_facet<_Fp>(__is.getloc()); + const _Fp& __mf = std::use_facet<_Fp>(__is.getloc()); __mf.get(_Ip(__is), _Ip(), __x.__intl_, __is, __err, __x.__mon_); __is.setstate(__err); } @@ -370,7 +370,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t8<_MoneyT>& __x) { typedef ostreambuf_iterator<_CharT, _Traits> _Op; typedef money_put<_CharT, _Op> _Fp; - const _Fp& __mf = use_facet<_Fp>(__os.getloc()); + const _Fp& __mf = std::use_facet<_Fp>(__os.getloc()); if (__mf.put(_Op(__os), __x.__intl_, __os, __os.fill(), __x.__mon_).failed()) __os.setstate(ios_base::badbit); } @@ -430,7 +430,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t9<_CharT>& __x) typedef istreambuf_iterator<_CharT, _Traits> _Ip; typedef time_get<_CharT, _Ip> _Fp; ios_base::iostate __err = ios_base::goodbit; - const _Fp& __tf = use_facet<_Fp>(__is.getloc()); + const _Fp& __tf = std::use_facet<_Fp>(__is.getloc()); __tf.get(_Ip(__is), _Ip(), __is, __err, __x.__tm_, __x.__fmt_, __x.__fmt_ + _Traits::length(__x.__fmt_)); __is.setstate(__err); @@ -490,7 +490,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t10<_CharT>& __x) { typedef ostreambuf_iterator<_CharT, _Traits> _Op; typedef time_put<_CharT, _Op> _Fp; - const _Fp& __tf = use_facet<_Fp>(__os.getloc()); + const _Fp& __tf = std::use_facet<_Fp>(__os.getloc()); if (__tf.put(_Op(__os), __os, __os.fill(), __x.__tm_, __x.__fmt_, __x.__fmt_ + _Traits::length(__x.__fmt_)).failed()) __os.setstate(ios_base::badbit); diff --git a/contrib/libs/cxxsupp/libcxx/include/ios b/contrib/libs/cxxsupp/libcxx/include/ios index e67b7d2b77..9eecf4d8dd 100644 --- a/contrib/libs/cxxsupp/libcxx/include/ios +++ b/contrib/libs/cxxsupp/libcxx/include/ios @@ -766,7 +766,7 @@ inline _LIBCPP_INLINE_VISIBILITY char basic_ios<_CharT, _Traits>::narrow(char_type __c, char __dfault) const { - return use_facet<ctype<char_type> >(getloc()).narrow(__c, __dfault); + return std::use_facet<ctype<char_type> >(getloc()).narrow(__c, __dfault); } template <class _CharT, class _Traits> @@ -774,7 +774,7 @@ inline _LIBCPP_INLINE_VISIBILITY _CharT basic_ios<_CharT, _Traits>::widen(char __c) const { - return use_facet<ctype<char_type> >(getloc()).widen(__c); + return std::use_facet<ctype<char_type> >(getloc()).widen(__c); } template <class _CharT, class _Traits> diff --git a/contrib/libs/cxxsupp/libcxx/include/istream b/contrib/libs/cxxsupp/libcxx/include/istream index 1c9adcc0c6..6e67d61de2 100644 --- a/contrib/libs/cxxsupp/libcxx/include/istream +++ b/contrib/libs/cxxsupp/libcxx/include/istream @@ -316,7 +316,7 @@ basic_istream<_CharT, _Traits>::sentry::sentry(basic_istream<_CharT, _Traits>& _ if (!__noskipws && (__is.flags() & ios_base::skipws)) { typedef istreambuf_iterator<_CharT, _Traits> _Ip; - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc()); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__is.getloc()); _Ip __i(__is); _Ip __eof; for (; __i != __eof; ++__i) @@ -366,7 +366,7 @@ __input_arithmetic(basic_istream<_CharT, _Traits>& __is, _Tp& __n) { #endif // _LIBCPP_NO_EXCEPTIONS typedef istreambuf_iterator<_CharT, _Traits> _Ip; typedef num_get<_CharT, _Ip> _Fp; - use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __state, __n); + std::use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __state, __n); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) @@ -476,7 +476,7 @@ __input_arithmetic_with_numeric_limits(basic_istream<_CharT, _Traits>& __is, _Tp typedef istreambuf_iterator<_CharT, _Traits> _Ip; typedef num_get<_CharT, _Ip> _Fp; long __temp; - use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __state, __temp); + std::use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __state, __temp); if (__temp < numeric_limits<_Tp>::min()) { __state |= ios_base::failbit; @@ -536,7 +536,7 @@ __input_c_string(basic_istream<_CharT, _Traits>& __is, _CharT* __p, size_t __n) { #endif _CharT* __s = __p; - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc()); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__is.getloc()); while (__s != __p + (__n-1)) { typename _Traits::int_type __i = __is.rdbuf()->sgetc(); @@ -1340,7 +1340,7 @@ ws(basic_istream<_CharT, _Traits>& __is) try { #endif // _LIBCPP_NO_EXCEPTIONS - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc()); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__is.getloc()); while (true) { typename _Traits::int_type __i = __is.rdbuf()->sgetc(); @@ -1375,7 +1375,7 @@ struct __is_istreamable : false_type { }; template <class _Stream, class _Tp> struct __is_istreamable<_Stream, _Tp, decltype( - declval<_Stream>() >> declval<_Tp>(), void() + std::declval<_Stream>() >> std::declval<_Tp>(), void() )> : true_type { }; template <class _Stream, class _Tp, class = typename enable_if< @@ -1461,7 +1461,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, if (__n <= 0) __n = numeric_limits<streamsize>::max(); streamsize __c = 0; - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc()); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__is.getloc()); while (__c < __n) { typename _Traits::int_type __i = __is.rdbuf()->sgetc(); @@ -1556,7 +1556,7 @@ basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str) { - return getline(__is, __str, __is.widen('\n')); + return std::getline(__is, __str, __is.widen('\n')); } template<class _CharT, class _Traits, class _Allocator> @@ -1565,7 +1565,7 @@ basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm) { - return getline(__is, __str, __dlm); + return std::getline(__is, __str, __dlm); } template<class _CharT, class _Traits, class _Allocator> @@ -1574,7 +1574,7 @@ basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str) { - return getline(__is, __str, __is.widen('\n')); + return std::getline(__is, __str, __is.widen('\n')); } template <class _CharT, class _Traits, size_t _Size> @@ -1590,7 +1590,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, bitset<_Size>& __x) { #endif basic_string<_CharT, _Traits> __str; - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc()); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__is.getloc()); size_t __c = 0; _CharT __zero = __ct.widen('0'); _CharT __one = __ct.widen('1'); @@ -1639,6 +1639,7 @@ _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <type_traits> #endif _LIBCPP_POP_MACROS diff --git a/contrib/libs/cxxsupp/libcxx/include/iterator b/contrib/libs/cxxsupp/libcxx/include/iterator index 679b3da317..35eca67b4a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/iterator +++ b/contrib/libs/cxxsupp/libcxx/include/iterator @@ -719,7 +719,6 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept; #include <__memory/pointer_traits.h> #include <cstddef> #include <initializer_list> -#include <type_traits> #include <version> // standard-mandated includes @@ -735,6 +734,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept; #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <exception> # include <new> +# include <type_traits> # include <typeinfo> # include <utility> #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/limits b/contrib/libs/cxxsupp/libcxx/include/limits index ee8249fa3e..9f5949e63c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/limits +++ b/contrib/libs/cxxsupp/libcxx/include/limits @@ -104,7 +104,9 @@ template<> class numeric_limits<cv long double>; #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <type_traits> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_signed.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -821,4 +823,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_LIMITS diff --git a/contrib/libs/cxxsupp/libcxx/include/locale b/contrib/libs/cxxsupp/libcxx/include/locale index 2c0df7f726..3d76ec862d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/locale +++ b/contrib/libs/cxxsupp/libcxx/include/locale @@ -211,6 +211,9 @@ template <class charT> class messages_byname; #include <streambuf> #include <version> +// TODO: Fix __bsd_locale_defaults.h +// NOLINTBEGIN(libcpp-robust-against-adl) + #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Most unix variants have catopen. These are the specific ones that don't. # if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__) @@ -446,8 +449,8 @@ string __num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms); - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms); + const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc); __thousands_sep = __np.thousands_sep(); return __np.grouping(); } @@ -459,8 +462,8 @@ __num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms); - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms); + const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc); __decimal_point = __np.decimal_point(); __thousands_sep = __np.thousands_sep(); return __np.grouping(); @@ -494,7 +497,7 @@ __num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& } return 0; } - ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms; + ptrdiff_t __f = std::find(__atoms, __atoms + 26, __ct) - __atoms; if (__f >= 24) return -1; switch (__base) @@ -547,7 +550,7 @@ __num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __ex } return 0; } - ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms; + ptrdiff_t __f = std::find(__atoms, __atoms + 32, __ct) - __atoms; if (__f >= 32) return -1; char __x = __src[__f]; @@ -677,7 +680,7 @@ public: static locale::id id; protected: - _LIBCPP_HIDE_FROM_ABI ~num_get() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {} template <class _Fp> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS @@ -849,7 +852,7 @@ __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) __libcpp_remove_reference_t<decltype(errno)> __save_errno = errno; errno = 0; char *__p2; - _Tp __ld = __do_strtod<_Tp>(__a, &__p2); + _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2); __libcpp_remove_reference_t<decltype(errno)> __current_errno = errno; if (__current_errno == 0) errno = __save_errno; @@ -892,8 +895,8 @@ num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, } return __b; } - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc()); - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc()); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__iob.getloc()); + const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__iob.getloc()); typedef typename numpunct<_CharT>::string_type string_type; const string_type __names[2] = {__np.truename(), __np.falsename()}; const string_type* __i = _VSTD::__scan_keyword(__b, __e, __names, __names+2, @@ -950,7 +953,7 @@ num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e, if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz) *__g_end++ = __dc; // Stage 3 - __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); + __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); // Digit grouping checked __check_grouping(__grouping, __g, __g_end, __err); // EOF checked @@ -1007,7 +1010,7 @@ num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e, if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz) *__g_end++ = __dc; // Stage 3 - __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); + __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); // Digit grouping checked __check_grouping(__grouping, __g, __g_end, __err); // EOF checked @@ -1062,7 +1065,7 @@ num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_typ if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz) *__g_end++ = __dc; // Stage 3 - __v = __num_get_float<_Fp>(__a, __a_end, __err); + __v = std::__num_get_float<_Fp>(__a, __a_end, __err); // Digit grouping checked __check_grouping(__grouping, __g, __g_end, __err); // EOF checked @@ -1084,8 +1087,8 @@ num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, char_type __atoms[26]; char_type __thousands_sep = 0; string __grouping; - use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src, - __num_get_base::__src + 26, __atoms); + std::use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src, + __num_get_base::__src + 26, __atoms); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; @@ -1152,8 +1155,8 @@ __num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc); - const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> > (__loc); + const numpunct<_CharT>& __npt = std::use_facet<numpunct<_CharT> >(__loc); string __grouping = __npt.grouping(); if (__grouping.empty()) { @@ -1172,7 +1175,7 @@ __num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne, *__oe++ = __ct.widen(*__nf++); *__oe++ = __ct.widen(*__nf++); } - reverse(__nf, __ne); + std::reverse(__nf, __ne); _CharT __thousands_sep = __npt.thousands_sep(); unsigned __dc = 0; unsigned __dg = 0; @@ -1189,7 +1192,7 @@ __num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne, *__oe++ = __ct.widen(*__p); ++__dc; } - reverse(__ob + (__nf - __nb), __oe); + std::reverse(__ob + (__nf - __nb), __oe); } if (__np == __ne) __op = __oe; @@ -1203,8 +1206,8 @@ __num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { - const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc); - const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc); + const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> > (__loc); + const numpunct<_CharT>& __npt = std::use_facet<numpunct<_CharT> >(__loc); string __grouping = __npt.grouping(); __oe = __ob; char* __nf = __nb; @@ -1233,7 +1236,7 @@ __num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne, } else { - reverse(__nf, __ns); + std::reverse(__nf, __ns); _CharT __thousands_sep = __npt.thousands_sep(); unsigned __dc = 0; unsigned __dg = 0; @@ -1249,7 +1252,7 @@ __num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne, *__oe++ = __ct.widen(*__p); ++__dc; } - reverse(__ob + (__nf - __nb), __oe); + std::reverse(__ob + (__nf - __nb), __oe); } for (__nf = __ns; __nf < __ne; ++__nf) { @@ -1347,7 +1350,7 @@ public: static locale::id id; protected: - _LIBCPP_HIDE_FROM_ABI ~num_put() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_put() override {} virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const; @@ -1459,7 +1462,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, { if ((__iob.flags() & ios_base::boolalpha) == 0) return do_put(__s, __iob, __fl, (unsigned long)__v); - const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc()); + const numpunct<char_type>& __np = std::use_facet<numpunct<char_type> >(__iob.getloc()); typedef typename numpunct<char_type>::string_type string_type; #ifdef _LIBCPP_ENABLE_DEBUG_MODE string_type __tmp(__v ? __np.truename() : __np.falsename()); @@ -1505,7 +1508,7 @@ num_put<_CharT, _OutputIterator>::__do_put_integral(iter_type __s, ios_base& __i this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); // [__o, __oe) contains thousands_sep'd wide number // Stage 3 & 4 - return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); + return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl); } template <class _CharT, class _OutputIterator> @@ -1593,7 +1596,7 @@ num_put<_CharT, _OutputIterator>::__do_put_floating_point(iter_type __s, ios_bas this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); // [__o, __oe) contains thousands_sep'd wide number // Stage 3 & 4 - __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl); + __s = std::__pad_and_output(__s, __ob, __op, __oe, __iob, __fl); return __s; } @@ -1628,7 +1631,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __o[2*(__nbuf-1) - 1]; char_type* __op; // pad here char_type* __oe; // end of output - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc()); __ct.widen(__nar, __ne, __o); __oe = __o + (__ne - __nar); if (__np == __ne) @@ -1637,7 +1640,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, __op = __o + (__np - __nar); // [__o, __oe) contains wide number // Stage 3 & 4 - return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); + return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl); } extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>; @@ -1792,7 +1795,7 @@ public: static locale::id id; protected: - _LIBCPP_HIDE_FROM_ABI ~time_get() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get() override {} virtual dateorder do_date_order() const; virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob, @@ -1923,7 +1926,7 @@ time_get<_CharT, _InputIterator>::__get_month(int& __m, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1; + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1; if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11) __m = __t; else @@ -1937,7 +1940,7 @@ time_get<_CharT, _InputIterator>::__get_year(int& __y, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); if (!(__err & ios_base::failbit)) { if (__t < 69) @@ -1955,7 +1958,7 @@ time_get<_CharT, _InputIterator>::__get_year4(int& __y, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); if (!(__err & ios_base::failbit)) __y = __t - 1900; } @@ -1967,7 +1970,7 @@ time_get<_CharT, _InputIterator>::__get_hour(int& __h, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); if (!(__err & ios_base::failbit) && __t <= 23) __h = __t; else @@ -1981,7 +1984,7 @@ time_get<_CharT, _InputIterator>::__get_12_hour(int& __h, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12) __h = __t; else @@ -1995,7 +1998,7 @@ time_get<_CharT, _InputIterator>::__get_minute(int& __m, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); if (!(__err & ios_base::failbit) && __t <= 59) __m = __t; else @@ -2009,7 +2012,7 @@ time_get<_CharT, _InputIterator>::__get_second(int& __s, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); if (!(__err & ios_base::failbit) && __t <= 60) __s = __t; else @@ -2023,7 +2026,7 @@ time_get<_CharT, _InputIterator>::__get_weekday(int& __w, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 1); if (!(__err & ios_base::failbit) && __t <= 6) __w = __t; else @@ -2037,7 +2040,7 @@ time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d, ios_base::iostate& __err, const ctype<char_type>& __ct) const { - int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3); + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 3); if (!(__err & ios_base::failbit) && __t <= 365) __d = __t; else @@ -2102,7 +2105,7 @@ time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e, ios_base::iostate& __err, tm* __tm, const char_type* __fmtb, const char_type* __fmte) const { - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc()); __err = ios_base::goodbit; while (__fmtb != __fmte && __err == ios_base::goodbit) { @@ -2189,7 +2192,7 @@ time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e, ios_base::iostate& __err, tm* __tm) const { - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc()); __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); return __b; } @@ -2201,7 +2204,7 @@ time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e, ios_base::iostate& __err, tm* __tm) const { - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc()); __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); return __b; } @@ -2213,7 +2216,7 @@ time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e, ios_base::iostate& __err, tm* __tm) const { - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc()); __get_year(__tm->tm_year, __b, __e, __err, __ct); return __b; } @@ -2226,7 +2229,7 @@ time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, char __fmt, char) const { __err = ios_base::goodbit; - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc()); switch (__fmt) { case 'a': @@ -2411,25 +2414,17 @@ public: __time_get_storage<_CharT>(__nm) {} protected: - _LIBCPP_HIDE_FROM_ABI ~time_get_byname() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get_byname() override {} - _LIBCPP_INLINE_VISIBILITY - dateorder do_date_order() const override {return this->__do_date_order();} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL dateorder do_date_order() const override {return this->__do_date_order();} private: - _LIBCPP_INLINE_VISIBILITY - const string_type* __weeks() const override {return this->__weeks_;} - _LIBCPP_INLINE_VISIBILITY - const string_type* __months() const override {return this->__months_;} - _LIBCPP_INLINE_VISIBILITY - const string_type* __am_pm() const override {return this->__am_pm_;} - _LIBCPP_INLINE_VISIBILITY - const string_type& __c() const override {return this->__c_;} - _LIBCPP_INLINE_VISIBILITY - const string_type& __r() const override {return this->__r_;} - _LIBCPP_INLINE_VISIBILITY - const string_type& __x() const override {return this->__x_;} - _LIBCPP_INLINE_VISIBILITY - const string_type& __X() const override {return this->__X_;} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __weeks() const override {return this->__weeks_;} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __months() const override {return this->__months_;} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __am_pm() const override {return this->__am_pm_;} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __c() const override {return this->__c_;} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __r() const override {return this->__r_;} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __x() const override {return this->__x_;} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __X() const override {return this->__X_;} }; extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>; @@ -2479,7 +2474,7 @@ public: static locale::id id; protected: - _LIBCPP_HIDE_FROM_ABI ~time_put() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put() override {} virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; @@ -2504,7 +2499,7 @@ time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob, const char_type* __pb, const char_type* __pe) const { - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__iob.getloc()); for (; __pb != __pe; ++__pb) { if (__ct.narrow(*__pb, 0) == '%') @@ -2570,7 +2565,7 @@ protected: #if defined(_MSC_VER) && defined(__clang__) ~time_put_byname() {} #else - _LIBCPP_HIDE_FROM_ABI ~time_put_byname() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {} #endif }; @@ -2619,7 +2614,7 @@ public: static const bool intl = _International; protected: - _LIBCPP_HIDE_FROM_ABI ~moneypunct() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {} virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();} virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();} @@ -2669,7 +2664,7 @@ public: : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());} protected: - _LIBCPP_HIDE_FROM_ABI ~moneypunct_byname() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {} char_type do_decimal_point() const override {return __decimal_point_;} char_type do_thousands_sep() const override {return __thousands_sep_;} @@ -2736,7 +2731,7 @@ __money_get<_CharT>::__gather_info(bool __intl, const locale& __loc, if (__intl) { const moneypunct<char_type, true>& __mp = - use_facet<moneypunct<char_type, true> >(__loc); + std::use_facet<moneypunct<char_type, true> >(__loc); __pat = __mp.neg_format(); __nsn = __mp.negative_sign(); __psn = __mp.positive_sign(); @@ -2749,7 +2744,7 @@ __money_get<_CharT>::__gather_info(bool __intl, const locale& __loc, else { const moneypunct<char_type, false>& __mp = - use_facet<moneypunct<char_type, false> >(__loc); + std::use_facet<moneypunct<char_type, false> >(__loc); __pat = __mp.neg_format(); __nsn = __mp.negative_sign(); __psn = __mp.positive_sign(); @@ -2797,7 +2792,7 @@ public: static locale::id id; protected: - _LIBCPP_HIDE_FROM_ABI ~money_get() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {} virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, @@ -2833,7 +2828,7 @@ __double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e) if (__new_cap == 0) __new_cap = sizeof(_Tp); size_t __n_off = static_cast<size_t>(__n - __b.get()); - _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap); + _Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap); if (__t == 0) __throw_bad_alloc(); if (__owns) @@ -2948,7 +2943,7 @@ money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e, ++__sym_space_end; const size_t __num_spaces = __sym_space_end - __sym.begin(); if (__num_spaces > __spaces.size() || - !equal(__spaces.end() - __num_spaces, __spaces.end(), + !std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) { // No match. Put __sym_space_end back at the // beginning of __sym, which will prevent a @@ -2979,14 +2974,14 @@ money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e, if (__ct.is(ctype_base::digit, __c)) { if (__wn == __we) - __double_or_nothing(__wb, __wn, __we); + std::__double_or_nothing(__wb, __wn, __we); *__wn++ = __c; ++__ng; } else if (__grp.size() > 0 && __ng > 0 && __c == __ts) { if (__gn == __ge) - __double_or_nothing(__gb, __gn, __ge); + std::__double_or_nothing(__gb, __gn, __ge); *__gn++ = __ng; __ng = 0; } @@ -2996,7 +2991,7 @@ money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e, if (__gb.get() != __gn && __ng > 0) { if (__gn == __ge) - __double_or_nothing(__gb, __gn, __ge); + std::__double_or_nothing(__gb, __gn, __ge); *__gn++ = __ng; } if (__fd > 0) @@ -3014,7 +3009,7 @@ money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e, return false; } if (__wn == __we) - __double_or_nothing(__wb, __wn, __we); + std::__double_or_nothing(__wb, __wn, __we); *__wn++ = *__b; } } @@ -3064,7 +3059,7 @@ money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, char_type* __wn; char_type* __we = __wbuf + __bz; locale __loc = __iob.getloc(); - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc); bool __neg = false; if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) @@ -3085,7 +3080,7 @@ money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, if (__neg) *__nc++ = '-'; for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc) - *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms]; + *__nc = __src[std::find(__atoms, _VSTD::end(__atoms), *__w) - __atoms]; *__nc = char(); if (sscanf(__nbuf, "%Lf", &__v) != 1) __throw_runtime_error("money_get error"); @@ -3108,7 +3103,7 @@ money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, char_type* __wn; char_type* __we = __wbuf + __bz; locale __loc = __iob.getloc(); - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc); bool __neg = false; if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) @@ -3170,7 +3165,7 @@ __money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc, if (__intl) { const moneypunct<char_type, true>& __mp = - use_facet<moneypunct<char_type, true> >(__loc); + std::use_facet<moneypunct<char_type, true> >(__loc); if (__neg) { __pat = __mp.neg_format(); @@ -3190,7 +3185,7 @@ __money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc, else { const moneypunct<char_type, false>& __mp = - use_facet<moneypunct<char_type, false> >(__loc); + std::use_facet<moneypunct<char_type, false> >(__loc); if (__neg) { __pat = __mp.neg_format(); @@ -3290,7 +3285,7 @@ __money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __m } } // reverse it - reverse(__t, __me); + std::reverse(__t, __me); } break; } @@ -3341,7 +3336,7 @@ public: static locale::id id; protected: - _LIBCPP_HIDE_FROM_ABI ~money_put() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {} virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const; @@ -3382,7 +3377,7 @@ money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl, } // gather info locale __loc = __iob.getloc(); - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc); __ct.widen(__bb, __bb + __n, __db); bool __neg = __n > 0 && __bb[0] == '-'; money_base::pattern __pat; @@ -3414,7 +3409,7 @@ money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl, this->__format(__mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); - return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); } template <class _CharT, class _OutputIterator> @@ -3425,7 +3420,7 @@ money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl, { // gather info locale __loc = __iob.getloc(); - const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); + const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc); bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-'); money_base::pattern __pat; char_type __dp; @@ -3456,7 +3451,7 @@ money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl, this->__format(__mb, __mi, __me, __iob.flags(), __digits.data(), __digits.data() + __digits.size(), __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); - return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); } extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>; @@ -3509,7 +3504,7 @@ public: static locale::id id; protected: - _LIBCPP_HIDE_FROM_ABI ~messages() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages() override {} virtual catalog do_open(const basic_string<char>&, const locale&) const; virtual string_type do_get(catalog, int __set, int __msgid, @@ -3543,7 +3538,7 @@ messages<_CharT>::do_get(catalog __c, int __set, int __msgid, { #ifdef _LIBCPP_HAS_CATOPEN string __ndflt; - __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt), + __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(std::back_inserter(__ndflt), __dflt.c_str(), __dflt.c_str() + __dflt.size()); if (__c != -1) @@ -3551,7 +3546,7 @@ messages<_CharT>::do_get(catalog __c, int __set, int __msgid, nl_catd __cat = (nl_catd)__c; char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str()); string_type __w; - __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w), + __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(std::back_inserter(__w), __n, __n + _VSTD::strlen(__n)); return __w; #else // !_LIBCPP_HAS_CATOPEN @@ -3598,7 +3593,7 @@ public: : messages<_CharT>(__refs) {} protected: - _LIBCPP_HIDE_FROM_ABI ~messages_byname() override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {} }; extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>; @@ -3998,7 +3993,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP char_type __1buf; if (this->gptr() == 0) this->setg(&__1buf, &__1buf+1, &__1buf+1); - const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4); + const size_t __unget_sz = __initial ? 0 : std::min<size_t>((this->egptr() - this->eback()) / 2, 4); int_type __c = traits_type::eof(); if (this->gptr() == this->egptr()) { @@ -4269,7 +4264,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP { if (this->gptr() != this->egptr()) { - reverse(this->gptr(), this->egptr()); + std::reverse(this->gptr(), this->egptr()); codecvt_base::result __r; const char_type* __e = this->gptr(); char* __extbe; @@ -4362,12 +4357,15 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +// NOLINTEND(libcpp-robust-against-adl) + #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> # include <concepts> # include <cstdarg> # include <iterator> # include <stdexcept> +# include <type_traits> # include <typeinfo> #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/math.h b/contrib/libs/cxxsupp/libcxx/include/math.h index f2d4eaedf8..7f9330eb1a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/math.h +++ b/contrib/libs/cxxsupp/libcxx/include/math.h @@ -307,10 +307,13 @@ long double truncl(long double x); // back to C++ linkage before including these C++ headers. extern "C++" { +#include <__type_traits/enable_if.h> +#include <__type_traits/is_floating_point.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_same.h> #include <__type_traits/promote.h> #include <limits> #include <stdlib.h> -#include <type_traits> # ifdef fpclassify @@ -364,29 +367,29 @@ extern "C++" { // signbit template <class _A1, std::__enable_if_t<std::is_floating_point<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __builtin_signbit(__x); } template <class _A1, std::__enable_if_t<std::is_integral<_A1>::value && std::is_signed<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; } template <class _A1, std::__enable_if_t<std::is_integral<_A1>::value && !std::is_signed<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { return false; } // fpclassify template <class _A1, std::__enable_if_t<std::is_floating_point<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI int fpclassify(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI int fpclassify(_A1 __x) _NOEXCEPT { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, __x); } template <class _A1, std::__enable_if_t<std::is_integral<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI int fpclassify(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI int fpclassify(_A1 __x) _NOEXCEPT { return __x == 0 ? FP_ZERO : FP_NORMAL; } @@ -397,13 +400,13 @@ inline _LIBCPP_HIDE_FROM_ABI int fpclassify(_A1 __x) _NOEXCEPT { template <class _A1, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { return __builtin_isfinite((typename std::__promote<_A1>::type)__x); } template <class _A1, std::__enable_if_t<std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { return true; } @@ -411,54 +414,66 @@ inline _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { template <class _A1, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { return __builtin_isinf((typename std::__promote<_A1>::type)__x); } template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI typename std::enable_if< std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity, bool>::type isinf(_A1) _NOEXCEPT { return false; } #if defined(_LIBCPP_PREFERRED_OVERLOAD) && !defined(__CUDACC__) -inline _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { return __builtin_isinf(__x); } +_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { + return __builtin_isinf(__x); +} -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isinf(double __x) _NOEXCEPT { return __builtin_isinf(__x); } +_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isinf(double __x) _NOEXCEPT { + return __builtin_isinf(__x); +} -inline _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { return __builtin_isinf(__x); } +_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { + return __builtin_isinf(__x); +} # endif // isnan template <class _A1, std::__enable_if_t<std::is_floating_point<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { return __builtin_isnan(__x); } template <class _A1, std::__enable_if_t<std::is_integral<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { return false; } #if defined(_LIBCPP_PREFERRED_OVERLOAD) && !defined(__CUDACC__) -inline _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { return __builtin_isnan(__x); } +_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { + return __builtin_isnan(__x); +} -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isnan(double __x) _NOEXCEPT { return __builtin_isnan(__x); } +_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isnan(double __x) _NOEXCEPT { + return __builtin_isnan(__x); +} -inline _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { return __builtin_isnan(__x); } +_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { + return __builtin_isnan(__x); +} # endif // isnormal template <class _A1, std::__enable_if_t<std::is_floating_point<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __builtin_isnormal(__x); } template <class _A1, std::__enable_if_t<std::is_integral<_A1>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __x != 0; } @@ -467,7 +482,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { template <class _A1, class _A2, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { typedef typename std::__promote<_A1, _A2>::type type; return __builtin_isgreater((type)__x, (type)__y); } @@ -477,7 +492,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { template <class _A1, class _A2, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { typedef typename std::__promote<_A1, _A2>::type type; return __builtin_isgreaterequal((type)__x, (type)__y); } @@ -487,7 +502,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { template <class _A1, class _A2, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { typedef typename std::__promote<_A1, _A2>::type type; return __builtin_isless((type)__x, (type)__y); } @@ -497,7 +512,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { template <class _A1, class _A2, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { typedef typename std::__promote<_A1, _A2>::type type; return __builtin_islessequal((type)__x, (type)__y); } @@ -507,7 +522,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { template <class _A1, class _A2, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { typedef typename std::__promote<_A1, _A2>::type type; return __builtin_islessgreater((type)__x, (type)__y); } @@ -517,7 +532,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { template <class _A1, class _A2, std::__enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { typedef typename std::__promote<_A1, _A2>::type type; return __builtin_isunordered((type)__x, (type)__y); } @@ -532,10 +547,21 @@ inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { // // handled in stdlib.h +// We have to provide double overloads for <math.h> to work on platforms that don't provide the full set of math +// functions. To make the overload set work with multiple functions that take the same arguments, we make our overloads +// templates. Functions are preferred over function templates during overload resolution, which means that our overload +// will only be selected when the C library doesn't provide one. + // acos # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float acos(float __x) _NOEXCEPT {return __builtin_acosf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double acos(double __x) _NOEXCEPT { + return __builtin_acos(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double acos(long double __x) _NOEXCEPT {return __builtin_acosl(__x);} # endif @@ -548,6 +574,12 @@ acos(_A1 __x) _NOEXCEPT {return __builtin_acos((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float asin(float __x) _NOEXCEPT {return __builtin_asinf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double asin(double __x) _NOEXCEPT { + return __builtin_asin(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double asin(long double __x) _NOEXCEPT {return __builtin_asinl(__x);} # endif @@ -560,6 +592,12 @@ asin(_A1 __x) _NOEXCEPT {return __builtin_asin((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float atan(float __x) _NOEXCEPT {return __builtin_atanf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double atan(double __x) _NOEXCEPT { + return __builtin_atan(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double atan(long double __x) _NOEXCEPT {return __builtin_atanl(__x);} # endif @@ -572,6 +610,12 @@ atan(_A1 __x) _NOEXCEPT {return __builtin_atan((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float atan2(float __y, float __x) _NOEXCEPT {return __builtin_atan2f(__y, __x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double atan2(double __x, double __y) _NOEXCEPT { + return __builtin_atan2(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double atan2(long double __y, long double __x) _NOEXCEPT {return __builtin_atan2l(__y, __x);} # endif @@ -594,12 +638,18 @@ atan2(_A1 __y, _A2 __x) _NOEXCEPT // ceil # if !defined(__sun__) -inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT {return __builtin_ceilf(__x);} -inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT {return __builtin_ceill(__x);} +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT {return __builtin_ceilf(__x);} + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { + return __builtin_ceil(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT {return __builtin_ceill(__x);} # endif template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type ceil(_A1 __x) _NOEXCEPT {return __builtin_ceil((double)__x);} @@ -607,6 +657,12 @@ ceil(_A1 __x) _NOEXCEPT {return __builtin_ceil((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float cos(float __x) _NOEXCEPT {return __builtin_cosf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double cos(double __x) _NOEXCEPT { + return __builtin_cos(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double cos(long double __x) _NOEXCEPT {return __builtin_cosl(__x);} # endif @@ -619,6 +675,12 @@ cos(_A1 __x) _NOEXCEPT {return __builtin_cos((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float cosh(float __x) _NOEXCEPT {return __builtin_coshf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double cosh(double __x) _NOEXCEPT { + return __builtin_cosh(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double cosh(long double __x) _NOEXCEPT {return __builtin_coshl(__x);} # endif @@ -631,6 +693,12 @@ cosh(_A1 __x) _NOEXCEPT {return __builtin_cosh((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float exp(float __x) _NOEXCEPT {return __builtin_expf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double exp(double __x) _NOEXCEPT { + return __builtin_exp(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double exp(long double __x) _NOEXCEPT {return __builtin_expl(__x);} # endif @@ -642,24 +710,36 @@ exp(_A1 __x) _NOEXCEPT {return __builtin_exp((double)__x);} // fabs # if !defined(__sun__) -inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT {return __builtin_fabsf(__x);} -inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT {return __builtin_fabsl(__x);} +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT {return __builtin_fabsf(__x);} + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { + return __builtin_fabs(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT {return __builtin_fabsl(__x);} # endif template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type fabs(_A1 __x) _NOEXCEPT {return __builtin_fabs((double)__x);} // floor # if !defined(__sun__) -inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT {return __builtin_floorf(__x);} -inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT {return __builtin_floorl(__x);} +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT {return __builtin_floorf(__x);} + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { + return __builtin_floor(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT {return __builtin_floorl(__x);} # endif template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type floor(_A1 __x) _NOEXCEPT {return __builtin_floor((double)__x);} @@ -667,6 +747,12 @@ floor(_A1 __x) _NOEXCEPT {return __builtin_floor((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float fmod(float __x, float __y) _NOEXCEPT {return __builtin_fmodf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double fmod(double __x, double __y) _NOEXCEPT { + return __builtin_fmod(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double fmod(long double __x, long double __y) _NOEXCEPT {return __builtin_fmodl(__x, __y);} # endif @@ -690,6 +776,12 @@ fmod(_A1 __x, _A2 __y) _NOEXCEPT # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float frexp(float __x, int* __e) _NOEXCEPT {return __builtin_frexpf(__x, __e);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double frexp(double __x, int* __e) _NOEXCEPT { + return __builtin_frexp(__x, __e); +} + inline _LIBCPP_HIDE_FROM_ABI long double frexp(long double __x, int* __e) _NOEXCEPT {return __builtin_frexpl(__x, __e);} # endif @@ -702,6 +794,12 @@ frexp(_A1 __x, int* __e) _NOEXCEPT {return __builtin_frexp((double)__x, __e);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float ldexp(float __x, int __e) _NOEXCEPT {return __builtin_ldexpf(__x, __e);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double ldexp(double __x, int __e) _NOEXCEPT { + return __builtin_ldexp(__x, __e); +} + inline _LIBCPP_HIDE_FROM_ABI long double ldexp(long double __x, int __e) _NOEXCEPT {return __builtin_ldexpl(__x, __e);} # endif @@ -714,6 +812,12 @@ ldexp(_A1 __x, int __e) _NOEXCEPT {return __builtin_ldexp((double)__x, __e);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float log(float __x) _NOEXCEPT {return __builtin_logf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double log(double __x) _NOEXCEPT { + return __builtin_log(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double log(long double __x) _NOEXCEPT {return __builtin_logl(__x);} # endif @@ -726,6 +830,13 @@ log(_A1 __x) _NOEXCEPT {return __builtin_log((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float log10(float __x) _NOEXCEPT {return __builtin_log10f(__x);} + + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double log10(double __x) _NOEXCEPT { + return __builtin_log10(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double log10(long double __x) _NOEXCEPT {return __builtin_log10l(__x);} # endif @@ -738,6 +849,12 @@ log10(_A1 __x) _NOEXCEPT {return __builtin_log10((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float modf(float __x, float* __y) _NOEXCEPT {return __builtin_modff(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double modf(double __x, double* __y) _NOEXCEPT { + return __builtin_modf(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double modf(long double __x, long double* __y) _NOEXCEPT {return __builtin_modfl(__x, __y);} # endif @@ -745,6 +862,12 @@ inline _LIBCPP_HIDE_FROM_ABI long double modf(long double __x, long double* __y) # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float pow(float __x, float __y) _NOEXCEPT {return __builtin_powf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double pow(double __x, double __y) _NOEXCEPT { + return __builtin_pow(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double pow(long double __x, long double __y) _NOEXCEPT {return __builtin_powl(__x, __y);} # endif @@ -768,6 +891,12 @@ pow(_A1 __x, _A2 __y) _NOEXCEPT # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float sin(float __x) _NOEXCEPT {return __builtin_sinf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double sin(double __x) _NOEXCEPT { + return __builtin_sin(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double sin(long double __x) _NOEXCEPT {return __builtin_sinl(__x);} #endif @@ -780,6 +909,12 @@ sin(_A1 __x) _NOEXCEPT {return __builtin_sin((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float sinh(float __x) _NOEXCEPT {return __builtin_sinhf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double sinh(double __x) _NOEXCEPT { + return __builtin_sinh(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double sinh(long double __x) _NOEXCEPT {return __builtin_sinhl(__x);} # endif @@ -792,6 +927,12 @@ sinh(_A1 __x) _NOEXCEPT {return __builtin_sinh((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float sqrt(float __x) _NOEXCEPT {return __builtin_sqrtf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double sqrt(double __x) _NOEXCEPT { + return __builtin_sqrt(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double sqrt(long double __x) _NOEXCEPT {return __builtin_sqrtl(__x);} # endif @@ -804,6 +945,12 @@ sqrt(_A1 __x) _NOEXCEPT {return __builtin_sqrt((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float tan(float __x) _NOEXCEPT {return __builtin_tanf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double tan(double __x) _NOEXCEPT { + return __builtin_tan(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double tan(long double __x) _NOEXCEPT {return __builtin_tanl(__x);} # endif @@ -816,6 +963,12 @@ tan(_A1 __x) _NOEXCEPT {return __builtin_tan((double)__x);} # if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float tanh(float __x) _NOEXCEPT {return __builtin_tanhf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double tanh(double __x) _NOEXCEPT { + return __builtin_tanh(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double tanh(long double __x) _NOEXCEPT {return __builtin_tanhl(__x);} # endif @@ -827,6 +980,12 @@ tanh(_A1 __x) _NOEXCEPT {return __builtin_tanh((double)__x);} // acosh inline _LIBCPP_HIDE_FROM_ABI float acosh(float __x) _NOEXCEPT {return __builtin_acoshf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double acosh(double __x) _NOEXCEPT { + return __builtin_acosh(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double acosh(long double __x) _NOEXCEPT {return __builtin_acoshl(__x);} template <class _A1> @@ -837,6 +996,12 @@ acosh(_A1 __x) _NOEXCEPT {return __builtin_acosh((double)__x);} // asinh inline _LIBCPP_HIDE_FROM_ABI float asinh(float __x) _NOEXCEPT {return __builtin_asinhf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double asinh(double __x) _NOEXCEPT { + return __builtin_asinh(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double asinh(long double __x) _NOEXCEPT {return __builtin_asinhl(__x);} template <class _A1> @@ -847,6 +1012,12 @@ asinh(_A1 __x) _NOEXCEPT {return __builtin_asinh((double)__x);} // atanh inline _LIBCPP_HIDE_FROM_ABI float atanh(float __x) _NOEXCEPT {return __builtin_atanhf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double atanh(double __x) _NOEXCEPT { + return __builtin_atanh(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double atanh(long double __x) _NOEXCEPT {return __builtin_atanhl(__x);} template <class _A1> @@ -856,57 +1027,32 @@ atanh(_A1 __x) _NOEXCEPT {return __builtin_atanh((double)__x);} // cbrt -inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT {return __builtin_cbrtf(__x);} -inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT {return __builtin_cbrtl(__x);} +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT {return __builtin_cbrtf(__x);} + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double cbrt(double __x) _NOEXCEPT { + return __builtin_cbrt(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT {return __builtin_cbrtl(__x);} template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type cbrt(_A1 __x) _NOEXCEPT {return __builtin_cbrt((double)__x);} // copysign -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI float __libcpp_copysign(float __x, float __y) _NOEXCEPT { - return __builtin_copysignf(__x, __y); -} - -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI double __libcpp_copysign(double __x, double __y) _NOEXCEPT { - return __builtin_copysign(__x, __y); -} - -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI long double __libcpp_copysign(long double __x, long double __y) _NOEXCEPT { - return __builtin_copysignl(__x, __y); -} - -template <class _A1, class _A2> -_LIBCPP_CONSTEXPR -inline _LIBCPP_HIDE_FROM_ABI -typename std::__enable_if_t -< - std::is_arithmetic<_A1>::value && - std::is_arithmetic<_A2>::value, - std::__promote<_A1, _A2> ->::type -__libcpp_copysign(_A1 __x, _A2 __y) _NOEXCEPT { - typedef typename std::__promote<_A1, _A2>::type __result_type; - static_assert((!(std::_IsSame<_A1, __result_type>::value && - std::_IsSame<_A2, __result_type>::value)), ""); - return __builtin_copysign((__result_type)__x, (__result_type)__y); -} - -inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { - return ::__libcpp_copysign(__x, __y); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { + return ::__builtin_copysignf(__x, __y); } -inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { - return ::__libcpp_copysign(__x, __y); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { + return ::__builtin_copysignl(__x, __y); } template <class _A1, class _A2> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::__enable_if_t < std::is_arithmetic<_A1>::value && @@ -914,12 +1060,18 @@ typename std::__enable_if_t std::__promote<_A1, _A2> >::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { - return ::__libcpp_copysign(__x, __y); + return ::__builtin_copysign(__x, __y); } // erf inline _LIBCPP_HIDE_FROM_ABI float erf(float __x) _NOEXCEPT {return __builtin_erff(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double erf(double __x) _NOEXCEPT { + return __builtin_erf(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double erf(long double __x) _NOEXCEPT {return __builtin_erfl(__x);} template <class _A1> @@ -930,6 +1082,12 @@ erf(_A1 __x) _NOEXCEPT {return __builtin_erf((double)__x);} // erfc inline _LIBCPP_HIDE_FROM_ABI float erfc(float __x) _NOEXCEPT {return __builtin_erfcf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double erfc(double __x) _NOEXCEPT { + return __builtin_erfc(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double erfc(long double __x) _NOEXCEPT {return __builtin_erfcl(__x);} template <class _A1> @@ -940,6 +1098,12 @@ erfc(_A1 __x) _NOEXCEPT {return __builtin_erfc((double)__x);} // exp2 inline _LIBCPP_HIDE_FROM_ABI float exp2(float __x) _NOEXCEPT {return __builtin_exp2f(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double exp2(double __x) _NOEXCEPT { + return __builtin_exp2(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double exp2(long double __x) _NOEXCEPT {return __builtin_exp2l(__x);} template <class _A1> @@ -950,6 +1114,12 @@ exp2(_A1 __x) _NOEXCEPT {return __builtin_exp2((double)__x);} // expm1 inline _LIBCPP_HIDE_FROM_ABI float expm1(float __x) _NOEXCEPT {return __builtin_expm1f(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double expm1(double __x) _NOEXCEPT { + return __builtin_expm1(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double expm1(long double __x) _NOEXCEPT {return __builtin_expm1l(__x);} template <class _A1> @@ -960,6 +1130,12 @@ expm1(_A1 __x) _NOEXCEPT {return __builtin_expm1((double)__x);} // fdim inline _LIBCPP_HIDE_FROM_ABI float fdim(float __x, float __y) _NOEXCEPT {return __builtin_fdimf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double fdim(double __x, double __y) _NOEXCEPT { + return __builtin_fdim(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double fdim(long double __x, long double __y) _NOEXCEPT {return __builtin_fdiml(__x, __y);} template <class _A1, class _A2> @@ -984,6 +1160,13 @@ inline _LIBCPP_HIDE_FROM_ABI float fma(float __x, float __y, float __z) _N { return __builtin_fmaf(__x, __y, __z); } + + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double fma(double __x, double __y, double __z) _NOEXCEPT { + return __builtin_fma(__x, __y, __z); +} + inline _LIBCPP_HIDE_FROM_ABI long double fma(long double __x, long double __y, long double __z) _NOEXCEPT { return __builtin_fmal(__x, __y, __z); @@ -1009,11 +1192,17 @@ fma(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT // fmax -inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT {return __builtin_fmaxf(__x, __y);} -inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT {return __builtin_fmaxl(__x, __y);} +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT {return __builtin_fmaxf(__x, __y);} + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT { + return __builtin_fmax(__x, __y); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT {return __builtin_fmaxl(__x, __y);} template <class _A1, class _A2> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::__enable_if_t < std::is_arithmetic<_A1>::value && @@ -1030,11 +1219,17 @@ fmax(_A1 __x, _A2 __y) _NOEXCEPT // fmin -inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT {return __builtin_fminf(__x, __y);} -inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT {return __builtin_fminl(__x, __y);} +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT {return __builtin_fminf(__x, __y);} + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT { + return __builtin_fmin(__x, __y); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT {return __builtin_fminl(__x, __y);} template <class _A1, class _A2> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::__enable_if_t < std::is_arithmetic<_A1>::value && @@ -1052,6 +1247,12 @@ fmin(_A1 __x, _A2 __y) _NOEXCEPT // hypot inline _LIBCPP_HIDE_FROM_ABI float hypot(float __x, float __y) _NOEXCEPT {return __builtin_hypotf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double hypot(double __x, double __y) _NOEXCEPT { + return __builtin_hypot(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y) _NOEXCEPT {return __builtin_hypotl(__x, __y);} template <class _A1, class _A2> @@ -1073,6 +1274,12 @@ hypot(_A1 __x, _A2 __y) _NOEXCEPT // ilogb inline _LIBCPP_HIDE_FROM_ABI int ilogb(float __x) _NOEXCEPT {return __builtin_ilogbf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double ilogb(double __x) _NOEXCEPT { + return __builtin_ilogb(__x); +} + inline _LIBCPP_HIDE_FROM_ABI int ilogb(long double __x) _NOEXCEPT {return __builtin_ilogbl(__x);} template <class _A1> @@ -1083,6 +1290,12 @@ ilogb(_A1 __x) _NOEXCEPT {return __builtin_ilogb((double)__x);} // lgamma inline _LIBCPP_HIDE_FROM_ABI float lgamma(float __x) _NOEXCEPT {return __builtin_lgammaf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double lgamma(double __x) _NOEXCEPT { + return __builtin_lgamma(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double lgamma(long double __x) _NOEXCEPT {return __builtin_lgammal(__x);} template <class _A1> @@ -1096,6 +1309,12 @@ inline _LIBCPP_HIDE_FROM_ABI long long llrint(float __x) _NOEXCEPT { return __builtin_llrintf(__x); } + +template <class = int> +_LIBCPP_HIDE_FROM_ABI long long llrint(double __x) _NOEXCEPT { + return __builtin_llrint(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long long llrint(long double __x) _NOEXCEPT { return __builtin_llrintl(__x); @@ -1115,6 +1334,12 @@ inline _LIBCPP_HIDE_FROM_ABI long long llround(float __x) _NOEXCEPT { return __builtin_llroundf(__x); } + +template <class = int> +_LIBCPP_HIDE_FROM_ABI long long llround(double __x) _NOEXCEPT { + return __builtin_llround(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long long llround(long double __x) _NOEXCEPT { return __builtin_llroundl(__x); @@ -1131,6 +1356,12 @@ llround(_A1 __x) _NOEXCEPT // log1p inline _LIBCPP_HIDE_FROM_ABI float log1p(float __x) _NOEXCEPT {return __builtin_log1pf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double log1p(double __x) _NOEXCEPT { + return __builtin_log1p(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double log1p(long double __x) _NOEXCEPT {return __builtin_log1pl(__x);} template <class _A1> @@ -1141,6 +1372,12 @@ log1p(_A1 __x) _NOEXCEPT {return __builtin_log1p((double)__x);} // log2 inline _LIBCPP_HIDE_FROM_ABI float log2(float __x) _NOEXCEPT {return __builtin_log2f(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double log2(double __x) _NOEXCEPT { + return __builtin_log2(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double log2(long double __x) _NOEXCEPT {return __builtin_log2l(__x);} template <class _A1> @@ -1151,6 +1388,12 @@ log2(_A1 __x) _NOEXCEPT {return __builtin_log2((double)__x);} // logb inline _LIBCPP_HIDE_FROM_ABI float logb(float __x) _NOEXCEPT {return __builtin_logbf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double logb(double __x) _NOEXCEPT { + return __builtin_logb(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double logb(long double __x) _NOEXCEPT {return __builtin_logbl(__x);} template <class _A1> @@ -1164,6 +1407,12 @@ inline _LIBCPP_HIDE_FROM_ABI long lrint(float __x) _NOEXCEPT { return __builtin_lrintf(__x); } + +template <class = int> +_LIBCPP_HIDE_FROM_ABI long lrint(double __x) _NOEXCEPT { + return __builtin_lrint(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long lrint(long double __x) _NOEXCEPT { return __builtin_lrintl(__x); @@ -1183,6 +1432,12 @@ inline _LIBCPP_HIDE_FROM_ABI long lround(float __x) _NOEXCEPT { return __builtin_lroundf(__x); } + +template <class = int> +_LIBCPP_HIDE_FROM_ABI long lround(double __x) _NOEXCEPT { + return __builtin_lround(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long lround(long double __x) _NOEXCEPT { return __builtin_lroundl(__x); @@ -1200,17 +1455,29 @@ lround(_A1 __x) _NOEXCEPT // nearbyint -inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT {return __builtin_nearbyintf(__x);} -inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT {return __builtin_nearbyintl(__x);} +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT {return __builtin_nearbyintf(__x);} + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double nearbyint(double __x) _NOEXCEPT { + return __builtin_nearbyint(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT {return __builtin_nearbyintl(__x);} template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type nearbyint(_A1 __x) _NOEXCEPT {return __builtin_nearbyint((double)__x);} // nextafter inline _LIBCPP_HIDE_FROM_ABI float nextafter(float __x, float __y) _NOEXCEPT {return __builtin_nextafterf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double nextafter(double __x, double __y) _NOEXCEPT { + return __builtin_nextafter(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double nextafter(long double __x, long double __y) _NOEXCEPT {return __builtin_nextafterl(__x, __y);} template <class _A1, class _A2> @@ -1232,6 +1499,12 @@ nextafter(_A1 __x, _A2 __y) _NOEXCEPT // nexttoward inline _LIBCPP_HIDE_FROM_ABI float nexttoward(float __x, long double __y) _NOEXCEPT {return __builtin_nexttowardf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double nexttoward(double __x, long double __y) _NOEXCEPT { + return __builtin_nexttoward(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double nexttoward(long double __x, long double __y) _NOEXCEPT {return __builtin_nexttowardl(__x, __y);} template <class _A1> @@ -1242,6 +1515,12 @@ nexttoward(_A1 __x, long double __y) _NOEXCEPT {return __builtin_nexttoward((dou // remainder inline _LIBCPP_HIDE_FROM_ABI float remainder(float __x, float __y) _NOEXCEPT {return __builtin_remainderf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double remainder(double __x, double __y) _NOEXCEPT { + return __builtin_remainder(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double remainder(long double __x, long double __y) _NOEXCEPT {return __builtin_remainderl(__x, __y);} template <class _A1, class _A2> @@ -1263,6 +1542,12 @@ remainder(_A1 __x, _A2 __y) _NOEXCEPT // remquo inline _LIBCPP_HIDE_FROM_ABI float remquo(float __x, float __y, int* __z) _NOEXCEPT {return __builtin_remquof(__x, __y, __z);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double remquo(double __x, double __y, int* __z) _NOEXCEPT { + return __builtin_remquo(__x, __y, __z); +} + inline _LIBCPP_HIDE_FROM_ABI long double remquo(long double __x, long double __y, int* __z) _NOEXCEPT {return __builtin_remquol(__x, __y, __z);} template <class _A1, class _A2> @@ -1283,17 +1568,23 @@ remquo(_A1 __x, _A2 __y, int* __z) _NOEXCEPT // rint -inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT { return __builtin_rintf(__x); } -inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double rint(double __x) _NOEXCEPT { + return __builtin_rint(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT { return __builtin_rintl(__x); } template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type rint(_A1 __x) _NOEXCEPT { @@ -1302,17 +1593,23 @@ rint(_A1 __x) _NOEXCEPT // round -inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT { return __builtin_roundf(__x); } -inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double round(double __x) _NOEXCEPT { + return __builtin_round(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT { return __builtin_roundl(__x); } template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type round(_A1 __x) _NOEXCEPT { @@ -1322,6 +1619,12 @@ round(_A1 __x) _NOEXCEPT // scalbln inline _LIBCPP_HIDE_FROM_ABI float scalbln(float __x, long __y) _NOEXCEPT {return __builtin_scalblnf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double scalbln(double __x, long __y) _NOEXCEPT { + return __builtin_scalbln(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double scalbln(long double __x, long __y) _NOEXCEPT {return __builtin_scalblnl(__x, __y);} template <class _A1> @@ -1332,6 +1635,12 @@ scalbln(_A1 __x, long __y) _NOEXCEPT {return __builtin_scalbln((double)__x, __y) // scalbn inline _LIBCPP_HIDE_FROM_ABI float scalbn(float __x, int __y) _NOEXCEPT {return __builtin_scalbnf(__x, __y);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double scalbn(double __x, int __y) _NOEXCEPT { + return __builtin_scalbn(__x, __y); +} + inline _LIBCPP_HIDE_FROM_ABI long double scalbn(long double __x, int __y) _NOEXCEPT {return __builtin_scalbnl(__x, __y);} template <class _A1> @@ -1342,6 +1651,12 @@ scalbn(_A1 __x, int __y) _NOEXCEPT {return __builtin_scalbn((double)__x, __y);} // tgamma inline _LIBCPP_HIDE_FROM_ABI float tgamma(float __x) _NOEXCEPT {return __builtin_tgammaf(__x);} + +template <class = int> +_LIBCPP_HIDE_FROM_ABI double tgamma(double __x) _NOEXCEPT { + return __builtin_tgamma(__x); +} + inline _LIBCPP_HIDE_FROM_ABI long double tgamma(long double __x) _NOEXCEPT {return __builtin_tgammal(__x);} template <class _A1> @@ -1351,17 +1666,23 @@ tgamma(_A1 __x) _NOEXCEPT {return __builtin_tgamma((double)__x);} // trunc -inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT { return __builtin_truncf(__x); } -inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT + +template <class = int> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double trunc(double __x) _NOEXCEPT { + return __builtin_trunc(__x); +} + +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT { return __builtin_truncl(__x); } template <class _A1> -inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename std::enable_if<std::is_integral<_A1>::value, double>::type trunc(_A1 __x) _NOEXCEPT { diff --git a/contrib/libs/cxxsupp/libcxx/include/memory b/contrib/libs/cxxsupp/libcxx/include/memory index 11a8823fce..8d63fb94b7 100644 --- a/contrib/libs/cxxsupp/libcxx/include/memory +++ b/contrib/libs/cxxsupp/libcxx/include/memory @@ -569,6 +569,13 @@ template<class T> constexpr unique_ptr<T> make_unique(size_t n); // C++14, constexpr since C++23 template<class T, class... Args> unspecified make_unique(Args&&...) = delete; // C++14, T == U[N] +template<class T> + constexpr unique_ptr<T> make_unique_for_overwrite(); // T is not array, C++20, constexpr since C++23 +template<class T> + constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); // T is U[], C++20, constexpr since C++23 +template<class T, class... Args> + unspecified make_unique_for_overwrite(Args&&...) = delete; // T is U[N], C++20 + template<class E, class T, class Y, class D> basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, unique_ptr<Y, D> const& p); @@ -718,6 +725,16 @@ template<class T, class A> shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N] (since C++20) template<class T> + shared_ptr<T> make_shared_for_overwrite(); // T is not U[], C++20 +template<class T, class A> + shared_ptr<T> allocate_shared_for_overwrite(const A& a); // T is not U[], C++20 + +template<class T> + shared_ptr<T> make_shared_for_overwrite(size_t N); // T is U[], C++20 +template<class T, class A> + shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N); // T is U[], C++20 + +template<class T> class weak_ptr { public: diff --git a/contrib/libs/cxxsupp/libcxx/include/mutex b/contrib/libs/cxxsupp/libcxx/include/mutex index 92695ee8a0..dc51d572c0 100644 --- a/contrib/libs/cxxsupp/libcxx/include/mutex +++ b/contrib/libs/cxxsupp/libcxx/include/mutex @@ -356,7 +356,7 @@ try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) unique_lock<_L0> __u0(__l0, try_to_lock); if (__u0.owns_lock()) { - __r = try_lock(__l1, __l2, __l3...); + __r = std::try_lock(__l1, __l2, __l3...); if (__r == -1) __u0.release(); else @@ -407,7 +407,7 @@ __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) case 0: { unique_lock<_L0> __u0(__l0); - __i = try_lock(__l1, __l2, __l3...); + __i = std::try_lock(__l1, __l2, __l3...); if (__i == -1) { __u0.release(); @@ -420,7 +420,7 @@ __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) case 1: { unique_lock<_L1> __u1(__l1); - __i = try_lock(__l2, __l3..., __l0); + __i = std::try_lock(__l2, __l3..., __l0); if (__i == -1) { __u1.release(); @@ -434,7 +434,7 @@ __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) __libcpp_thread_yield(); break; default: - __lock_first(__i - 2, __l2, __l3..., __l0, __l1); + std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1); return; } } @@ -445,7 +445,7 @@ inline _LIBCPP_INLINE_VISIBILITY void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) { - __lock_first(0, __l0, __l1, __l2, __l3...); + std::__lock_first(0, __l0, __l1, __l2, __l3...); } template <class _L0> @@ -684,7 +684,7 @@ call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) typedef tuple<_Callable&&, _Args&&...> _Gp; _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); __call_once_param<_Gp> __p(__f); - __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); + std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); } } @@ -702,7 +702,7 @@ call_once(once_flag& __flag, _Callable& __func) #endif { __call_once_param<_Callable> __p(__func); - __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); + std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); } } @@ -718,7 +718,7 @@ call_once(once_flag& __flag, const _Callable& __func) #endif { __call_once_param<const _Callable> __p(__func); - __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); + std::__call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); } } @@ -731,6 +731,7 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> # include <functional> +# include <type_traits> #endif #endif // _LIBCPP_MUTEX diff --git a/contrib/libs/cxxsupp/libcxx/include/new b/contrib/libs/cxxsupp/libcxx/include/new index 825034c44c..aa62f81b02 100644 --- a/contrib/libs/cxxsupp/libcxx/include/new +++ b/contrib/libs/cxxsupp/libcxx/include/new @@ -89,10 +89,12 @@ void operator delete[](void* ptr, void*) noexcept; #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> #include <__config> +#include <__type_traits/is_function.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> #include <cstddef> #include <cstdlib> #include <exception> -#include <type_traits> #include <version> #if defined(_LIBCPP_ABI_VCRUNTIME) @@ -295,9 +297,9 @@ _LIBCPP_INLINE_VISIBILITY void __do_deallocate_handle_size(void *__ptr, size_t __size, _Args ...__args) { #ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION (void)__size; - return __libcpp_operator_delete(__ptr, __args...); + return std::__libcpp_operator_delete(__ptr, __args...); #else - return __libcpp_operator_delete(__ptr, __size, __args...); + return std::__libcpp_operator_delete(__ptr, __size, __args...); #endif } @@ -337,16 +339,27 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate_unsized(void* __ptr, s // chances are that you want to use `__libcpp_allocate` instead. // // Returns the allocated memory, or `nullptr` on failure. -inline _LIBCPP_INLINE_VISIBILITY -void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) { -#if defined(_LIBCPP_MSVCRT_LIKE) - return ::_aligned_malloc(__size, __alignment); -#else - void* __result = nullptr; - (void)::posix_memalign(&__result, __alignment, __size); - // If posix_memalign fails, __result is unmodified so we still return `nullptr`. - return __result; -#endif +inline _LIBCPP_INLINE_VISIBILITY void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) { +# if defined(_LIBCPP_MSVCRT_LIKE) + return ::_aligned_malloc(__size, __alignment); + // Use posix_memalign instead of ::aligned_alloc to fix the musl and some of the tests +# elif _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_C11_ALIGNED_ALLOC) && false + // aligned_alloc() requires that __size is a multiple of __alignment, + // but for C++ [new.delete.general], only states "if the value of an + // alignment argument passed to any of these functions is not a valid + // alignment value, the behavior is undefined". + // To handle calls such as ::operator new(1, std::align_val_t(128)), we + // round __size up to the next multiple of __alignment. + size_t __rounded_size = (__size + __alignment - 1) & ~(__alignment - 1); + // Rounding up could have wrapped around to zero, so we have to add another + // max() ternary to the actual call site to avoid succeeded in that case. + return ::aligned_alloc(__alignment, __size > __rounded_size ? __size : __rounded_size); +# else + void* __result = nullptr; + (void)::posix_memalign(&__result, __alignment, __size); + // If posix_memalign fails, __result is unmodified so we still return `nullptr`. + return __result; +# endif } inline _LIBCPP_INLINE_VISIBILITY @@ -391,4 +404,8 @@ inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUC _LIBCPP_END_NAMESPACE_STD +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_NEW diff --git a/contrib/libs/cxxsupp/libcxx/include/numeric b/contrib/libs/cxxsupp/libcxx/include/numeric index e427695f1c..f025913cb5 100644 --- a/contrib/libs/cxxsupp/libcxx/include/numeric +++ b/contrib/libs/cxxsupp/libcxx/include/numeric @@ -175,6 +175,7 @@ template<class T> # include <concepts> # include <functional> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_NUMERIC diff --git a/contrib/libs/cxxsupp/libcxx/include/optional b/contrib/libs/cxxsupp/libcxx/include/optional index 41c003cdb6..c8fca8885c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/optional +++ b/contrib/libs/cxxsupp/libcxx/include/optional @@ -166,7 +166,7 @@ template<class T> #include <__functional/invoke.h> #include <__functional/unary_function.h> #include <__memory/construct_at.h> -#include <__tuple/sfinae_helpers.h> +#include <__tuple_dir/sfinae_helpers.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> @@ -1185,8 +1185,8 @@ template<class _Tp> template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() == - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() == + std::declval<const _Up&>()), bool>, bool > operator==(const optional<_Tp>& __x, const optional<_Up>& __y) @@ -1201,8 +1201,8 @@ operator==(const optional<_Tp>& __x, const optional<_Up>& __y) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() != - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() != + std::declval<const _Up&>()), bool>, bool > operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) @@ -1217,8 +1217,8 @@ operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() < - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() < + std::declval<const _Up&>()), bool>, bool > operator<(const optional<_Tp>& __x, const optional<_Up>& __y) @@ -1233,8 +1233,8 @@ operator<(const optional<_Tp>& __x, const optional<_Up>& __y) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() > - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() > + std::declval<const _Up&>()), bool>, bool > operator>(const optional<_Tp>& __x, const optional<_Up>& __y) @@ -1249,8 +1249,8 @@ operator>(const optional<_Tp>& __x, const optional<_Up>& __y) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() <= - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() <= + std::declval<const _Up&>()), bool>, bool > operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) @@ -1265,8 +1265,8 @@ operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() >= - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() >= + std::declval<const _Up&>()), bool>, bool > operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) @@ -1379,8 +1379,8 @@ operator>=(nullopt_t, const optional<_Tp>& __x) noexcept template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() == - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() == + std::declval<const _Up&>()), bool>, bool > operator==(const optional<_Tp>& __x, const _Up& __v) @@ -1391,8 +1391,8 @@ operator==(const optional<_Tp>& __x, const _Up& __v) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() == - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() == + std::declval<const _Up&>()), bool>, bool > operator==(const _Tp& __v, const optional<_Up>& __x) @@ -1403,8 +1403,8 @@ operator==(const _Tp& __v, const optional<_Up>& __x) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() != - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() != + std::declval<const _Up&>()), bool>, bool > operator!=(const optional<_Tp>& __x, const _Up& __v) @@ -1415,8 +1415,8 @@ operator!=(const optional<_Tp>& __x, const _Up& __v) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() != - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() != + std::declval<const _Up&>()), bool>, bool > operator!=(const _Tp& __v, const optional<_Up>& __x) @@ -1427,8 +1427,8 @@ operator!=(const _Tp& __v, const optional<_Up>& __x) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() < - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() < + std::declval<const _Up&>()), bool>, bool > operator<(const optional<_Tp>& __x, const _Up& __v) @@ -1439,8 +1439,8 @@ operator<(const optional<_Tp>& __x, const _Up& __v) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() < - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() < + std::declval<const _Up&>()), bool>, bool > operator<(const _Tp& __v, const optional<_Up>& __x) @@ -1451,8 +1451,8 @@ operator<(const _Tp& __v, const optional<_Up>& __x) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() <= - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() <= + std::declval<const _Up&>()), bool>, bool > operator<=(const optional<_Tp>& __x, const _Up& __v) @@ -1463,8 +1463,8 @@ operator<=(const optional<_Tp>& __x, const _Up& __v) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() <= - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() <= + std::declval<const _Up&>()), bool>, bool > operator<=(const _Tp& __v, const optional<_Up>& __x) @@ -1475,8 +1475,8 @@ operator<=(const _Tp& __v, const optional<_Up>& __x) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() > - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() > + std::declval<const _Up&>()), bool>, bool > operator>(const optional<_Tp>& __x, const _Up& __v) @@ -1487,8 +1487,8 @@ operator>(const optional<_Tp>& __x, const _Up& __v) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() > - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() > + std::declval<const _Up&>()), bool>, bool > operator>(const _Tp& __v, const optional<_Up>& __x) @@ -1499,8 +1499,8 @@ operator>(const _Tp& __v, const optional<_Up>& __x) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() >= - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() >= + std::declval<const _Up&>()), bool>, bool > operator>=(const optional<_Tp>& __x, const _Up& __v) @@ -1511,8 +1511,8 @@ operator>=(const optional<_Tp>& __x, const _Up& __v) template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< - is_convertible_v<decltype(declval<const _Tp&>() >= - declval<const _Up&>()), bool>, + is_convertible_v<decltype(std::declval<const _Tp&>() >= + std::declval<const _Up&>()), bool>, bool > operator>=(const _Tp& __v, const optional<_Up>& __x) @@ -1574,10 +1574,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER > 14 -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 -# include <chrono> -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> # include <climits> diff --git a/contrib/libs/cxxsupp/libcxx/include/ostream b/contrib/libs/cxxsupp/libcxx/include/ostream index 6e0d3d5a23..743d40539c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/ostream +++ b/contrib/libs/cxxsupp/libcxx/include/ostream @@ -412,7 +412,7 @@ basic_ostream<_CharT, _Traits>::operator<<(bool __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -439,7 +439,7 @@ basic_ostream<_CharT, _Traits>::operator<<(short __n) { ios_base::fmtflags __flags = ios_base::flags() & ios_base::basefield; typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __flags == ios_base::oct || __flags == ios_base::hex ? static_cast<long>(static_cast<unsigned short>(__n)) : @@ -468,7 +468,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned short __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), static_cast<unsigned long>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -495,7 +495,7 @@ basic_ostream<_CharT, _Traits>::operator<<(int __n) { ios_base::fmtflags __flags = ios_base::flags() & ios_base::basefield; typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __flags == ios_base::oct || __flags == ios_base::hex ? static_cast<long>(static_cast<unsigned int>(__n)) : @@ -524,7 +524,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned int __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), static_cast<unsigned long>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -550,7 +550,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -576,7 +576,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -602,7 +602,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long long __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -628,7 +628,7 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -654,7 +654,7 @@ basic_ostream<_CharT, _Traits>::operator<<(float __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), static_cast<double>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -680,7 +680,7 @@ basic_ostream<_CharT, _Traits>::operator<<(double __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -706,7 +706,7 @@ basic_ostream<_CharT, _Traits>::operator<<(long double __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -732,7 +732,7 @@ basic_ostream<_CharT, _Traits>::operator<<(const void* __n) if (__s) { typedef num_put<char_type, ostreambuf_iterator<char_type, traits_type> > _Fp; - const _Fp& __f = use_facet<_Fp>(this->getloc()); + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } @@ -759,14 +759,14 @@ __put_character_sequence(basic_ostream<_CharT, _Traits>& __os, if (__s) { typedef ostreambuf_iterator<_CharT, _Traits> _Ip; - if (__pad_and_output(_Ip(__os), - __str, - (__os.flags() & ios_base::adjustfield) == ios_base::left ? - __str + __len : - __str, - __str + __len, - __os, - __os.fill()).failed()) + if (std::__pad_and_output(_Ip(__os), + __str, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? + __str + __len : + __str, + __str + __len, + __os, + __os.fill()).failed()) __os.setstate(ios_base::badbit | ios_base::failbit); } #ifndef _LIBCPP_NO_EXCEPTIONS @@ -800,14 +800,14 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, char __cn) { _CharT __c = __os.widen(__cn); typedef ostreambuf_iterator<_CharT, _Traits> _Ip; - if (__pad_and_output(_Ip(__os), - &__c, - (__os.flags() & ios_base::adjustfield) == ios_base::left ? - &__c + 1 : - &__c, - &__c + 1, - __os, - __os.fill()).failed()) + if (std::__pad_and_output(_Ip(__os), + &__c, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? + &__c + 1 : + &__c, + &__c + 1, + __os, + __os.fill()).failed()) __os.setstate(ios_base::badbit | ios_base::failbit); } #ifndef _LIBCPP_NO_EXCEPTIONS @@ -874,14 +874,14 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const char* __strn) } for (_CharT* __p = __wb; *__strn != '\0'; ++__strn, ++__p) *__p = __os.widen(*__strn); - if (__pad_and_output(_Ip(__os), - __wb, - (__os.flags() & ios_base::adjustfield) == ios_base::left ? - __wb + __len : - __wb, - __wb + __len, - __os, - __os.fill()).failed()) + if (std::__pad_and_output(_Ip(__os), + __wb, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? + __wb + __len : + __wb, + __wb + __len, + __os, + __os.fill()).failed()) __os.setstate(ios_base::badbit | ios_base::failbit); } #ifndef _LIBCPP_NO_EXCEPTIONS @@ -1063,7 +1063,7 @@ struct __is_ostreamable : false_type { }; template <class _Stream, class _Tp> struct __is_ostreamable<_Stream, _Tp, decltype( - declval<_Stream>() << declval<_Tp>(), void() + std::declval<_Stream>() << std::declval<_Tp>(), void() )> : true_type { }; template <class _Stream, class _Tp, class = typename enable_if< @@ -1113,7 +1113,7 @@ template<class _CharT, class _Traits, class _Yp, class _Dp> inline _LIBCPP_INLINE_VISIBILITY typename enable_if < - is_same<void, __void_t<decltype((declval<basic_ostream<_CharT, _Traits>&>() << declval<typename unique_ptr<_Yp, _Dp>::pointer>()))> >::value, + is_same<void, __void_t<decltype((std::declval<basic_ostream<_CharT, _Traits>&>() << std::declval<typename unique_ptr<_Yp, _Dp>::pointer>()))> >::value, basic_ostream<_CharT, _Traits>& >::type operator<<(basic_ostream<_CharT, _Traits>& __os, unique_ptr<_Yp, _Dp> const& __p) @@ -1126,8 +1126,8 @@ _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x) { return __os << __x.template to_string<_CharT, _Traits> - (use_facet<ctype<_CharT> >(__os.getloc()).widen('0'), - use_facet<ctype<_CharT> >(__os.getloc()).widen('1')); + (std::use_facet<ctype<_CharT> >(__os.getloc()).widen('0'), + std::use_facet<ctype<_CharT> >(__os.getloc()).widen('1')); } #if 0 @@ -1191,6 +1191,7 @@ _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_OSTREAM diff --git a/contrib/libs/cxxsupp/libcxx/include/queue b/contrib/libs/cxxsupp/libcxx/include/queue index c58da5ec6e..6c1b892efa 100644 --- a/contrib/libs/cxxsupp/libcxx/include/queue +++ b/contrib/libs/cxxsupp/libcxx/include/queue @@ -382,6 +382,8 @@ public: swap(c, __q.c); } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; } + template <class _T1, class _C1> friend _LIBCPP_INLINE_VISIBILITY @@ -633,6 +635,8 @@ public: void swap(priority_queue& __q) _NOEXCEPT_(__is_nothrow_swappable<container_type>::value && __is_nothrow_swappable<value_compare>::value); + + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; } }; #if _LIBCPP_STD_VER >= 17 diff --git a/contrib/libs/cxxsupp/libcxx/include/ranges b/contrib/libs/cxxsupp/libcxx/include/ranges index 643853e1d3..f999fa00c3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/ranges +++ b/contrib/libs/cxxsupp/libcxx/include/ranges @@ -115,6 +115,27 @@ namespace std::ranges { template<range R> using borrowed_subrange_t = see below; + // [range.elements], elements view + template<input_range V, size_t N> + requires see below + class elements_view; + + template<class T, size_t N> + inline constexpr bool enable_borrowed_range<elements_view<T, N>> = + enable_borrowed_range<T>; + + template<class R> + using keys_view = elements_view<R, 0>; + template<class R> + using values_view = elements_view<R, 1>; + + namespace views { + template<size_t N> + inline constexpr unspecified elements = unspecified; + inline constexpr auto keys = elements<0>; + inline constexpr auto values = elements<1>; + } + // [range.empty], empty view template<class T> requires is_object_v<T> @@ -244,8 +265,15 @@ namespace std::ranges { (forward_range<V> || tiny-range<Pattern>) class lazy_split_view; + // [range.split], split view + template<forward_range V, forward_range Pattern> + requires view<V> && view<Pattern> && + indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> + class split_view; + namespace views { inline constexpr unspecified lazy_split = unspecified; + inline constexpr unspecified split = unspecified; } // [range.istream], istream view @@ -271,6 +299,13 @@ namespace std::ranges { (enable_borrowed_range<Views> && ...); namespace views { inline constexpr unspecified zip = unspecified; } // C++2b + + // [range.as.rvalue] + template <view V> + requires input_range<V> + class as_rvalue_view; // since C++23 + + namespace views { inline constexpr unspecified as_rvalue ) unspecified; } // since C++23 } namespace std { @@ -309,6 +344,7 @@ namespace std { #include <__config> #include <__ranges/access.h> #include <__ranges/all.h> +#include <__ranges/as_rvalue_view.h> #include <__ranges/common_view.h> #include <__ranges/concepts.h> #include <__ranges/counted.h> @@ -316,6 +352,7 @@ namespace std { #include <__ranges/data.h> #include <__ranges/drop_view.h> #include <__ranges/drop_while_view.h> +#include <__ranges/elements_view.h> #include <__ranges/empty.h> #include <__ranges/empty_view.h> #include <__ranges/enable_borrowed_range.h> @@ -330,6 +367,7 @@ namespace std { #include <__ranges/reverse_view.h> #include <__ranges/single_view.h> #include <__ranges/size.h> +#include <__ranges/split_view.h> #include <__ranges/subrange.h> #include <__ranges/take_view.h> #include <__ranges/take_while_view.h> @@ -352,8 +390,8 @@ namespace std { #include <iterator> // [tuple.helper] -#include <__tuple/tuple_element.h> -#include <__tuple/tuple_size.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_size.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/contrib/libs/cxxsupp/libcxx/include/ratio b/contrib/libs/cxxsupp/libcxx/include/ratio index 5d7af88a2a..3969a392f3 100644 --- a/contrib/libs/cxxsupp/libcxx/include/ratio +++ b/contrib/libs/cxxsupp/libcxx/include/ratio @@ -79,9 +79,9 @@ typedef ratio<1000000000000000000000000, 1> yotta; // not supported #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__type_traits/integral_constant.h> #include <climits> #include <cstdint> -#include <type_traits> #include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -525,4 +525,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_RATIO diff --git a/contrib/libs/cxxsupp/libcxx/include/regex b/contrib/libs/cxxsupp/libcxx/include/regex index f35197339b..06c017fcce 100644 --- a/contrib/libs/cxxsupp/libcxx/include/regex +++ b/contrib/libs/cxxsupp/libcxx/include/regex @@ -1157,8 +1157,8 @@ template <class _CharT> void regex_traits<_CharT>::__init() { - __ct_ = &use_facet<ctype<char_type> >(__loc_); - __col_ = &use_facet<collate<char_type> >(__loc_); + __ct_ = &std::use_facet<ctype<char_type> >(__loc_); + __col_ = &std::use_facet<collate<char_type> >(__loc_); } template <class _CharT> @@ -1233,7 +1233,7 @@ regex_traits<_CharT>::__lookup_collatename(_ForwardIterator __f, string_type __r; if (!__s.empty()) { - __r = __get_collation_name(__s.c_str()); + __r = std::__get_collation_name(__s.c_str()); if (__r.empty() && __s.size() <= 2) { __r = __col_->transform(__s.data(), __s.data() + __s.size()); @@ -1296,7 +1296,7 @@ regex_traits<_CharT>::__lookup_classname(_ForwardIterator __f, { string_type __s(__f, __l); __ct_->tolower(&__s[0], &__s[0] + __s.size()); - return __get_classname(__s.c_str(), __icase); + return std::__get_classname(__s.c_str(), __icase); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -1446,12 +1446,12 @@ public: _LIBCPP_INLINE_VISIBILITY __node() {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~__node() {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec_split(bool, __state&) const {} }; @@ -2094,7 +2094,7 @@ __l_anchor_multiline<_CharT>::__exec(__state& __s) const } else if (__multiline_ && !__s.__at_first_ && - __is_eol(*_VSTD::prev(__s.__current_))) + std::__is_eol(*_VSTD::prev(__s.__current_))) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); @@ -2136,7 +2136,7 @@ __r_anchor_multiline<_CharT>::__exec(__state& __s) const __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); } - else if (__multiline_ && __is_eol(*__s.__current_)) + else if (__multiline_ && std::__is_eol(*__s.__current_)) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); @@ -2405,7 +2405,7 @@ public: for (size_t __i = 0; __i < __e.size(); ++__i) __e[__i] = __traits_.translate(__e[__i]); } - __ranges_.push_back(make_pair( + __ranges_.push_back(std::make_pair( __traits_.transform(__b.begin(), __b.end()), __traits_.transform(__e.begin(), __e.end()))); } @@ -2418,20 +2418,20 @@ public: __b[0] = __traits_.translate_nocase(__b[0]); __e[0] = __traits_.translate_nocase(__e[0]); } - __ranges_.push_back(make_pair(_VSTD::move(__b), _VSTD::move(__e))); + __ranges_.push_back(std::make_pair(_VSTD::move(__b), _VSTD::move(__e))); } } _LIBCPP_INLINE_VISIBILITY void __add_digraph(_CharT __c1, _CharT __c2) { if (__icase_) - __digraphs_.push_back(make_pair(__traits_.translate_nocase(__c1), - __traits_.translate_nocase(__c2))); + __digraphs_.push_back(std::make_pair(__traits_.translate_nocase(__c1), + __traits_.translate_nocase(__c2))); else if (__collate_) - __digraphs_.push_back(make_pair(__traits_.translate(__c1), - __traits_.translate(__c2))); + __digraphs_.push_back(std::make_pair(__traits_.translate(__c1), + __traits_.translate(__c2))); else - __digraphs_.push_back(make_pair(__c1, __c2)); + __digraphs_.push_back(std::make_pair(__c1, __c2)); } _LIBCPP_INLINE_VISIBILITY void __add_equivalence(const string_type& __s) @@ -5523,7 +5523,7 @@ public: regex_constants::match_flag_type __flags = regex_constants::format_default) const { basic_string<char_type, _ST, _SA> __r; - format(back_inserter(__r), __fmt.data(), __fmt.data() + __fmt.size(), + format(std::back_inserter(__r), __fmt.data(), __fmt.data() + __fmt.size(), __flags); return __r; } @@ -5533,7 +5533,7 @@ public: regex_constants::match_flag_type __flags = regex_constants::format_default) const { string_type __r; - format(back_inserter(__r), __fmt, + format(std::back_inserter(__r), __fmt, __fmt + char_traits<char_type>::length(__fmt), __flags); return __r; } @@ -6794,7 +6794,7 @@ regex_replace(const basic_string<_CharT, _ST, _SA>& __s, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT, _ST, _SA> __r; - _VSTD::regex_replace(back_inserter(__r), __s.begin(), __s.end(), __e, + _VSTD::regex_replace(std::back_inserter(__r), __s.begin(), __s.end(), __e, __fmt.c_str(), __flags); return __r; } @@ -6807,7 +6807,7 @@ regex_replace(const basic_string<_CharT, _ST, _SA>& __s, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT, _ST, _SA> __r; - _VSTD::regex_replace(back_inserter(__r), __s.begin(), __s.end(), __e, + _VSTD::regex_replace(std::back_inserter(__r), __s.begin(), __s.end(), __e, __fmt, __flags); return __r; } @@ -6821,7 +6821,7 @@ regex_replace(const _CharT* __s, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT> __r; - _VSTD::regex_replace(back_inserter(__r), __s, + _VSTD::regex_replace(std::back_inserter(__r), __s, __s + char_traits<_CharT>::length(__s), __e, __fmt.c_str(), __flags); return __r; @@ -6836,7 +6836,7 @@ regex_replace(const _CharT* __s, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT> __r; - _VSTD::regex_replace(back_inserter(__r), __s, + _VSTD::regex_replace(std::back_inserter(__r), __s, __s + char_traits<_CharT>::length(__s), __e, __fmt, __flags); return __r; diff --git a/contrib/libs/cxxsupp/libcxx/include/semaphore b/contrib/libs/cxxsupp/libcxx/include/semaphore index 3e4f51cae5..ddccb28dab 100644 --- a/contrib/libs/cxxsupp/libcxx/include/semaphore +++ b/contrib/libs/cxxsupp/libcxx/include/semaphore @@ -113,7 +113,7 @@ public: if (__rel_time == chrono::duration<Rep, Period>::zero()) return try_acquire(); auto const __test_fn = [this]() { return try_acquire(); }; - return __libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy(), __rel_time); + return std::__libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy(), __rel_time); } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY bool try_acquire() diff --git a/contrib/libs/cxxsupp/libcxx/include/source_location b/contrib/libs/cxxsupp/libcxx/include/source_location new file mode 100644 index 0000000000..e9e852a6e4 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/source_location @@ -0,0 +1,87 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_SOURCE_LOCATION +#define _LIBCPP_SOURCE_LOCATION + +/* source_location synopsis + +namespace std { + struct source_location { + static consteval source_location current() noexcept; + constexpr source_location() noexcept; + + constexpr uint_least32_t line() const noexcept; + constexpr uint_least32_t column() const noexcept; + constexpr const char* file_name() const noexcept; + constexpr const char* function_name() const noexcept; + }; +} +*/ + +#include <__config> +#include <cstdint> +#include <version> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_source_location) && \ + !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403) + +class source_location { + // The names source_location::__impl, _M_file_name, _M_function_name, _M_line, and _M_column + // are hard-coded in the compiler and must not be changed here. + struct __impl { + const char* _M_file_name; + const char* _M_function_name; + unsigned _M_line; + unsigned _M_column; + }; + const __impl* __ptr_ = nullptr; + // GCC returns the type 'const void*' from the builtin, while clang returns + // `const __impl*`. Per C++ [expr.const], casts from void* are not permitted + // in constant evaluation, so we don't want to use `void*` as the argument + // type unless the builtin returned that, anyhow, and the invalid cast is + // unavoidable. + using __bsl_ty = decltype(__builtin_source_location()); + +public: + // The defaulted __ptr argument is necessary so that the builtin is evaluated + // in the context of the caller. An explicit value should never be provided. + static consteval source_location current(__bsl_ty __ptr = __builtin_source_location()) noexcept { + source_location __sl; + __sl.__ptr_ = static_cast<const __impl*>(__ptr); + return __sl; + } + _LIBCPP_HIDE_FROM_ABI constexpr source_location() noexcept = default; + + _LIBCPP_HIDE_FROM_ABI constexpr uint_least32_t line() const noexcept { + return __ptr_ != nullptr ? __ptr_->_M_line : 0; + } + _LIBCPP_HIDE_FROM_ABI constexpr uint_least32_t column() const noexcept { + return __ptr_ != nullptr ? __ptr_->_M_column : 0; + } + _LIBCPP_HIDE_FROM_ABI constexpr const char* file_name() const noexcept { + return __ptr_ != nullptr ? __ptr_->_M_file_name : ""; + } + _LIBCPP_HIDE_FROM_ABI constexpr const char* function_name() const noexcept { + return __ptr_ != nullptr ? __ptr_->_M_function_name : ""; + } +}; + +#endif // _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && + // _LIBCPP_APPLE_CLANG_VER <= 1403) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_SOURCE_LOCATION diff --git a/contrib/libs/cxxsupp/libcxx/include/sstream b/contrib/libs/cxxsupp/libcxx/include/sstream index 91d1a07353..78cc28a502 100644 --- a/contrib/libs/cxxsupp/libcxx/include/sstream +++ b/contrib/libs/cxxsupp/libcxx/include/sstream @@ -260,7 +260,7 @@ protected: int_type overflow (int_type __c = traits_type::eof()) override; pos_type seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out) override; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI_VIRTUAL pos_type seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out) override { return seekoff(__sp, ios_base::beg, __wch); @@ -876,4 +876,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if _LIBCPP_STD_VER <= 20 && !defined(_LIPCPP_REMOVE_TRANSITIVE_INCLUDES) +# include <type_traits> +#endif + #endif // _LIBCPP_SSTREAM diff --git a/contrib/libs/cxxsupp/libcxx/include/stack b/contrib/libs/cxxsupp/libcxx/include/stack index 2abbcd025c..d653d1bc7e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/stack +++ b/contrib/libs/cxxsupp/libcxx/include/stack @@ -255,6 +255,8 @@ public: swap(c, __s.c); } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; } + template <class T1, class _C1> friend bool diff --git a/contrib/libs/cxxsupp/libcxx/include/stdlib.h b/contrib/libs/cxxsupp/libcxx/include/stdlib.h index 64581b67f2..4dd3a9c14a 100644 --- a/contrib/libs/cxxsupp/libcxx/include/stdlib.h +++ b/contrib/libs/cxxsupp/libcxx/include/stdlib.h @@ -110,24 +110,24 @@ extern "C++" { // MSVCRT already has the correct prototype in <stdlib.h> if __cplusplus is defined #if !defined(_LIBCPP_MSVCRT) && !defined(__sun__) -inline _LIBCPP_INLINE_VISIBILITY long abs(long __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY long abs(long __x) _NOEXCEPT { return __builtin_labs(__x); } -inline _LIBCPP_INLINE_VISIBILITY long long abs(long long __x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY long long abs(long long __x) _NOEXCEPT { return __builtin_llabs(__x); } #endif // !defined(_LIBCPP_MSVCRT) && !defined(__sun__) #if !defined(__sun__) -inline _LIBCPP_INLINE_VISIBILITY float abs(float __lcpp_x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY float abs(float __lcpp_x) _NOEXCEPT { return __builtin_fabsf(__lcpp_x); // Use builtins to prevent needing math.h } -inline _LIBCPP_INLINE_VISIBILITY double abs(double __lcpp_x) _NOEXCEPT { +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY double abs(double __lcpp_x) _NOEXCEPT { return __builtin_fabs(__lcpp_x); } -inline _LIBCPP_INLINE_VISIBILITY long double +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY long double abs(long double __lcpp_x) _NOEXCEPT { return __builtin_fabsl(__lcpp_x); } diff --git a/contrib/libs/cxxsupp/libcxx/include/string b/contrib/libs/cxxsupp/libcxx/include/string index bbb1c1a859..7ad144a79e 100644 --- a/contrib/libs/cxxsupp/libcxx/include/string +++ b/contrib/libs/cxxsupp/libcxx/include/string @@ -3518,7 +3518,7 @@ basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find(): received nullptr"); - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3528,7 +3528,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, size_type __pos) const _NOEXCEPT { - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } @@ -3544,7 +3544,7 @@ basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3555,7 +3555,7 @@ basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find(): received nullptr"); - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3565,7 +3565,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(value_type __c, size_type __pos) const _NOEXCEPT { - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -3579,7 +3579,7 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3589,7 +3589,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, size_type __pos) const _NOEXCEPT { - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } @@ -3605,7 +3605,7 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3616,7 +3616,7 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::rfind(): received nullptr"); - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3626,7 +3626,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c, size_type __pos) const _NOEXCEPT { - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -3640,7 +3640,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); - return __str_find_first_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3650,7 +3650,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { - return __str_find_first_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } @@ -3666,7 +3666,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; - return __str_find_first_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3677,7 +3677,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_first_of(): received nullptr"); - return __str_find_first_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3700,7 +3700,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); - return __str_find_last_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3710,7 +3710,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { - return __str_find_last_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } @@ -3726,7 +3726,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; - return __str_find_last_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3737,7 +3737,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_last_of(): received nullptr"); - return __str_find_last_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3760,7 +3760,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* _ size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3770,7 +3770,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } @@ -3786,7 +3786,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3797,7 +3797,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* _ size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_first_not_of(): received nullptr"); - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3807,7 +3807,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c, size_type __pos) const _NOEXCEPT { - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -3821,7 +3821,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __ size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3831,7 +3831,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } @@ -3847,7 +3847,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3858,7 +3858,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __ size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_last_not_of(): received nullptr"); - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3868,7 +3868,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, size_type __pos) const _NOEXCEPT { - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -4487,7 +4487,7 @@ struct __string_hash : public __unary_function<basic_string<_CharT, char_traits< { size_t operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT - { return __do_string_hash(__val.data(), __val.data() + __val.size()); } + { return std::__do_string_hash(__val.data(), __val.data() + __val.size()); } }; template <class _Allocator> diff --git a/contrib/libs/cxxsupp/libcxx/include/string_view b/contrib/libs/cxxsupp/libcxx/include/string_view index 7ebef2a104..4ba6b0e12d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/string_view +++ b/contrib/libs/cxxsupp/libcxx/include/string_view @@ -496,14 +496,14 @@ public: size_type find(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT { _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr"); - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find(_CharT __c, size_type __pos = 0) const _NOEXCEPT { - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -511,7 +511,7 @@ public: size_type find(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find(): received nullptr"); - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -519,7 +519,7 @@ public: size_type find(const _CharT* __s, size_type __pos = 0) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find(): received nullptr"); - return __str_find<value_type, size_type, traits_type, npos> + return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -528,14 +528,14 @@ public: size_type rfind(basic_string_view __s, size_type __pos = npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr"); - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type rfind(_CharT __c, size_type __pos = npos) const _NOEXCEPT { - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -543,7 +543,7 @@ public: size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr"); - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -551,7 +551,7 @@ public: size_type rfind(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::rfind(): received nullptr"); - return __str_rfind<value_type, size_type, traits_type, npos> + return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -560,7 +560,7 @@ public: size_type find_first_of(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT { _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_first_of(): received nullptr"); - return __str_find_first_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -572,7 +572,7 @@ public: size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr"); - return __str_find_first_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -580,7 +580,7 @@ public: size_type find_first_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_of(): received nullptr"); - return __str_find_first_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -589,7 +589,7 @@ public: size_type find_last_of(basic_string_view __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_last_of(): received nullptr"); - return __str_find_last_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -601,7 +601,7 @@ public: size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr"); - return __str_find_last_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -609,7 +609,7 @@ public: size_type find_last_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_of(): received nullptr"); - return __str_find_last_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -618,14 +618,14 @@ public: size_type find_first_not_of(basic_string_view __s, size_type __pos=0) const _NOEXCEPT { _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_first_not_of(): received nullptr"); - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(_CharT __c, size_type __pos=0) const _NOEXCEPT { - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -633,7 +633,7 @@ public: size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr"); - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -641,7 +641,7 @@ public: size_type find_first_not_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_not_of(): received nullptr"); - return __str_find_first_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -650,14 +650,14 @@ public: size_type find_last_not_of(basic_string_view __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_last_not_of(): received nullptr"); - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(_CharT __c, size_type __pos=npos) const _NOEXCEPT { - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } @@ -665,7 +665,7 @@ public: size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr"); - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -673,7 +673,7 @@ public: size_type find_last_not_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_not_of(): received nullptr"); - return __str_find_last_not_of<value_type, size_type, traits_type, npos> + return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -957,7 +957,7 @@ struct __string_view_hash : public __unary_function<basic_string_view<_CharT, ch { _LIBCPP_INLINE_VISIBILITY size_t operator()(const basic_string_view<_CharT, char_traits<_CharT> > __val) const _NOEXCEPT { - return __do_string_hash(__val.data(), __val.data() + __val.size()); + return std::__do_string_hash(__val.data(), __val.data() + __val.size()); } }; diff --git a/contrib/libs/cxxsupp/libcxx/include/thread b/contrib/libs/cxxsupp/libcxx/include/thread index 7c6d4f8828..7a1117f555 100644 --- a/contrib/libs/cxxsupp/libcxx/include/thread +++ b/contrib/libs/cxxsupp/libcxx/include/thread @@ -199,7 +199,7 @@ __thread_specific_ptr<_Tp>::set_pointer(pointer __p) { _LIBCPP_ASSERT(get() == nullptr, "Attempting to overwrite thread local data"); - __libcpp_tls_set(__key_, __p); + std::__libcpp_tls_set(__key_, __p); } template<> diff --git a/contrib/libs/cxxsupp/libcxx/include/tuple b/contrib/libs/cxxsupp/libcxx/include/tuple index a307461658..221b50375d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/tuple +++ b/contrib/libs/cxxsupp/libcxx/include/tuple @@ -205,11 +205,45 @@ template <class... Types> #include <__compare/common_comparison_category.h> #include <__compare/synth_three_way.h> #include <__config> +#include <__functional/invoke.h> #include <__functional/unwrap_ref.h> #include <__fwd/array.h> #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> +#include <__type_traits/apply_cv.h> +#include <__type_traits/common_reference.h> +#include <__type_traits/common_type.h> +#include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/copy_cvref.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_empty.h> +#include <__type_traits/is_final.h> +#include <__type_traits/is_implicitly_default_constructible.h> +#include <__type_traits/is_move_assignable.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_assignable.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/lazy.h> #include <__type_traits/maybe_const.h> +#include <__type_traits/nat.h> +#include <__type_traits/negation.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> @@ -217,7 +251,6 @@ template <class... Types> #include <__utility/piecewise_construct.h> #include <__utility/swap.h> #include <cstddef> -#include <type_traits> #include <version> // standard-mandated includes @@ -1397,7 +1430,7 @@ template <size_t _Nx> inline _LIBCPP_INLINE_VISIBILITY constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) { return __i == _Nx ? __not_found : - __find_idx_return(__i, __find_idx(__i + 1, __matches), __matches[__i]); + __find_detail::__find_idx_return(__i, __find_detail::__find_idx(__i + 1, __matches), __matches[__i]); } template <class _T1, class ..._Args> @@ -1644,7 +1677,7 @@ struct __tuple_cat_return_1<tuple<_Types...>, true, _Tuple0, _Tuple1, _Tuples... tuple<_Types...>, typename __make_tuple_types<__remove_cvref_t<_Tuple0> >::type >::type, - __tuple_like<__libcpp_remove_reference_t<_Tuple1> >::value, + __tuple_like_ext<__libcpp_remove_reference_t<_Tuple1> >::value, _Tuple1, _Tuples...> { }; @@ -1654,7 +1687,7 @@ template <class ..._Tuples> struct __tuple_cat_return; template <class _Tuple0, class ..._Tuples> struct __tuple_cat_return<_Tuple0, _Tuples...> : public __tuple_cat_return_1<tuple<>, - __tuple_like<__libcpp_remove_reference_t<_Tuple0> >::value, _Tuple0, + __tuple_like_ext<__libcpp_remove_reference_t<_Tuple0> >::value, _Tuple0, _Tuples...> { }; @@ -1822,6 +1855,7 @@ _LIBCPP_END_NAMESPACE_STD # include <exception> # include <iosfwd> # include <new> +# include <type_traits> # include <typeinfo> # include <utility> #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/type_traits b/contrib/libs/cxxsupp/libcxx/include/type_traits index e70039e35a..7646f58059 100644 --- a/contrib/libs/cxxsupp/libcxx/include/type_traits +++ b/contrib/libs/cxxsupp/libcxx/include/type_traits @@ -158,8 +158,8 @@ namespace std // Alignment properties and transformations: template <class T> struct alignment_of; template <size_t Len, size_t Align = most_stringent_alignment_requirement> - struct aligned_storage; - template <size_t Len, class... Types> struct aligned_union; + struct aligned_storage; // deprecated in C++23 + template <size_t Len, class... Types> struct aligned_union; // deprecated in C++23 template <class T> struct remove_cvref; // C++20 template <class T> struct decay; @@ -497,6 +497,7 @@ namespace std #include <__type_traits/is_scalar.h> #include <__type_traits/is_scoped_enum.h> #include <__type_traits/is_signed.h> +#include <__type_traits/is_specialization.h> #include <__type_traits/is_standard_layout.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivial.h> @@ -541,14 +542,4 @@ namespace std # pragma GCC system_header #endif -_LIBCPP_BEGIN_NAMESPACE_STD - -// CUDA headers use libc++ internals. -#ifdef __CUDACC__ -template <bool _Cond, class _Ret = void> -using __lazy_enable_if _LIBCPP_NODEBUG = __enable_if_t<_Cond, _Ret>; -#endif - -_LIBCPP_END_NAMESPACE_STD - #endif // _LIBCPP_TYPE_TRAITS diff --git a/contrib/libs/cxxsupp/libcxx/include/unordered_map b/contrib/libs/cxxsupp/libcxx/include/unordered_map index cd0aea1205..14f93bab36 100644 --- a/contrib/libs/cxxsupp/libcxx/include/unordered_map +++ b/contrib/libs/cxxsupp/libcxx/include/unordered_map @@ -1149,7 +1149,7 @@ public: #endif _LIBCPP_INLINE_VISIBILITY ~unordered_map() { - static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); + static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); } _LIBCPP_INLINE_VISIBILITY @@ -2041,7 +2041,7 @@ private: #endif _LIBCPP_INLINE_VISIBILITY ~unordered_multimap() { - static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); + static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); } _LIBCPP_INLINE_VISIBILITY diff --git a/contrib/libs/cxxsupp/libcxx/include/unordered_set b/contrib/libs/cxxsupp/libcxx/include/unordered_set index 9a25510139..b4203c08a9 100644 --- a/contrib/libs/cxxsupp/libcxx/include/unordered_set +++ b/contrib/libs/cxxsupp/libcxx/include/unordered_set @@ -613,7 +613,7 @@ public: #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY ~unordered_set() { - static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); + static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); } _LIBCPP_INLINE_VISIBILITY @@ -1267,7 +1267,7 @@ public: #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY ~unordered_multiset() { - static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); + static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); } _LIBCPP_INLINE_VISIBILITY diff --git a/contrib/libs/cxxsupp/libcxx/include/utility b/contrib/libs/cxxsupp/libcxx/include/utility index ac6c18b06a..a4d8cf853d 100644 --- a/contrib/libs/cxxsupp/libcxx/include/utility +++ b/contrib/libs/cxxsupp/libcxx/include/utility @@ -243,6 +243,7 @@ template <class T> #include <__utility/auto_cast.h> #include <__utility/cmp.h> #include <__utility/declval.h> +#include <__utility/exception_guard.h> #include <__utility/exchange.h> #include <__utility/forward.h> #include <__utility/forward_like.h> @@ -255,9 +256,7 @@ template <class T> #include <__utility/rel_ops.h> #include <__utility/swap.h> #include <__utility/to_underlying.h> -#include <__utility/transaction.h> #include <__utility/unreachable.h> -#include <type_traits> #include <version> // standard-mandated includes @@ -267,15 +266,17 @@ template <class T> #include <initializer_list> // [tuple.helper] -#include <__tuple/tuple_element.h> -#include <__tuple/tuple_size.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_size.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdlib> # include <iosfwd> +# include <type_traits> #endif #endif // _LIBCPP_UTILITY diff --git a/contrib/libs/cxxsupp/libcxx/include/valarray b/contrib/libs/cxxsupp/libcxx/include/valarray index 6c33d0531c..92521ed381 100644 --- a/contrib/libs/cxxsupp/libcxx/include/valarray +++ b/contrib/libs/cxxsupp/libcxx/include/valarray @@ -353,6 +353,7 @@ template <class T> unspecified2 end(const valarray<T>& v); #include <__functional/operations.h> #include <__memory/allocator.h> #include <__memory/uninitialized_algorithms.h> +#include <__type_traits/remove_reference.h> #include <__utility/move.h> #include <__utility/swap.h> #include <cmath> @@ -545,7 +546,7 @@ struct __abs_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return abs(__x);} + {return std::abs(__x);} }; template <class _Tp> @@ -554,7 +555,7 @@ struct __acos_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return acos(__x);} + {return std::acos(__x);} }; template <class _Tp> @@ -563,7 +564,7 @@ struct __asin_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return asin(__x);} + {return std::asin(__x);} }; template <class _Tp> @@ -572,7 +573,7 @@ struct __atan_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return atan(__x);} + {return std::atan(__x);} }; template <class _Tp> @@ -581,7 +582,7 @@ struct __atan2_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x, const _Tp& __y) const - {return atan2(__x, __y);} + {return std::atan2(__x, __y);} }; template <class _Tp> @@ -590,7 +591,7 @@ struct __cos_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return cos(__x);} + {return std::cos(__x);} }; template <class _Tp> @@ -599,7 +600,7 @@ struct __cosh_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return cosh(__x);} + {return std::cosh(__x);} }; template <class _Tp> @@ -608,7 +609,7 @@ struct __exp_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return exp(__x);} + {return std::exp(__x);} }; template <class _Tp> @@ -617,7 +618,7 @@ struct __log_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return log(__x);} + {return std::log(__x);} }; template <class _Tp> @@ -626,7 +627,7 @@ struct __log10_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return log10(__x);} + {return std::log10(__x);} }; template <class _Tp> @@ -635,7 +636,7 @@ struct __pow_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x, const _Tp& __y) const - {return pow(__x, __y);} + {return std::pow(__x, __y);} }; template <class _Tp> @@ -644,7 +645,7 @@ struct __sin_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return sin(__x);} + {return std::sin(__x);} }; template <class _Tp> @@ -653,7 +654,7 @@ struct __sinh_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return sinh(__x);} + {return std::sinh(__x);} }; template <class _Tp> @@ -662,7 +663,7 @@ struct __sqrt_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return sqrt(__x);} + {return std::sqrt(__x);} }; template <class _Tp> @@ -671,7 +672,7 @@ struct __tan_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return tan(__x);} + {return std::tan(__x);} }; template <class _Tp> @@ -680,7 +681,7 @@ struct __tanh_expr typedef _Tp __result_type; _LIBCPP_INLINE_VISIBILITY _Tp operator()(const _Tp& __x) const - {return tanh(__x);} + {return std::tanh(__x);} }; template <class _ValExpr> @@ -4932,6 +4933,7 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <algorithm> # include <concepts> +# include <cstring> # include <functional> #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/variant b/contrib/libs/cxxsupp/libcxx/include/variant index 26835f327d..13c89822ca 100644 --- a/contrib/libs/cxxsupp/libcxx/include/variant +++ b/contrib/libs/cxxsupp/libcxx/include/variant @@ -211,9 +211,26 @@ namespace std { #include <__compare/three_way_comparable.h> #include <__config> #include <__functional/hash.h> +#include <__functional/invoke.h> #include <__functional/operations.h> #include <__functional/unary_function.h> +#include <__type_traits/add_const.h> +#include <__type_traits/add_cv.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/add_volatile.h> #include <__type_traits/dependent_type.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_destructible.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_trivially_copy_assignable.h> +#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/is_trivially_move_assignable.h> +#include <__type_traits/is_trivially_move_constructible.h> +#include <__type_traits/is_void.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/type_identity.h> +#include <__type_traits/void_t.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> @@ -224,7 +241,6 @@ namespace std { #include <limits> #include <new> #include <tuple> -#include <type_traits> #include <version> // standard-mandated includes @@ -436,24 +452,24 @@ constexpr _Trait __common_trait(initializer_list<_Trait> __traits) { template <typename... _Types> struct __traits { static constexpr _Trait __copy_constructible_trait = - __common_trait({__trait<_Types, + __variant_detail::__common_trait({__trait<_Types, is_trivially_copy_constructible, is_copy_constructible>...}); static constexpr _Trait __move_constructible_trait = - __common_trait({__trait<_Types, + __variant_detail::__common_trait({__trait<_Types, is_trivially_move_constructible, is_move_constructible>...}); - static constexpr _Trait __copy_assignable_trait = __common_trait( + static constexpr _Trait __copy_assignable_trait = __variant_detail::__common_trait( {__copy_constructible_trait, __trait<_Types, is_trivially_copy_assignable, is_copy_assignable>...}); - static constexpr _Trait __move_assignable_trait = __common_trait( + static constexpr _Trait __move_assignable_trait = __variant_detail::__common_trait( {__move_constructible_trait, __trait<_Types, is_trivially_move_assignable, is_move_assignable>...}); - static constexpr _Trait __destructible_trait = __common_trait( + static constexpr _Trait __destructible_trait = __variant_detail::__common_trait( {__trait<_Types, is_trivially_destructible, is_destructible>...}); }; @@ -1213,7 +1229,7 @@ struct __narrowing_check { template <class _Dest> static auto __test_impl(_Dest (&&)[1]) -> __type_identity<_Dest>; template <class _Dest, class _Source> - using _Apply _LIBCPP_NODEBUG = decltype(__test_impl<_Dest>({declval<_Source>()})); + using _Apply _LIBCPP_NODEBUG = decltype(__test_impl<_Dest>({std::declval<_Source>()})); }; template <class _Dest, class _Source> @@ -1484,7 +1500,7 @@ constexpr bool __holds_alternative(const variant<_Types...>& __v) noexcept { template <class _Tp, class... _Types> _LIBCPP_HIDE_FROM_ABI constexpr bool holds_alternative(const variant<_Types...>& __v) noexcept { - return __holds_alternative<__find_exactly_one_t<_Tp, _Types...>::value>(__v); + return std::__holds_alternative<__find_exactly_one_t<_Tp, _Types...>::value>(__v); } template <size_t _Ip, class _Vp> @@ -1492,7 +1508,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr auto&& __generic_get(_Vp&& __v) { using __variant_detail::__access::__variant; - if (!__holds_alternative<_Ip>(__v)) { + if (!std::__holds_alternative<_Ip>(__v)) { __throw_bad_variant_access(); } return __variant::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)).__value; @@ -1505,7 +1521,7 @@ constexpr variant_alternative_t<_Ip, variant<_Types...>>& get( variant<_Types...>& __v) { static_assert(_Ip < sizeof...(_Types)); static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); - return __generic_get<_Ip>(__v); + return std::__generic_get<_Ip>(__v); } template <size_t _Ip, class... _Types> @@ -1515,7 +1531,7 @@ constexpr variant_alternative_t<_Ip, variant<_Types...>>&& get( variant<_Types...>&& __v) { static_assert(_Ip < sizeof...(_Types)); static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); - return __generic_get<_Ip>(_VSTD::move(__v)); + return std::__generic_get<_Ip>(_VSTD::move(__v)); } template <size_t _Ip, class... _Types> @@ -1525,7 +1541,7 @@ constexpr const variant_alternative_t<_Ip, variant<_Types...>>& get( const variant<_Types...>& __v) { static_assert(_Ip < sizeof...(_Types)); static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); - return __generic_get<_Ip>(__v); + return std::__generic_get<_Ip>(__v); } template <size_t _Ip, class... _Types> @@ -1535,7 +1551,7 @@ constexpr const variant_alternative_t<_Ip, variant<_Types...>>&& get( const variant<_Types...>&& __v) { static_assert(_Ip < sizeof...(_Types)); static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); - return __generic_get<_Ip>(_VSTD::move(__v)); + return std::__generic_get<_Ip>(_VSTD::move(__v)); } template <class _Tp, class... _Types> @@ -1576,7 +1592,7 @@ template <size_t _Ip, class _Vp> _LIBCPP_HIDE_FROM_ABI constexpr auto* __generic_get_if(_Vp* __v) noexcept { using __variant_detail::__access::__variant; - return __v && __holds_alternative<_Ip>(*__v) + return __v && std::__holds_alternative<_Ip>(*__v) ? _VSTD::addressof(__variant::__get_alt<_Ip>(*__v).__value) : nullptr; } @@ -1587,7 +1603,7 @@ constexpr add_pointer_t<variant_alternative_t<_Ip, variant<_Types...>>> get_if(variant<_Types...>* __v) noexcept { static_assert(_Ip < sizeof...(_Types)); static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); - return __generic_get_if<_Ip>(__v); + return std::__generic_get_if<_Ip>(__v); } template <size_t _Ip, class... _Types> @@ -1596,7 +1612,7 @@ constexpr add_pointer_t<const variant_alternative_t<_Ip, variant<_Types...>>> get_if(const variant<_Types...>* __v) noexcept { static_assert(_Ip < sizeof...(_Types)); static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); - return __generic_get_if<_Ip>(__v); + return std::__generic_get_if<_Ip>(__v); } template <class _Tp, class... _Types> @@ -1731,7 +1747,7 @@ constexpr void __throw_if_valueless(_Vs&&... __vs) { template < class _Visitor, class... _Vs, - typename = void_t<decltype(_VSTD::__as_variant(declval<_Vs>()))...> > + typename = void_t<decltype(_VSTD::__as_variant(std::declval<_Vs>()))...> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { @@ -1744,7 +1760,7 @@ constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { #if _LIBCPP_STD_VER > 17 template < class _Rp, class _Visitor, class... _Vs, - typename = void_t<decltype(_VSTD::__as_variant(declval<_Vs>()))...> > + typename = void_t<decltype(_VSTD::__as_variant(std::declval<_Vs>()))...> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Rp visit(_Visitor&& __visitor, _Vs&&... __vs) { @@ -1782,7 +1798,7 @@ struct _LIBCPP_TEMPLATE_VIS hash< return hash<__value_type>{}(__alt.__value); }, __v); - return __hash_combine(__res, hash<size_t>{}(__v.index())); + return std::__hash_combine(__res, hash<size_t>{}(__v.index())); } }; @@ -1799,13 +1815,13 @@ constexpr auto&& __unchecked_get(_Vp&& __v) noexcept { template <class _Tp, class... _Types> _LIBCPP_HIDE_FROM_ABI constexpr auto&& __unchecked_get(const variant<_Types...>& __v) noexcept { - return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); + return std::__unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); } template <class _Tp, class... _Types> _LIBCPP_HIDE_FROM_ABI constexpr auto&& __unchecked_get(variant<_Types...>& __v) noexcept { - return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); + return std::__unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); } #endif // _LIBCPP_STD_VER > 14 @@ -1815,6 +1831,7 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> # include <typeinfo> # include <utility> #endif diff --git a/contrib/libs/cxxsupp/libcxx/include/vector b/contrib/libs/cxxsupp/libcxx/include/vector index 53bb94c828..32ee8cd450 100644 --- a/contrib/libs/cxxsupp/libcxx/include/vector +++ b/contrib/libs/cxxsupp/libcxx/include/vector @@ -267,6 +267,13 @@ template <class T, class Allocator, class Predicate> typename vector<T, Allocator>::size_type erase_if(vector<T, Allocator>& c, Predicate pred); // C++20 + +template<class T> + inline constexpr bool is-vector-bool-reference = see below; // exposition only, since C++23 + +template<class T, class charT> requires is-vector-bool-reference<T> // Since C++23 + struct formatter<T, charT>; + } // std */ @@ -281,9 +288,11 @@ erase_if(vector<T, Allocator>& c, Predicate pred); // C++20 #include <__algorithm/unwrap_iter.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__bit_reference> +#include <__concepts/same_as.h> #include <__config> #include <__debug> #include <__format/enable_insertable.h> +#include <__format/formatter.h> #include <__functional/hash.h> #include <__functional/unary_function.h> #include <__iterator/advance.h> @@ -299,6 +308,7 @@ erase_if(vector<T, Allocator>& c, Predicate pred); // C++20 #include <__split_buffer> #include <__type_traits/is_allocator.h> #include <__type_traits/noexcept_move_assign_container.h> +#include <__utility/exception_guard.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> @@ -428,18 +438,27 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - ~vector() - { - __annotate_delete(); - std::__debug_db_erase_c(this); +private: + class __destroy_vector { + public: + _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} - if (this->__begin_ != nullptr) - { - __clear(); - __alloc_traits::deallocate(__alloc(), this->__begin_, capacity()); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() { + __vec_.__annotate_delete(); + std::__debug_db_erase_c(std::addressof(__vec_)); + + if (__vec_.__begin_ != nullptr) { + __vec_.__clear(); + __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity()); + } } - } + + private: + vector& __vec_; + }; + +public: + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector(*this)(); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x, const __type_identity_t<allocator_type>& __a); @@ -1080,12 +1099,14 @@ template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } + __guard.__complete(); } #if _LIBCPP_STD_VER > 11 @@ -1094,12 +1115,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __end_cap_(nullptr, __a) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } + __guard.__complete(); } #endif @@ -1107,12 +1130,14 @@ template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n, __x); } + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1122,9 +1147,11 @@ template <class _InputIterator, __enable_if_t<__is_exactly_cpp17_input_iterator< _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1135,9 +1162,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1147,6 +1176,7 @@ template <class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_For _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = static_cast<size_type>(std::distance(__first, __last)); if (__n > 0) @@ -1154,6 +1184,7 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __las __vallocate(__n); __construct_at_end(__first, __last, __n); } + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1164,6 +1195,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = static_cast<size_type>(std::distance(__first, __last)); if (__n > 0) @@ -1171,6 +1203,7 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __las __vallocate(__n); __construct_at_end(__first, __last, __n); } + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1178,6 +1211,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x) : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) @@ -1185,6 +1219,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x) __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1192,6 +1227,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t<allocator_type>& __a) : __end_cap_(nullptr, __a) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) @@ -1199,6 +1235,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t<alloc __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1238,7 +1275,9 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_ else { typedef move_iterator<iterator> _Ip; + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); assign(_Ip(__x.begin()), _Ip(__x.end())); + __guard.__complete(); } } @@ -1249,12 +1288,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } + __guard.__complete(); } template <class _Tp, class _Allocator> @@ -1263,12 +1304,14 @@ inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il, const allocator_type& __a) : __end_cap_(nullptr, __a) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } + __guard.__complete(); } #endif // _LIBCPP_CXX03_LANG @@ -1923,18 +1966,6 @@ vector<_Tp, _Allocator>::resize(size_type __sz) this->__destruct_at_end(this->__begin_ + __sz); } -template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -void -vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) -{ - size_type __cs = size(); - if (__cs < __sz) - this->__append(__sz - __cs, __x); - else if (__cs > __sz) - this->__destruct_at_end(this->__begin_ + __sz); -} - #if _YNDX_LIBCXX_ENABLE_VECTOR_POD_RESIZE_UNINITIALIZED template <class _Tp, class _Allocator> @@ -1955,6 +1986,18 @@ vector<_Tp, _Allocator>::resize_uninitialized(size_type __sz) template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void +vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) +{ + size_type __cs = size(); + if (__cs < __sz) + this->__append(__sz - __cs, __x); + else if (__cs > __sz) + this->__destruct_at_end(this->__begin_ + __sz); +} + +template <class _Tp, class _Allocator> +_LIBCPP_CONSTEXPR_SINCE_CXX20 +void vector<_Tp, _Allocator>::swap(vector& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT @@ -2132,7 +2175,25 @@ public: #else _NOEXCEPT; #endif - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~vector(); + +private: + class __destroy_vector { + public: + _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() { + if (__vec_.__begin_ != nullptr) + __storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap()); + std::__debug_db_invalidate_all(this); + } + + private: + vector& __vec_; + }; + +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~vector() { __destroy_vector(*this)(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n, const allocator_type& __a); @@ -2668,12 +2729,14 @@ vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __la __size_(0), __cap_alloc_(0, __default_init_tag()) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); size_type __n = static_cast<size_type>(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } + __guard.__complete(); } template <class _Allocator> @@ -2685,12 +2748,14 @@ vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __la __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); size_type __n = static_cast<size_type>(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } + __guard.__complete(); } #ifndef _LIBCPP_CXX03_LANG @@ -2729,15 +2794,6 @@ vector<bool, _Allocator>::vector(initializer_list<value_type> __il, const alloca template <class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 -vector<bool, _Allocator>::~vector() -{ - if (__begin_ != nullptr) - __storage_traits::deallocate(__alloc(), __begin_, __cap()); - std::__debug_db_invalidate_all(this); -} - -template <class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(const vector& __v) : __begin_(nullptr), __size_(0), @@ -3355,14 +3411,35 @@ erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) { } template <> -inline constexpr bool __format::__enable_insertable<std::vector<char>> = true; +inline constexpr bool __format::__enable_insertable<vector<char>> = true; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -inline constexpr bool __format::__enable_insertable<std::vector<wchar_t>> = true; +inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true; #endif #endif // _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER > 20 +template <class _Tp, class CharT> +// Since is-vector-bool-reference is only used once it's inlined here. + requires same_as<typename _Tp::__container, vector<bool, typename _Tp::__container::allocator_type>> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Tp, CharT> { +private: + formatter<bool, CharT> __underlying_; + +public: + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __underlying_.parse(__ctx); + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _Tp& __ref, _FormatContext& __ctx) const { + return __underlying_.format(__ref, __ctx); + } +}; +#endif // _LIBCPP_STD_VER > 20 + _LIBCPP_END_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 diff --git a/contrib/libs/cxxsupp/libcxx/include/version b/contrib/libs/cxxsupp/libcxx/include/version index f69d4ba252..a998eb56ca 100644 --- a/contrib/libs/cxxsupp/libcxx/include/version +++ b/contrib/libs/cxxsupp/libcxx/include/version @@ -55,7 +55,7 @@ __cpp_lib_chrono_udls 201304L <chrono> __cpp_lib_clamp 201603L <algorithm> __cpp_lib_complex_udls 201309L <complex> __cpp_lib_concepts 202002L <concepts> -__cpp_lib_constexpr_algorithms 201806L <algorithm> +__cpp_lib_constexpr_algorithms 201806L <algorithm> <utility> __cpp_lib_constexpr_bitset 202207L <bitset> __cpp_lib_constexpr_charconv 202207L <charconv> __cpp_lib_constexpr_cmath 202202L <cmath> <cstdlib> @@ -82,6 +82,7 @@ __cpp_lib_erase_if 202002L <deque> <forward __cpp_lib_exchange_function 201304L <utility> __cpp_lib_execution 201902L <execution> 201603L // C++17 +__cpp_lib_expected 202202L <expected> __cpp_lib_filesystem 201703L <filesystem> __cpp_lib_format 202106L <format> __cpp_lib_forward_like 202207L <utility> @@ -136,8 +137,9 @@ __cpp_lib_out_ptr 202106L <memory> __cpp_lib_parallel_algorithm 201603L <algorithm> <numeric> __cpp_lib_polymorphic_allocator 201902L <memory_resource> __cpp_lib_quoted_string_io 201304L <iomanip> -__cpp_lib_ranges 201811L <algorithm> <functional> <iterator> +__cpp_lib_ranges 202106L <algorithm> <functional> <iterator> <memory> <ranges> +__cpp_lib_ranges_as_rvalue 202207L <ranges> __cpp_lib_ranges_chunk 202202L <ranges> __cpp_lib_ranges_chunk_by 202202L <ranges> __cpp_lib_ranges_iota 202202L <numeric> @@ -324,7 +326,7 @@ __cpp_lib_void_t 201411L <type_traits> # endif # define __cpp_lib_concepts 202002L # define __cpp_lib_constexpr_algorithms 201806L -// # define __cpp_lib_constexpr_complex 201711L +# define __cpp_lib_constexpr_complex 201711L # define __cpp_lib_constexpr_dynamic_alloc 201907L # define __cpp_lib_constexpr_functional 201907L # define __cpp_lib_constexpr_iterator 201811L @@ -362,8 +364,8 @@ __cpp_lib_void_t 201411L <type_traits> # endif # define __cpp_lib_list_remove_return_type 201806L # define __cpp_lib_math_constants 201907L -// # define __cpp_lib_polymorphic_allocator 201902L -# define __cpp_lib_ranges 201811L +# define __cpp_lib_polymorphic_allocator 201902L +# define __cpp_lib_ranges 202106L # define __cpp_lib_remove_cvref 201711L # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # define __cpp_lib_semaphore 201907L @@ -372,7 +374,9 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_shared_ptr_arrays 201707L # define __cpp_lib_shift 201806L // # define __cpp_lib_smart_ptr_for_overwrite 202002L -// # define __cpp_lib_source_location 201907L +# if __has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403) +# define __cpp_lib_source_location 201907L +# endif # define __cpp_lib_span 202002L # define __cpp_lib_ssize 201902L # define __cpp_lib_starts_ends_with 201711L @@ -398,6 +402,7 @@ __cpp_lib_void_t 201411L <type_traits> # undef __cpp_lib_constexpr_memory # define __cpp_lib_constexpr_memory 202202L // # define __cpp_lib_constexpr_typeinfo 202106L +# define __cpp_lib_expected 202202L # define __cpp_lib_forward_like 202207L // # define __cpp_lib_invoke_r 202106L # define __cpp_lib_is_scoped_enum 202011L @@ -405,6 +410,7 @@ __cpp_lib_void_t 201411L <type_traits> # undef __cpp_lib_optional # define __cpp_lib_optional 202110L // # define __cpp_lib_out_ptr 202106L +# define __cpp_lib_ranges_as_rvalue 202207L // # define __cpp_lib_ranges_chunk 202202L // # define __cpp_lib_ranges_chunk_by 202202L // # define __cpp_lib_ranges_iota 202202L diff --git a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp index ec7bb7d9b2..7777e888c0 100644 --- a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp @@ -26,6 +26,11 @@ # define SYS_futex SYS_futex_time64 #endif +#elif defined(__FreeBSD__) + +#include <sys/types.h> +#include <sys/umtx.h> + #else // <- Add other operating systems here // Baseline needs no new headers @@ -72,6 +77,22 @@ static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const vo const_cast<__cxx_atomic_contention_t*>(__ptr), 0); } +#elif defined(__FreeBSD__) + +static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val) +{ + _umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr), + UMTX_OP_WAIT_UINT_PRIVATE, __val, NULL, NULL); +} + +static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, + bool __notify_one) +{ + _umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr), + UMTX_OP_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, NULL, NULL); +} + #else // <- Add other operating systems here // Baseline is just a timed backoff diff --git a/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp b/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp index d4a735b423..e00611dd1c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/memory_resource.cpp @@ -410,23 +410,39 @@ bool synchronized_pool_resource::do_is_equal(const memory_resource& other) const // 23.12.6, mem.res.monotonic.buffer +static void* align_down(size_t align, size_t size, void*& ptr, size_t& space) { + if (size > space) + return nullptr; + + char* p1 = static_cast<char*>(ptr); + char* new_ptr = reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(p1 - size) & ~(align - 1)); + + if (new_ptr < (p1 - space)) + return nullptr; + + ptr = new_ptr; + space -= p1 - new_ptr; + + return ptr; +} + void* monotonic_buffer_resource::__initial_descriptor::__try_allocate_from_chunk(size_t bytes, size_t align) { if (!__cur_) return nullptr; void* new_ptr = static_cast<void*>(__cur_); - size_t new_capacity = (__end_ - __cur_); - void* aligned_ptr = std::align(align, bytes, new_ptr, new_capacity); + size_t new_capacity = (__cur_ - __start_); + void* aligned_ptr = align_down(align, bytes, new_ptr, new_capacity); if (aligned_ptr != nullptr) - __cur_ = static_cast<char*>(new_ptr) + bytes; + __cur_ = static_cast<char*>(new_ptr); return aligned_ptr; } void* monotonic_buffer_resource::__chunk_footer::__try_allocate_from_chunk(size_t bytes, size_t align) { void* new_ptr = static_cast<void*>(__cur_); - size_t new_capacity = (reinterpret_cast<char*>(this) - __cur_); - void* aligned_ptr = std::align(align, bytes, new_ptr, new_capacity); + size_t new_capacity = (__cur_ - __start_); + void* aligned_ptr = align_down(align, bytes, new_ptr, new_capacity); if (aligned_ptr != nullptr) - __cur_ = static_cast<char*>(new_ptr) + bytes; + __cur_ = static_cast<char*>(new_ptr); return aligned_ptr; } @@ -464,10 +480,11 @@ void* monotonic_buffer_resource::do_allocate(size_t bytes, size_t align) { } char* start = (char*)__res_->allocate(aligned_capacity, align); - __chunk_footer* footer = (__chunk_footer*)(start + aligned_capacity - footer_size); + auto end = start + aligned_capacity - footer_size; + __chunk_footer* footer = (__chunk_footer*)(end); footer->__next_ = __chunks_; footer->__start_ = start; - footer->__cur_ = start; + footer->__cur_ = end; footer->__align_ = align; __chunks_ = footer; diff --git a/contrib/libs/cxxsupp/libcxx/src/thread.cpp b/contrib/libs/cxxsupp/libcxx/src/thread.cpp index ce2822dbac..ec4f65f982 100644 --- a/contrib/libs/cxxsupp/libcxx/src/thread.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/thread.cpp @@ -164,8 +164,8 @@ __thread_struct_imp::~__thread_struct_imp() for (_Notify::iterator i = notify_.begin(), e = notify_.end(); i != e; ++i) { - i->second->unlock(); i->first->notify_all(); + i->second->unlock(); } for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); i != e; ++i) diff --git a/contrib/libs/cxxsupp/libcxx/ya.make b/contrib/libs/cxxsupp/libcxx/ya.make index 56dc15f5c1..a1e7dad497 100644 --- a/contrib/libs/cxxsupp/libcxx/ya.make +++ b/contrib/libs/cxxsupp/libcxx/ya.make @@ -14,9 +14,9 @@ LICENSE( LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(2022-12-06) +VERSION(2023-06-02) -ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/96d63993dd3698bbf2d6a83c035cd05faed7317b.tar.gz) +ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/185b81e034ba60081023b6e59504dfffb560f3e3.tar.gz) ADDINCL( GLOBAL contrib/libs/cxxsupp/libcxx/include diff --git a/contrib/libs/opentelemetry-proto/CHANGELOG.md b/contrib/libs/opentelemetry-proto/CHANGELOG.md index bca0bb7ae3..ab793a015e 100644 --- a/contrib/libs/opentelemetry-proto/CHANGELOG.md +++ b/contrib/libs/opentelemetry-proto/CHANGELOG.md @@ -2,7 +2,35 @@ ## Unreleased -Full list of differences found in [this compare](https://github.com/open-telemetry/opentelemetry-proto/compare/v0.20.0...main). +Full list of differences found in [this compare](https://github.com/open-telemetry/opentelemetry-proto/compare/v1.1.0...main). + +## 1.1.0 - 2024-01-10 + +Full list of differences found in [this compare](https://github.com/open-telemetry/opentelemetry-proto/compare/v1.0.0...v1.1.0). + +### Added + +* Add `flags` field to `Span` and `Span/Link` for W3C-specified Trace Context flags . + [#503](https://github.com/open-telemetry/opentelemetry-proto/pull/503) + +### Changed + +* Update and fix OTLP JSON examples. [#516](https://github.com/open-telemetry/opentelemetry-proto/pull/516), + [#510](https://github.com/open-telemetry/opentelemetry-proto/pull/510), + [#499](https://github.com/open-telemetry/opentelemetry-proto/pull/499) +* Remove irrelevant comments from metric name field. [#512](https://github.com/open-telemetry/opentelemetry-proto/pull/512) +* Add comment to explain schema_url fields. [#504](https://github.com/open-telemetry/opentelemetry-proto/pull/504) + +## 1.0.0 - 2023-07-03 + +Full list of differences found in [this compare](https://github.com/open-telemetry/opentelemetry-proto/compare/v0.20.0...v1.0.0). + +### Maturity + +* Add note about the possibility to have unstable components after 1.0.0 + [#489](https://github.com/open-telemetry/opentelemetry-proto/pull/489) +* Add maturity JSON entry per package + [#490](https://github.com/open-telemetry/opentelemetry-proto/pull/490) ## 0.20.0 - 2023-06-06 @@ -47,7 +75,7 @@ Full list of differences found in [this compare](https://github.com/open-telemet * Add `csharp_namespace` option to protos. ([#399](https://github.com/open-telemetry/opentelemetry-proto/pull/399)) * Fix some out-of-date urls which link to [specification](https://github.com/open-telemetry/opentelemetry-specification). ([#402](https://github.com/open-telemetry/opentelemetry-proto/pull/402)) -* :stop_sign: [BREAKING] Delete deprecated InstrumentationLibrary, +* :stop_sign: [BREAKING] Delete deprecated InstrumentationLibrary, InstrumentationLibraryLogs, InstrumentationLibrarySpans and InstrumentationLibraryMetrics messages. Delete deprecated instrumentation_library_logs, instrumentation_library_spans and @@ -126,7 +154,7 @@ Full list of differences found in [this compare](https://github.com/open-telemet * Remove unused deprecated message StringKeyValue (#358) * Remove experimental metrics config service (#359) - + ## 0.12.0 - 2022-01-19 Full list of differences found in [this compare](https://github.com/open-telemetry/opentelemetry-proto/compare/v0.11.0...v0.12.0). @@ -277,9 +305,9 @@ Full list of differences found in [this compare.](https://github.com/open-teleme ### Changed * :stop_sign: [BREAKING] Metrics - protocol was refactored, and lots of breaking changes. -** Removed MetricDescriptor and embedded into Metric and the new data types. -** Add new data types Gauge/Sum/Histogram. -** Make use of the "AggregationTemporality" into the data types that allow that support. + * Removed MetricDescriptor and embedded into Metric and the new data types. + * Add new data types Gauge/Sum/Histogram. + * Make use of the "AggregationTemporality" into the data types that allow that support. * Rename enum values to follow the proto3 style guide. ### Added diff --git a/contrib/libs/opentelemetry-proto/opentelemetry/proto/logs/v1/logs.proto b/contrib/libs/opentelemetry-proto/opentelemetry/proto/logs/v1/logs.proto index 0b4b649729..f9b97dd745 100644 --- a/contrib/libs/opentelemetry-proto/opentelemetry/proto/logs/v1/logs.proto +++ b/contrib/libs/opentelemetry-proto/opentelemetry/proto/logs/v1/logs.proto @@ -55,6 +55,9 @@ message ResourceLogs { // A list of ScopeLogs that originate from a resource. repeated ScopeLogs scope_logs = 2; + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_logs" field which have their own schema_url field. string schema_url = 3; @@ -70,6 +73,9 @@ message ScopeLogs { // A list of log records. repeated LogRecord log_records = 2; + // The Schema URL, if known. This is the identifier of the Schema that the log data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all logs in the "logs" field. string schema_url = 3; } @@ -104,9 +110,11 @@ enum SeverityNumber { SEVERITY_NUMBER_FATAL4 = 24; } -// LogRecordFlags is defined as a protobuf 'uint32' type and is to be used as -// bit-fields. Each non-zero value defined in this enum is a bit-mask. -// To extract the bit-field, for example, use an expression like: +// LogRecordFlags represents constants used to interpret the +// LogRecord.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: // // (logRecord.flags & LOG_RECORD_FLAGS_TRACE_FLAGS_MASK) // diff --git a/contrib/libs/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto b/contrib/libs/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto index da986dda18..3394aee933 100644 --- a/contrib/libs/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto +++ b/contrib/libs/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto @@ -55,6 +55,9 @@ message ResourceMetrics { // A list of metrics that originate from a resource. repeated ScopeMetrics scope_metrics = 2; + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_metrics" field which have their own schema_url field. string schema_url = 3; @@ -70,6 +73,9 @@ message ScopeMetrics { // A list of metrics that originate from an instrumentation library. repeated Metric metrics = 2; + // The Schema URL, if known. This is the identifier of the Schema that the metric data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all metrics in the "metrics" field. string schema_url = 3; } @@ -162,7 +168,7 @@ message ScopeMetrics { message Metric { reserved 4, 6, 8; - // name of the metric, including its DNS name prefix. It must be unique. + // name of the metric. string name = 1; // description of the metric, which can be used in documentation. diff --git a/contrib/libs/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto b/contrib/libs/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto index b2869edc42..a1fdfa3ac9 100644 --- a/contrib/libs/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto +++ b/contrib/libs/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto @@ -55,6 +55,9 @@ message ResourceSpans { // A list of ScopeSpans that originate from a resource. repeated ScopeSpans scope_spans = 2; + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_spans" field which have their own schema_url field. string schema_url = 3; @@ -70,6 +73,9 @@ message ScopeSpans { // A list of Spans that originate from an instrumentation scope. repeated Span spans = 2; + // The Schema URL, if known. This is the identifier of the Schema that the span data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all spans and span events in the "spans" field. string schema_url = 3; } @@ -103,6 +109,22 @@ message Span { // field must be empty. The ID is an 8-byte array. bytes parent_span_id = 4; + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // To read the 8-bit W3C trace flag, use `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. + // + // When creating span messages, if the message is logically forwarded from another source + // with an equivalent flags fields (i.e., usually another OTLP span message), the field SHOULD + // be copied as-is. If creating from a source that does not have an equivalent flags field + // (such as a runtime representation of an OpenTelemetry span), the high 24 bits MUST + // be set to zero. + // + // [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + fixed32 flags = 16; + // A description of the span's operation. // // For example, the name can be a qualified method name or a file name @@ -236,6 +258,16 @@ message Span { // dropped_attributes_count is the number of dropped attributes. If the value is 0, // then no attributes were dropped. uint32 dropped_attributes_count = 5; + + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // When creating new spans, the most-significant 24-bits MUST be + // zero. To read the 8-bit W3C trace flag (use flags & + // SPAN_FLAGS_TRACE_FLAGS_MASK). [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + fixed32 flags = 6; } // links is a collection of Links, which are references from this span to a span @@ -274,3 +306,28 @@ message Status { // The status code. StatusCode code = 3; } + +// SpanFlags represents constants used to interpret the +// Span.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: +// +// (span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK) +// +// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. +// +// Note that Span flags were introduced in version 1.1 of the +// OpenTelemetry protocol. Older Span producers do not set this +// field, consequently consumers should not rely on the absence of a +// particular flag bit to indicate the presence of a particular feature. +enum SpanFlags { + // The zero value for the enum. Should not be used for comparisons. + // Instead use bitwise "and" with the appropriate mask as shown above. + SPAN_FLAGS_DO_NOT_USE = 0; + + // Bits 0-7 are used for trace flags. + SPAN_FLAGS_TRACE_FLAGS_MASK = 0x000000FF; + + // Bits 8-31 are reserved for future use. +} diff --git a/contrib/libs/opentelemetry-proto/ya.make b/contrib/libs/opentelemetry-proto/ya.make index 84c5759554..14dfa177e8 100644 --- a/contrib/libs/opentelemetry-proto/ya.make +++ b/contrib/libs/opentelemetry-proto/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(1.0.0) +VERSION(1.1.0) -ORIGINAL_SOURCE(https://github.com/open-telemetry/opentelemetry-proto/archive/v1.0.0.tar.gz) +ORIGINAL_SOURCE(https://github.com/open-telemetry/opentelemetry-proto/archive/v1.1.0.tar.gz) PY_NAMESPACE(.) diff --git a/contrib/python/Jinja2/py3/.dist-info/METADATA b/contrib/python/Jinja2/py3/.dist-info/METADATA index f54bb5ca1a..56e942902a 100644 --- a/contrib/python/Jinja2/py3/.dist-info/METADATA +++ b/contrib/python/Jinja2/py3/.dist-info/METADATA @@ -1,10 +1,8 @@ Metadata-Version: 2.1 Name: Jinja2 -Version: 3.1.2 +Version: 3.1.3 Summary: A very fast and expressive template engine. Home-page: https://palletsprojects.com/p/jinja/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com Maintainer: Pallets Maintainer-email: contact@palletsprojects.com License: BSD-3-Clause @@ -13,9 +11,7 @@ Project-URL: Documentation, https://jinja.palletsprojects.com/ Project-URL: Changes, https://jinja.palletsprojects.com/changes/ Project-URL: Source Code, https://github.com/pallets/jinja/ Project-URL: Issue Tracker, https://github.com/pallets/jinja/issues/ -Project-URL: Twitter, https://twitter.com/PalletsTeam Project-URL: Chat, https://discord.gg/pallets -Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers @@ -27,9 +23,9 @@ Classifier: Topic :: Text Processing :: Markup :: HTML Requires-Python: >=3.7 Description-Content-Type: text/x-rst License-File: LICENSE.rst -Requires-Dist: MarkupSafe (>=2.0) +Requires-Dist: MarkupSafe >=2.0 Provides-Extra: i18n -Requires-Dist: Babel (>=2.7) ; extra == 'i18n' +Requires-Dist: Babel >=2.7 ; extra == 'i18n' Jinja ===== @@ -106,8 +102,4 @@ Links - PyPI Releases: https://pypi.org/project/Jinja2/ - Source Code: https://github.com/pallets/jinja/ - Issue Tracker: https://github.com/pallets/jinja/issues/ -- Website: https://palletsprojects.com/p/jinja/ -- Twitter: https://twitter.com/PalletsTeam - Chat: https://discord.gg/pallets - - diff --git a/contrib/python/Jinja2/py3/README.rst b/contrib/python/Jinja2/py3/README.rst index a197aea647..94b22ecabe 100644 --- a/contrib/python/Jinja2/py3/README.rst +++ b/contrib/python/Jinja2/py3/README.rst @@ -73,6 +73,4 @@ Links - PyPI Releases: https://pypi.org/project/Jinja2/ - Source Code: https://github.com/pallets/jinja/ - Issue Tracker: https://github.com/pallets/jinja/issues/ -- Website: https://palletsprojects.com/p/jinja/ -- Twitter: https://twitter.com/PalletsTeam - Chat: https://discord.gg/pallets diff --git a/contrib/python/Jinja2/py3/jinja2/__init__.py b/contrib/python/Jinja2/py3/jinja2/__init__.py index a684093795..8076e72cd1 100644 --- a/contrib/python/Jinja2/py3/jinja2/__init__.py +++ b/contrib/python/Jinja2/py3/jinja2/__init__.py @@ -35,4 +35,4 @@ from .utils import pass_environment as pass_environment from .utils import pass_eval_context as pass_eval_context from .utils import select_autoescape as select_autoescape -__version__ = "3.1.2" +__version__ = "3.1.3" diff --git a/contrib/python/Jinja2/py3/jinja2/async_utils.py b/contrib/python/Jinja2/py3/jinja2/async_utils.py index 1a4f3892ce..715d70119b 100644 --- a/contrib/python/Jinja2/py3/jinja2/async_utils.py +++ b/contrib/python/Jinja2/py3/jinja2/async_utils.py @@ -74,7 +74,7 @@ async def auto_aiter( async for item in t.cast("t.AsyncIterable[V]", iterable): yield item else: - for item in t.cast("t.Iterable[V]", iterable): + for item in iterable: yield item diff --git a/contrib/python/Jinja2/py3/jinja2/compiler.py b/contrib/python/Jinja2/py3/jinja2/compiler.py index 3458095f54..ff95c807b0 100644 --- a/contrib/python/Jinja2/py3/jinja2/compiler.py +++ b/contrib/python/Jinja2/py3/jinja2/compiler.py @@ -993,7 +993,6 @@ class CodeGenerator(NodeVisitor): # far, we don't have to add a check if something extended # the template before this one. if self.extends_so_far > 0: - # if we have a known extends we just add a template runtime # error into the generated code. We could catch that at compile # time too, but i welcome it not to confuse users by throwing the @@ -1407,7 +1406,7 @@ class CodeGenerator(NodeVisitor): if pass_arg is None: - def finalize(value: t.Any) -> t.Any: + def finalize(value: t.Any) -> t.Any: # noqa: F811 return default(env_finalize(value)) else: @@ -1415,7 +1414,7 @@ class CodeGenerator(NodeVisitor): if pass_arg == "environment": - def finalize(value: t.Any) -> t.Any: + def finalize(value: t.Any) -> t.Any: # noqa: F811 return default(env_finalize(self.environment, value)) self._finalize = self._FinalizeInfo(finalize, src) diff --git a/contrib/python/Jinja2/py3/jinja2/environment.py b/contrib/python/Jinja2/py3/jinja2/environment.py index ea04e8b443..185d33246e 100644 --- a/contrib/python/Jinja2/py3/jinja2/environment.py +++ b/contrib/python/Jinja2/py3/jinja2/environment.py @@ -701,7 +701,7 @@ class Environment: .. versionadded:: 2.5 """ - return compile(source, filename, "exec") # type: ignore + return compile(source, filename, "exec") @typing.overload def compile( # type: ignore @@ -920,7 +920,7 @@ class Environment: ) def filter_func(x: str) -> bool: - return "." in x and x.rsplit(".", 1)[1] in extensions # type: ignore + return "." in x and x.rsplit(".", 1)[1] in extensions if filter_func is not None: names = [name for name in names if filter_func(name)] @@ -1253,7 +1253,7 @@ class Template: t.blocks = namespace["blocks"] # render function and module - t.root_render_func = namespace["root"] # type: ignore + t.root_render_func = namespace["root"] t._module = None # debug and loader helpers @@ -1349,7 +1349,7 @@ class Template: ctx = self.new_context(dict(*args, **kwargs)) try: - yield from self.root_render_func(ctx) # type: ignore + yield from self.root_render_func(ctx) except Exception: yield self.environment.handle_exception() @@ -1532,7 +1532,7 @@ class TemplateModule: " API you are using." ) - body_stream = list(template.root_render_func(context)) # type: ignore + body_stream = list(template.root_render_func(context)) self._body_stream = body_stream self.__dict__.update(context.get_exported()) @@ -1564,7 +1564,7 @@ class TemplateExpression: def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Optional[t.Any]: context = self._template.new_context(dict(*args, **kwargs)) - consume(self._template.root_render_func(context)) # type: ignore + consume(self._template.root_render_func(context)) rv = context.vars["result"] if self._undefined_to_none and isinstance(rv, Undefined): rv = None diff --git a/contrib/python/Jinja2/py3/jinja2/ext.py b/contrib/python/Jinja2/py3/jinja2/ext.py index d5550540cd..fade1fa3bc 100644 --- a/contrib/python/Jinja2/py3/jinja2/ext.py +++ b/contrib/python/Jinja2/py3/jinja2/ext.py @@ -291,14 +291,14 @@ class InternationalizationExtension(Extension): if hasattr(translations, "pgettext"): # Python < 3.8 - pgettext = translations.pgettext # type: ignore + pgettext = translations.pgettext else: def pgettext(c: str, s: str) -> str: return s if hasattr(translations, "npgettext"): - npgettext = translations.npgettext # type: ignore + npgettext = translations.npgettext else: def npgettext(c: str, s: str, p: str, n: int) -> str: @@ -495,16 +495,26 @@ class InternationalizationExtension(Extension): parser.stream.expect("variable_end") elif parser.stream.current.type == "block_begin": next(parser.stream) - if parser.stream.current.test("name:endtrans"): + block_name = ( + parser.stream.current.value + if parser.stream.current.type == "name" + else None + ) + if block_name == "endtrans": break - elif parser.stream.current.test("name:pluralize"): + elif block_name == "pluralize": if allow_pluralize: break parser.fail( "a translatable section can have only one pluralize section" ) + elif block_name == "trans": + parser.fail( + "trans blocks can't be nested; did you mean `endtrans`?" + ) parser.fail( - "control structures in translatable sections are not allowed" + f"control structures in translatable sections are not allowed; " + f"saw `{block_name}`" ) elif parser.stream.eos: parser.fail("unclosed translation block") diff --git a/contrib/python/Jinja2/py3/jinja2/filters.py b/contrib/python/Jinja2/py3/jinja2/filters.py index ed07c4c0e2..c7ecc9bb68 100644 --- a/contrib/python/Jinja2/py3/jinja2/filters.py +++ b/contrib/python/Jinja2/py3/jinja2/filters.py @@ -248,13 +248,17 @@ def do_items(value: t.Union[t.Mapping[K, V], Undefined]) -> t.Iterator[t.Tuple[K yield from value.items() +_space_re = re.compile(r"\s", flags=re.ASCII) + + @pass_eval_context def do_xmlattr( eval_ctx: "EvalContext", d: t.Mapping[str, t.Any], autospace: bool = True ) -> str: """Create an SGML/XML attribute string based on the items in a dict. - All values that are neither `none` nor `undefined` are automatically - escaped: + + If any key contains a space, this fails with a ``ValueError``. Values that + are neither ``none`` nor ``undefined`` are automatically escaped. .. sourcecode:: html+jinja @@ -273,12 +277,22 @@ def do_xmlattr( As you can see it automatically prepends a space in front of the item if the filter returned something unless the second parameter is false. + + .. versionchanged:: 3.1.3 + Keys with spaces are not allowed. """ - rv = " ".join( - f'{escape(key)}="{escape(value)}"' - for key, value in d.items() - if value is not None and not isinstance(value, Undefined) - ) + items = [] + + for key, value in d.items(): + if value is None or isinstance(value, Undefined): + continue + + if _space_re.search(key) is not None: + raise ValueError(f"Spaces are not allowed in attributes: '{key}'") + + items.append(f'{escape(key)}="{escape(value)}"') + + rv = " ".join(items) if autospace and rv: rv = " " + rv diff --git a/contrib/python/Jinja2/py3/jinja2/loaders.py b/contrib/python/Jinja2/py3/jinja2/loaders.py index 261802176a..dfa2ad7ec5 100644 --- a/contrib/python/Jinja2/py3/jinja2/loaders.py +++ b/contrib/python/Jinja2/py3/jinja2/loaders.py @@ -16,7 +16,6 @@ from types import ModuleType from .exceptions import TemplateNotFound from .utils import internalcode -from .utils import open_if_exists if t.TYPE_CHECKING: from .environment import Environment @@ -196,29 +195,30 @@ class FileSystemLoader(BaseLoader): self, environment: "Environment", template: str ) -> t.Tuple[str, str, t.Callable[[], bool]]: pieces = split_template_path(template) + for searchpath in self.searchpath: # Use posixpath even on Windows to avoid "drive:" or UNC # segments breaking out of the search directory. filename = posixpath.join(searchpath, *pieces) - f = open_if_exists(filename) - if f is None: - continue - try: - contents = f.read().decode(self.encoding) - finally: - f.close() - mtime = os.path.getmtime(filename) + if os.path.isfile(filename): + break + else: + raise TemplateNotFound(template) - def uptodate() -> bool: - try: - return os.path.getmtime(filename) == mtime - except OSError: - return False + with open(filename, encoding=self.encoding) as f: + contents = f.read() - # Use normpath to convert Windows altsep to sep. - return contents, os.path.normpath(filename), uptodate - raise TemplateNotFound(template) + mtime = os.path.getmtime(filename) + + def uptodate() -> bool: + try: + return os.path.getmtime(filename) == mtime + except OSError: + return False + + # Use normpath to convert Windows altsep to sep. + return contents, os.path.normpath(filename), uptodate def list_templates(self) -> t.List[str]: found = set() @@ -412,7 +412,7 @@ class PackageLoader(BaseLoader): ) offset = len(prefix) - for name in self._loader._files.keys(): # type: ignore + for name in self._loader._files.keys(): # Find names under the templates directory that aren't directories. if name.startswith(prefix) and name[-1] != os.path.sep: results.append(name[offset:].replace(os.path.sep, "/")) diff --git a/contrib/python/Jinja2/py3/jinja2/nativetypes.py b/contrib/python/Jinja2/py3/jinja2/nativetypes.py index ac08610348..71db8cc31f 100644 --- a/contrib/python/Jinja2/py3/jinja2/nativetypes.py +++ b/contrib/python/Jinja2/py3/jinja2/nativetypes.py @@ -106,7 +106,7 @@ class NativeTemplate(Template): try: return self.environment_class.concat( # type: ignore - self.root_render_func(ctx) # type: ignore + self.root_render_func(ctx) ) except Exception: return self.environment.handle_exception() diff --git a/contrib/python/Jinja2/py3/jinja2/parser.py b/contrib/python/Jinja2/py3/jinja2/parser.py index cefce2dfa1..3354bc9339 100644 --- a/contrib/python/Jinja2/py3/jinja2/parser.py +++ b/contrib/python/Jinja2/py3/jinja2/parser.py @@ -311,12 +311,14 @@ class Parser: # enforce that required blocks only contain whitespace or comments # by asserting that the body, if not empty, is just TemplateData nodes # with whitespace data - if node.required and not all( - isinstance(child, nodes.TemplateData) and child.data.isspace() - for body in node.body - for child in body.nodes # type: ignore - ): - self.fail("Required blocks can only contain comments or whitespace") + if node.required: + for body_node in node.body: + if not isinstance(body_node, nodes.Output) or any( + not isinstance(output_node, nodes.TemplateData) + or not output_node.data.isspace() + for output_node in body_node.nodes + ): + self.fail("Required blocks can only contain comments or whitespace") self.stream.skip_if("name:" + node.name) return node @@ -857,7 +859,7 @@ class Parser: else: args.append(None) - return nodes.Slice(lineno=lineno, *args) + return nodes.Slice(lineno=lineno, *args) # noqa: B026 def parse_call_args(self) -> t.Tuple: token = self.stream.expect("lparen") diff --git a/contrib/python/Jinja2/py3/jinja2/runtime.py b/contrib/python/Jinja2/py3/jinja2/runtime.py index 985842b284..58a540ba3f 100644 --- a/contrib/python/Jinja2/py3/jinja2/runtime.py +++ b/contrib/python/Jinja2/py3/jinja2/runtime.py @@ -272,9 +272,9 @@ class Context: # Allow callable classes to take a context if ( hasattr(__obj, "__call__") # noqa: B004 - and _PassArg.from_obj(__obj.__call__) is not None # type: ignore + and _PassArg.from_obj(__obj.__call__) is not None ): - __obj = __obj.__call__ # type: ignore + __obj = __obj.__call__ pass_arg = _PassArg.from_obj(__obj) @@ -927,9 +927,7 @@ def make_logging_undefined( logger.addHandler(logging.StreamHandler(sys.stderr)) def _log_message(undef: Undefined) -> None: - logger.warning( # type: ignore - "Template variable warning: %s", undef._undefined_message - ) + logger.warning("Template variable warning: %s", undef._undefined_message) class LoggingUndefined(base): # type: ignore __slots__ = () diff --git a/contrib/python/Jinja2/py3/jinja2/utils.py b/contrib/python/Jinja2/py3/jinja2/utils.py index 9b5f5a50eb..18914a58fd 100644 --- a/contrib/python/Jinja2/py3/jinja2/utils.py +++ b/contrib/python/Jinja2/py3/jinja2/utils.py @@ -182,7 +182,7 @@ def object_type_repr(obj: t.Any) -> str: def pformat(obj: t.Any) -> str: """Format an object using :func:`pprint.pformat`.""" - from pprint import pformat # type: ignore + from pprint import pformat return pformat(obj) @@ -259,7 +259,7 @@ def urlize( if trim_url_limit is not None: def trim_url(x: str) -> str: - if len(x) > trim_url_limit: # type: ignore + if len(x) > trim_url_limit: return f"{x[:trim_url_limit]}..." return x diff --git a/contrib/python/Jinja2/py3/tests/test_ext.py b/contrib/python/Jinja2/py3/tests/test_ext.py index 2e842e0ab5..0b48ca2586 100644 --- a/contrib/python/Jinja2/py3/tests/test_ext.py +++ b/contrib/python/Jinja2/py3/tests/test_ext.py @@ -7,6 +7,7 @@ from jinja2 import DictLoader from jinja2 import Environment from jinja2 import nodes from jinja2 import pass_context +from jinja2 import TemplateSyntaxError from jinja2.exceptions import TemplateAssertionError from jinja2.ext import Extension from jinja2.lexer import count_newlines @@ -468,6 +469,18 @@ class TestInternationalization: (3, "npgettext", ("babel", "%(users)s user", "%(users)s users", None), []), ] + def test_nested_trans_error(self): + s = "{% trans %}foo{% trans %}{% endtrans %}" + with pytest.raises(TemplateSyntaxError) as excinfo: + i18n_env.from_string(s) + assert "trans blocks can't be nested" in str(excinfo.value) + + def test_trans_block_error(self): + s = "{% trans %}foo{% wibble bar %}{% endwibble %}{% endtrans %}" + with pytest.raises(TemplateSyntaxError) as excinfo: + i18n_env.from_string(s) + assert "saw `wibble`" in str(excinfo.value) + class TestScope: def test_basic_scope_behavior(self): diff --git a/contrib/python/Jinja2/py3/tests/test_filters.py b/contrib/python/Jinja2/py3/tests/test_filters.py index 73f0f0be3c..f50ed13ab5 100644 --- a/contrib/python/Jinja2/py3/tests/test_filters.py +++ b/contrib/python/Jinja2/py3/tests/test_filters.py @@ -474,6 +474,12 @@ class TestFilter: assert 'bar="23"' in out assert 'blub:blub="<?>"' in out + def test_xmlattr_key_with_spaces(self, env): + with pytest.raises(ValueError, match="Spaces are not allowed"): + env.from_string( + "{{ {'src=1 onerror=alert(1)': 'my_class'}|xmlattr }}" + ).render() + def test_sort1(self, env): tmpl = env.from_string("{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}") assert tmpl.render() == "[1, 2, 3]|[3, 2, 1]" @@ -870,4 +876,6 @@ class TestFilter: with pytest.raises(TemplateRuntimeError, match="No filter named 'f'"): t1.render(x=42) + + with pytest.raises(TemplateRuntimeError, match="No filter named 'f'"): t2.render(x=42) diff --git a/contrib/python/Jinja2/py3/tests/test_inheritance.py b/contrib/python/Jinja2/py3/tests/test_inheritance.py index 0c20d4da7d..0a525e7ac9 100644 --- a/contrib/python/Jinja2/py3/tests/test_inheritance.py +++ b/contrib/python/Jinja2/py3/tests/test_inheritance.py @@ -287,26 +287,34 @@ class TestInheritance: env = Environment( loader=DictLoader( { - "default": "{% block x required %}data {# #}{% endblock %}", - "default1": "{% block x required %}{% block y %}" - "{% endblock %} {% endblock %}", - "default2": "{% block x required %}{% if true %}" - "{% endif %} {% endblock %}", - "level1": "{% if default %}{% extends default %}" - "{% else %}{% extends 'default' %}{% endif %}" - "{%- block x %}CHILD{% endblock %}", + "empty": "{% block x required %}{% endblock %}", + "blank": "{% block x required %} {# c #}{% endblock %}", + "text": "{% block x required %}data {# c #}{% endblock %}", + "block": "{% block x required %}{% block y %}" + "{% endblock %}{% endblock %}", + "if": "{% block x required %}{% if true %}" + "{% endif %}{% endblock %}", + "top": "{% extends t %}{% block x %}CHILD{% endblock %}", } ) ) - t = env.get_template("level1") + t = env.get_template("top") + assert t.render(t="empty") == "CHILD" + assert t.render(t="blank") == "CHILD" - with pytest.raises( + required_block_check = pytest.raises( TemplateSyntaxError, match="Required blocks can only contain comments or whitespace", - ): - assert t.render(default="default") - assert t.render(default="default2") - assert t.render(default="default3") + ) + + with required_block_check: + t.render(t="text") + + with required_block_check: + t.render(t="block") + + with required_block_check: + t.render(t="if") def test_required_with_scope(self, env): env = Environment( @@ -347,8 +355,11 @@ class TestInheritance: ) ) tmpl = env.get_template("child") + with pytest.raises(TemplateSyntaxError): tmpl.render(default="default1", seq=list(range(3))) + + with pytest.raises(TemplateSyntaxError): tmpl.render(default="default2", seq=list(range(3))) diff --git a/contrib/python/Jinja2/py3/tests/test_loader.py b/contrib/python/Jinja2/py3/tests/test_loader.py index a396e18fec..d3b4ddf1ba 100644 --- a/contrib/python/Jinja2/py3/tests/test_loader.py +++ b/contrib/python/Jinja2/py3/tests/test_loader.py @@ -186,6 +186,7 @@ class TestFileSystemLoader: class TestModuleLoader: archive = None + mod_env = None def compile_down(self, prefix_loader, zip="deflated"): log = [] @@ -199,13 +200,14 @@ class TestModuleLoader: self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive)) return "".join(log) - def teardown(self): - if hasattr(self, "mod_env"): + def teardown_method(self): + if self.archive is not None: if os.path.isfile(self.archive): os.remove(self.archive) else: shutil.rmtree(self.archive) self.archive = None + self.mod_env = None def test_log(self, prefix_loader): log = self.compile_down(prefix_loader) diff --git a/contrib/python/Jinja2/py3/ya.make b/contrib/python/Jinja2/py3/ya.make index 67ba20df0c..2c15cb57d4 100644 --- a/contrib/python/Jinja2/py3/ya.make +++ b/contrib/python/Jinja2/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(3.1.2) +VERSION(3.1.3) LICENSE(BSD-3-Clause) diff --git a/contrib/python/fonttools/.dist-info/METADATA b/contrib/python/fonttools/.dist-info/METADATA index f156c42697..f9e01c388f 100644 --- a/contrib/python/fonttools/.dist-info/METADATA +++ b/contrib/python/fonttools/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: fonttools -Version: 4.47.0 +Version: 4.47.2 Summary: Tools to manipulate font files Home-page: http://github.com/fonttools/fonttools Author: Just van Rossum @@ -375,6 +375,18 @@ Have fun! Changelog ~~~~~~~~~ +4.47.2 (released 2024-01-11) +---------------------------- + +Minor release to fix uploading wheels to PyPI. + +4.47.1 (released 2024-01-11) +---------------------------- + +- [merge] Improve help message and add standard command line options (#3408) +- [otlLib] Pass ``ttFont`` to ``name.addName`` in ``buildStatTable`` (#3406) +- [featureVars] Re-use ``FeatureVariationRecord``'s when possible (#3413) + 4.47.0 (released 2023-12-18) ---------------------------- diff --git a/contrib/python/fonttools/fontTools/__init__.py b/contrib/python/fonttools/fontTools/__init__.py index 6c00e567a4..7410d3c7fe 100644 --- a/contrib/python/fonttools/fontTools/__init__.py +++ b/contrib/python/fonttools/fontTools/__init__.py @@ -3,6 +3,6 @@ from fontTools.misc.loggingTools import configLogger log = logging.getLogger(__name__) -version = __version__ = "4.47.0" +version = __version__ = "4.47.2" __all__ = ["version", "log", "configLogger"] diff --git a/contrib/python/fonttools/fontTools/merge/__init__.py b/contrib/python/fonttools/fontTools/merge/__init__.py index 8d8a5213e8..7653e4a079 100644 --- a/contrib/python/fonttools/fontTools/merge/__init__.py +++ b/contrib/python/fonttools/fontTools/merge/__init__.py @@ -139,6 +139,7 @@ class Merger(object): *(vars(table).keys() for table in tables if table is not NotImplemented), ) for key in allKeys: + log.info(" %s", key) try: mergeLogic = logic[key] except KeyError: @@ -181,17 +182,50 @@ def main(args=None): args = sys.argv[1:] options = Options() - args = options.parse_opts(args, ignore_unknown=["output-file"]) - outfile = "merged.ttf" + args = options.parse_opts(args) fontfiles = [] + if options.input_file: + with open(options.input_file) as inputfile: + fontfiles = [ + line.strip() + for line in inputfile.readlines() + if not line.lstrip().startswith("#") + ] for g in args: - if g.startswith("--output-file="): - outfile = g[14:] - continue fontfiles.append(g) - if len(args) < 1: - print("usage: pyftmerge font...", file=sys.stderr) + if len(fontfiles) < 1: + print( + "usage: pyftmerge [font1 ... fontN] [--input-file=filelist.txt] [--output-file=merged.ttf] [--import-file=tables.ttx]", + file=sys.stderr, + ) + print( + " [--drop-tables=tags] [--verbose] [--timing]", + file=sys.stderr, + ) + print("", file=sys.stderr) + print(" font1 ... fontN Files to merge.", file=sys.stderr) + print( + " --input-file=<filename> Read files to merge from a text file, each path new line. # Comment lines allowed.", + file=sys.stderr, + ) + print( + " --output-file=<filename> Specify output file name (default: merged.ttf).", + file=sys.stderr, + ) + print( + " --import-file=<filename> TTX file to import after merging. This can be used to set metadata.", + file=sys.stderr, + ) + print( + " --drop-tables=<table tags> Comma separated list of table tags to skip, case sensitive.", + file=sys.stderr, + ) + print( + " --verbose Output progress information.", + file=sys.stderr, + ) + print(" --timing Output progress timing.", file=sys.stderr) return 1 configLogger(level=logging.INFO if options.verbose else logging.WARNING) @@ -202,8 +236,12 @@ def main(args=None): merger = Merger(options=options) font = merger.merge(fontfiles) + + if options.import_file: + font.importXML(options.import_file) + with timer("compile and save font"): - font.save(outfile) + font.save(options.output_file) if __name__ == "__main__": diff --git a/contrib/python/fonttools/fontTools/merge/options.py b/contrib/python/fonttools/fontTools/merge/options.py index f134009368..8bc8947138 100644 --- a/contrib/python/fonttools/fontTools/merge/options.py +++ b/contrib/python/fonttools/fontTools/merge/options.py @@ -11,6 +11,9 @@ class Options(object): self.verbose = False self.timing = False self.drop_tables = [] + self.input_file = None + self.output_file = "merged.ttf" + self.import_file = None self.set(**kwargs) diff --git a/contrib/python/fonttools/fontTools/otlLib/builder.py b/contrib/python/fonttools/fontTools/otlLib/builder.py index 3508a7e28d..4b457f4d9f 100644 --- a/contrib/python/fonttools/fontTools/otlLib/builder.py +++ b/contrib/python/fonttools/fontTools/otlLib/builder.py @@ -2781,14 +2781,13 @@ def buildStatTable( """ ttFont["STAT"] = ttLib.newTable("STAT") statTable = ttFont["STAT"].table = ot.STAT() - nameTable = ttFont["name"] statTable.ElidedFallbackNameID = _addName( - nameTable, elidedFallbackName, windows=windowsNames, mac=macNames + ttFont, elidedFallbackName, windows=windowsNames, mac=macNames ) # 'locations' contains data for AxisValue Format 4 axisRecords, axisValues = _buildAxisRecords( - axes, nameTable, windowsNames=windowsNames, macNames=macNames + axes, ttFont, windowsNames=windowsNames, macNames=macNames ) if not locations: statTable.Version = 0x00010001 @@ -2797,10 +2796,10 @@ def buildStatTable( # requires a higher table version statTable.Version = 0x00010002 multiAxisValues = _buildAxisValuesFormat4( - locations, axes, nameTable, windowsNames=windowsNames, macNames=macNames + locations, axes, ttFont, windowsNames=windowsNames, macNames=macNames ) axisValues = multiAxisValues + axisValues - nameTable.names.sort() + ttFont["name"].names.sort() # Store AxisRecords axisRecordArray = ot.AxisRecordArray() @@ -2820,14 +2819,14 @@ def buildStatTable( statTable.AxisValueCount = len(axisValues) -def _buildAxisRecords(axes, nameTable, windowsNames=True, macNames=True): +def _buildAxisRecords(axes, ttFont, windowsNames=True, macNames=True): axisRecords = [] axisValues = [] for axisRecordIndex, axisDict in enumerate(axes): axis = ot.AxisRecord() axis.AxisTag = axisDict["tag"] axis.AxisNameID = _addName( - nameTable, axisDict["name"], 256, windows=windowsNames, mac=macNames + ttFont, axisDict["name"], 256, windows=windowsNames, mac=macNames ) axis.AxisOrdering = axisDict.get("ordering", axisRecordIndex) axisRecords.append(axis) @@ -2837,7 +2836,7 @@ def _buildAxisRecords(axes, nameTable, windowsNames=True, macNames=True): axisValRec.AxisIndex = axisRecordIndex axisValRec.Flags = axisVal.get("flags", 0) axisValRec.ValueNameID = _addName( - nameTable, axisVal["name"], windows=windowsNames, mac=macNames + ttFont, axisVal["name"], windows=windowsNames, mac=macNames ) if "value" in axisVal: @@ -2863,9 +2862,7 @@ def _buildAxisRecords(axes, nameTable, windowsNames=True, macNames=True): return axisRecords, axisValues -def _buildAxisValuesFormat4( - locations, axes, nameTable, windowsNames=True, macNames=True -): +def _buildAxisValuesFormat4(locations, axes, ttFont, windowsNames=True, macNames=True): axisTagToIndex = {} for axisRecordIndex, axisDict in enumerate(axes): axisTagToIndex[axisDict["tag"]] = axisRecordIndex @@ -2875,7 +2872,7 @@ def _buildAxisValuesFormat4( axisValRec = ot.AxisValue() axisValRec.Format = 4 axisValRec.ValueNameID = _addName( - nameTable, axisLocationDict["name"], windows=windowsNames, mac=macNames + ttFont, axisLocationDict["name"], windows=windowsNames, mac=macNames ) axisValRec.Flags = axisLocationDict.get("flags", 0) axisValueRecords = [] @@ -2891,7 +2888,8 @@ def _buildAxisValuesFormat4( return axisValues -def _addName(nameTable, value, minNameID=0, windows=True, mac=True): +def _addName(ttFont, value, minNameID=0, windows=True, mac=True): + nameTable = ttFont["name"] if isinstance(value, int): # Already a nameID return value @@ -2916,5 +2914,5 @@ def _addName(nameTable, value, minNameID=0, windows=True, mac=True): else: raise TypeError("value must be int, str, dict or list") return nameTable.addMultilingualName( - names, windows=windows, mac=mac, minNameID=minNameID + names, ttFont=ttFont, windows=windows, mac=mac, minNameID=minNameID ) diff --git a/contrib/python/fonttools/fontTools/varLib/featureVars.py b/contrib/python/fonttools/fontTools/varLib/featureVars.py index a6beb5c7d2..828b843594 100644 --- a/contrib/python/fonttools/fontTools/varLib/featureVars.py +++ b/contrib/python/fonttools/fontTools/varLib/featureVars.py @@ -414,6 +414,10 @@ def addFeatureVariationsRaw(font, table, conditionalSubstitutions, featureTag="r axis.axisTag: axisIndex for axisIndex, axis in enumerate(font["fvar"].axes) } + hasFeatureVariations = ( + hasattr(table, "FeatureVariations") and table.FeatureVariations is not None + ) + featureVariationRecords = [] for conditionSet, lookupIndices in conditionalSubstitutions: conditionTable = [] @@ -440,11 +444,19 @@ def addFeatureVariationsRaw(font, table, conditionalSubstitutions, featureTag="r varFeatureIndex, combinedLookupIndices ) ) - featureVariationRecords.append( - buildFeatureVariationRecord(conditionTable, records) - ) + if hasFeatureVariations and ( + fvr := findFeatureVariationRecord(table.FeatureVariations, conditionTable) + ): + fvr.FeatureTableSubstitution.SubstitutionRecord.extend(records) + fvr.FeatureTableSubstitution.SubstitutionCount = len( + fvr.FeatureTableSubstitution.SubstitutionRecord + ) + else: + featureVariationRecords.append( + buildFeatureVariationRecord(conditionTable, records) + ) - if hasattr(table, "FeatureVariations") and table.FeatureVariations is not None: + if hasFeatureVariations: if table.FeatureVariations.Version != 0x00010000: raise VarLibError( "Unsupported FeatureVariations table version: " @@ -614,6 +626,21 @@ def buildConditionTable(axisIndex, filterRangeMinValue, filterRangeMaxValue): return ct +def findFeatureVariationRecord(featureVariations, conditionTable): + """Find a FeatureVariationRecord that has the same conditionTable.""" + if featureVariations.Version != 0x00010000: + raise VarLibError( + "Unsupported FeatureVariations table version: " + f"0x{featureVariations.Version:08x} (expected 0x00010000)." + ) + + for fvr in featureVariations.FeatureVariationRecord: + if conditionTable == fvr.ConditionSet.ConditionTable: + return fvr + + return None + + def sortFeatureList(table): """Sort the feature list by feature tag, and remap the feature indices elsewhere. This is needed after the feature list has been modified. diff --git a/contrib/python/fonttools/fontTools/varLib/interpolatable.py b/contrib/python/fonttools/fontTools/varLib/interpolatable.py index 0a9bbebc41..5fc12e04c9 100644 --- a/contrib/python/fonttools/fontTools/varLib/interpolatable.py +++ b/contrib/python/fonttools/fontTools/varLib/interpolatable.py @@ -376,9 +376,6 @@ def test_gen( size1 = m1Vec[0] * m1Vec[0] midSize = midVector[0] * midVector[0] - power = 1 - t = tolerance**power - for overweight, problem_type in enumerate( ( InterpolatableProblem.UNDERWEIGHT, @@ -386,8 +383,7 @@ def test_gen( ) ): if overweight: - expectedSize = sqrt(size0 * size1) - expectedSize = (size0 + size1) - expectedSize + expectedSize = max(size0, size1) continue else: expectedSize = sqrt(size0 * size1) @@ -406,13 +402,9 @@ def test_gen( ) or (overweight and 1e-5 + expectedSize / tolerance < midSize): try: if overweight: - this_tolerance = (expectedSize / midSize) ** ( - 1 / power - ) + this_tolerance = expectedSize / midSize else: - this_tolerance = (midSize / expectedSize) ** ( - 1 / power - ) + this_tolerance = midSize / expectedSize except ZeroDivisionError: this_tolerance = 0 log.debug("tolerance %g", this_tolerance) diff --git a/contrib/python/fonttools/ya.make b/contrib/python/fonttools/ya.make index 6e76c94da1..4d380b556c 100644 --- a/contrib/python/fonttools/ya.make +++ b/contrib/python/fonttools/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(4.47.0) +VERSION(4.47.2) LICENSE(MIT) diff --git a/contrib/python/google-auth/py3/.dist-info/METADATA b/contrib/python/google-auth/py3/.dist-info/METADATA index 21345a0555..2820e8856d 100644 --- a/contrib/python/google-auth/py3/.dist-info/METADATA +++ b/contrib/python/google-auth/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-auth -Version: 2.26.1 +Version: 2.26.2 Summary: Google Authentication Library Home-page: https://github.com/googleapis/google-auth-library-python Author: Google Cloud Platform diff --git a/contrib/python/google-auth/py3/google/auth/external_account_authorized_user.py b/contrib/python/google-auth/py3/google/auth/external_account_authorized_user.py index 55230103f4..526588f7e8 100644 --- a/contrib/python/google-auth/py3/google/auth/external_account_authorized_user.py +++ b/contrib/python/google-auth/py3/google/auth/external_account_authorized_user.py @@ -342,6 +342,7 @@ class Credentials( revoke_url=info.get("revoke_url"), quota_project_id=info.get("quota_project_id"), scopes=info.get("scopes"), + universe_domain=info.get("universe_domain", _DEFAULT_UNIVERSE_DOMAIN), **kwargs ) diff --git a/contrib/python/google-auth/py3/google/auth/version.py b/contrib/python/google-auth/py3/google/auth/version.py index 1c94c2f5f6..6d53c4c411 100644 --- a/contrib/python/google-auth/py3/google/auth/version.py +++ b/contrib/python/google-auth/py3/google/auth/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2.26.1" +__version__ = "2.26.2" diff --git a/contrib/python/google-auth/py3/tests/data/external_account_authorized_user_non_gdu.json b/contrib/python/google-auth/py3/tests/data/external_account_authorized_user_non_gdu.json new file mode 100644 index 0000000000..b82854c743 --- /dev/null +++ b/contrib/python/google-auth/py3/tests/data/external_account_authorized_user_non_gdu.json @@ -0,0 +1,10 @@ +{ + "type": "external_account_authorized_user", + "audience": "//iam.fake_universe_domain/locations/global/workforcePools/$WORKFORCE_POOL_ID/providers/$PROVIDER_ID", + "refresh_token": "refreshToken", + "token_url": "https://sts.fake_universe_domain/v1/oauth/token", + "token_info_url": "https://sts.fake_universe_domain/v1/instrospect", + "client_id": "clientId", + "client_secret": "clientSecret", + "universe_domain": "fake_universe_domain" +} diff --git a/contrib/python/google-auth/py3/tests/test__default.py b/contrib/python/google-auth/py3/tests/test__default.py index d619614790..aaf892f6d0 100644 --- a/contrib/python/google-auth/py3/tests/test__default.py +++ b/contrib/python/google-auth/py3/tests/test__default.py @@ -158,6 +158,10 @@ EXTERNAL_ACCOUNT_AUTHORIZED_USER_FILE = os.path.join( DATA_DIR, "external_account_authorized_user.json" ) +EXTERNAL_ACCOUNT_AUTHORIZED_USER_NON_GDU_FILE = os.path.join( + DATA_DIR, "external_account_authorized_user_non_gdu.json" +) + MOCK_CREDENTIALS = mock.Mock(spec=credentials.CredentialsWithQuotaProject) MOCK_CREDENTIALS.with_quota_project.return_value = MOCK_CREDENTIALS @@ -577,6 +581,15 @@ def test_load_credentials_from_file_external_account_authorized_user(): assert project_id is None +def test_load_credentials_from_file_external_account_authorized_user_non_gdu(): + credentials, _ = _default.load_credentials_from_file( + EXTERNAL_ACCOUNT_AUTHORIZED_USER_NON_GDU_FILE, request=mock.sentinel.request + ) + + assert isinstance(credentials, external_account_authorized_user.Credentials) + assert credentials.universe_domain == "fake_universe_domain" + + def test_load_credentials_from_file_external_account_authorized_user_bad_format(tmpdir): filename = tmpdir.join("external_account_authorized_user_bad.json") filename.write(json.dumps({"type": "external_account_authorized_user"})) diff --git a/contrib/python/google-auth/py3/ya.make b/contrib/python/google-auth/py3/ya.make index 75848da971..976b926bff 100644 --- a/contrib/python/google-auth/py3/ya.make +++ b/contrib/python/google-auth/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(2.26.1) +VERSION(2.26.2) LICENSE(Apache-2.0) diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA index 15385afbc9..b4f00cf430 100644 --- a/contrib/python/hypothesis/py3/.dist-info/METADATA +++ b/contrib/python/hypothesis/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: hypothesis -Version: 6.92.6 +Version: 6.92.8 Summary: A library for property-based testing Home-page: https://hypothesis.works Author: David R. MacIver and Zac Hatfield-Dodds diff --git a/contrib/python/hypothesis/py3/hypothesis/control.py b/contrib/python/hypothesis/py3/hypothesis/control.py index c49dba2954..3a973f666f 100644 --- a/contrib/python/hypothesis/py3/hypothesis/control.py +++ b/contrib/python/hypothesis/py3/hypothesis/control.py @@ -8,6 +8,7 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. +import inspect import math from collections import defaultdict from typing import NoReturn, Union @@ -25,6 +26,10 @@ from hypothesis.utils.dynamicvariables import DynamicVariable from hypothesis.vendor.pretty import IDKey +def _calling_function_name(frame): + return frame.f_back.f_code.co_name + + def reject() -> NoReturn: if _current_build_context.value is None: note_deprecation( @@ -32,7 +37,8 @@ def reject() -> NoReturn: since="2023-09-25", has_codemod=False, ) - raise UnsatisfiedAssumption + f = _calling_function_name(inspect.currentframe()) + raise UnsatisfiedAssumption(f"reject() in {f}") def assume(condition: object) -> bool: @@ -49,7 +55,8 @@ def assume(condition: object) -> bool: has_codemod=False, ) if not condition: - raise UnsatisfiedAssumption + f = _calling_function_name(inspect.currentframe()) + raise UnsatisfiedAssumption(f"failed to satisfy assume() in {f}") return True diff --git a/contrib/python/hypothesis/py3/hypothesis/core.py b/contrib/python/hypothesis/py3/hypothesis/core.py index 7c149d1222..86b20ea6f9 100644 --- a/contrib/python/hypothesis/py3/hypothesis/core.py +++ b/contrib/python/hypothesis/py3/hypothesis/core.py @@ -1005,10 +1005,10 @@ class StateForActualGivenExecution: f"{self.test.__name__} returned {result!r} instead.", HealthCheck.return_value, ) - except UnsatisfiedAssumption: + except UnsatisfiedAssumption as e: # An "assume" check failed, so instead we inform the engine that # this test run was invalid. - data.mark_invalid() + data.mark_invalid(e.reason) except StopTest: # The engine knows how to handle this control exception, so it's # OK to re-raise it. diff --git a/contrib/python/hypothesis/py3/hypothesis/errors.py b/contrib/python/hypothesis/py3/hypothesis/errors.py index 9ee81cfc36..8387a87586 100644 --- a/contrib/python/hypothesis/py3/hypothesis/errors.py +++ b/contrib/python/hypothesis/py3/hypothesis/errors.py @@ -23,6 +23,9 @@ class UnsatisfiedAssumption(HypothesisException): If you're seeing this error something has gone wrong. """ + def __init__(self, reason=None): + self.reason = reason + class NoSuchExample(HypothesisException): """The condition we have been asked to satisfy appears to be always false. diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py b/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py index 8af37e453b..4ba92b1da8 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py @@ -73,6 +73,14 @@ def convert(node: ast.AST, argname: str) -> object: if node.id != argname: raise ValueError("Non-local variable") return ARG + if isinstance(node, ast.Call): + if ( + isinstance(node.func, ast.Name) + and node.func.id == "len" + and len(node.args) == 1 + ): + # error unless comparison is to the len *of the lambda arg* + return convert(node.args[0], argname) return ast.literal_eval(node) @@ -86,26 +94,28 @@ def comp_to_kwargs(x: ast.AST, op: ast.AST, y: ast.AST, *, argname: str) -> dict # (and we can't even do `arg == arg`, because what if it's NaN?) raise ValueError("Can't analyse this comparison") + of_len = {"len": True} if isinstance(x, ast.Call) or isinstance(y, ast.Call) else {} + if isinstance(op, ast.Lt): if a is ARG: - return {"max_value": b, "exclude_max": True} - return {"min_value": a, "exclude_min": True} + return {"max_value": b, "exclude_max": True, **of_len} + return {"min_value": a, "exclude_min": True, **of_len} elif isinstance(op, ast.LtE): if a is ARG: - return {"max_value": b} - return {"min_value": a} + return {"max_value": b, **of_len} + return {"min_value": a, **of_len} elif isinstance(op, ast.Eq): if a is ARG: - return {"min_value": b, "max_value": b} - return {"min_value": a, "max_value": a} + return {"min_value": b, "max_value": b, **of_len} + return {"min_value": a, "max_value": a, **of_len} elif isinstance(op, ast.GtE): if a is ARG: - return {"min_value": b} - return {"max_value": a} + return {"min_value": b, **of_len} + return {"max_value": a, **of_len} elif isinstance(op, ast.Gt): if a is ARG: - return {"min_value": b, "exclude_min": True} - return {"max_value": a, "exclude_max": True} + return {"min_value": b, "exclude_min": True, **of_len} + return {"max_value": a, "exclude_max": True, **of_len} raise ValueError("Unhandled comparison operator") # e.g. ast.Ne @@ -120,6 +130,9 @@ def merge_preds(*con_predicates: ConstructivePredicate) -> ConstructivePredicate } predicate = None for kw, p in con_predicates: + assert ( + not p or not predicate or p is predicate + ), "Can't merge two partially-constructive preds" predicate = p or predicate if "min_value" in kw: if kw["min_value"] > base["min_value"]: @@ -134,6 +147,11 @@ def merge_preds(*con_predicates: ConstructivePredicate) -> ConstructivePredicate elif kw["max_value"] == base["max_value"]: base["exclude_max"] |= kw.get("exclude_max", False) + has_len = {"len" in kw for kw, _ in con_predicates} + assert len(has_len) == 1, "can't mix numeric with length constraints" + if has_len == {True}: + base["len"] = True + if not base["exclude_min"]: del base["exclude_min"] if base["min_value"] == -math.inf: @@ -154,6 +172,8 @@ def numeric_bounds_from_ast( {"min_value": 0}, None >>> lambda x: x < 10 {"max_value": 10, "exclude_max": True}, None + >>> lambda x: len(x) >= 5 + {"min_value": 5, "len": True}, None >>> lambda x: x >= y {}, lambda x: x >= y @@ -169,7 +189,10 @@ def numeric_bounds_from_ast( for comp in comparisons: try: kwargs = comp_to_kwargs(*comp, argname=argname) - bounds.append(ConstructivePredicate(kwargs, None)) + # Because `len` could be redefined in the enclosing scope, we *always* + # have to apply the condition as a filter, in addition to rewriting. + pred = fallback.predicate if "len" in kwargs else None + bounds.append(ConstructivePredicate(kwargs, pred)) except ValueError: bounds.append(fallback) return merge_preds(*bounds) @@ -209,6 +232,9 @@ def get_numeric_predicate_bounds(predicate: Predicate) -> ConstructivePredicate: operator.eq: {"min_value": arg, "max_value": arg}, # lambda x: arg == x operator.ge: {"max_value": arg}, # lambda x: arg >= x operator.gt: {"max_value": arg, "exclude_max": True}, # lambda x: arg > x + # Special-case our default predicates for length bounds + min_len: {"min_value": arg, "len": True}, + max_len: {"max_value": arg, "len": True}, } if predicate.func in options: return ConstructivePredicate(options[predicate.func], None) @@ -270,7 +296,8 @@ def get_integer_predicate_bounds(predicate: Predicate) -> ConstructivePredicate: elif kwargs.get("exclude_max", False): kwargs["max_value"] = int(kwargs["max_value"]) - 1 - kwargs = {k: v for k, v in kwargs.items() if k in {"min_value", "max_value"}} + kw_categories = {"min_value", "max_value", "len"} + kwargs = {k: v for k, v in kwargs.items() if k in kw_categories} return ConstructivePredicate(kwargs, predicate) diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/reflection.py b/contrib/python/hypothesis/py3/hypothesis/internal/reflection.py index 2f0480c987..d5ea7161f3 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/reflection.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/reflection.py @@ -19,7 +19,7 @@ import re import sys import textwrap import types -from functools import wraps +from functools import partial, wraps from io import StringIO from keyword import iskeyword from tokenize import COMMENT, detect_encoding, generate_tokens, untokenize @@ -432,6 +432,8 @@ def extract_lambda_source(f): def get_pretty_function_description(f): + if isinstance(f, partial): + return pretty(f) if not hasattr(f, "__name__"): return repr(f) name = f.__name__ diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/collections.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/collections.py index 2bee499ac2..1f86f37a42 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/collections.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/collections.py @@ -15,6 +15,7 @@ from hypothesis.errors import InvalidArgument from hypothesis.internal.conjecture import utils as cu from hypothesis.internal.conjecture.junkdrawer import LazySequenceCopy from hypothesis.internal.conjecture.utils import combine_labels +from hypothesis.internal.filtering import get_integer_predicate_bounds from hypothesis.internal.reflection import is_identity_function from hypothesis.strategies._internal.strategies import ( T3, @@ -199,7 +200,22 @@ class ListStrategy(SearchStrategy): new = copy.copy(self) new.min_size = 1 return new - return super().filter(condition) + + kwargs, pred = get_integer_predicate_bounds(condition) + if kwargs.get("len") and ("min_value" in kwargs or "max_value" in kwargs): + new = copy.copy(self) + new.min_size = max(self.min_size, kwargs.get("min_value", self.min_size)) + new.max_size = min(self.max_size, kwargs.get("max_value", self.max_size)) + # Recompute average size; this is cheaper than making it into a property. + new.average_size = min( + max(new.min_size * 2, new.min_size + 5), + 0.5 * (new.min_size + new.max_size), + ) + if pred is None: + return new + return SearchStrategy.filter(new, condition) + + return SearchStrategy.filter(self, condition) class UniqueListStrategy(ListStrategy): diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py index 382bffeb8b..ef8fe6a63a 100644 --- a/contrib/python/hypothesis/py3/hypothesis/version.py +++ b/contrib/python/hypothesis/py3/hypothesis/version.py @@ -8,5 +8,5 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. -__version_info__ = (6, 92, 6) +__version_info__ = (6, 92, 8) __version__ = ".".join(map(str, __version_info__)) diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make index 2a6ae3478d..92b1d0c734 100644 --- a/contrib/python/hypothesis/py3/ya.make +++ b/contrib/python/hypothesis/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(6.92.6) +VERSION(6.92.8) LICENSE(MPL-2.0) diff --git a/contrib/python/ydb/py3/.dist-info/METADATA b/contrib/python/ydb/py3/.dist-info/METADATA index 058eb80b41..675a1d8825 100644 --- a/contrib/python/ydb/py3/.dist-info/METADATA +++ b/contrib/python/ydb/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ydb -Version: 3.7.0 +Version: 3.8.0 Summary: YDB Python SDK Home-page: http://github.com/ydb-platform/ydb-python-sdk Author: Yandex LLC diff --git a/contrib/python/ydb/py3/ya.make b/contrib/python/ydb/py3/ya.make index f92572fa82..484d68aafd 100644 --- a/contrib/python/ydb/py3/ya.make +++ b/contrib/python/ydb/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(3.7.0) +VERSION(3.8.0) LICENSE(Apache-2.0) @@ -66,6 +66,8 @@ PY_SRCS( ydb/dbapi/cursor.py ydb/dbapi/errors.py ydb/default_pem.py + ydb/draft/__init__.py + ydb/draft/dynamic_config.py ydb/driver.py ydb/export.py ydb/global_settings.py diff --git a/contrib/python/ydb/py3/ydb/__init__.py b/contrib/python/ydb/py3/ydb/__init__.py index 902b1e0850..8bfba3a902 100644 --- a/contrib/python/ydb/py3/ydb/__init__.py +++ b/contrib/python/ydb/py3/ydb/__init__.py @@ -18,6 +18,7 @@ from .scripting import * # noqa from .import_client import * # noqa from .tracing import * # noqa from .topic import * # noqa +from .draft import * # noqa try: import ydb.aio as aio # noqa diff --git a/contrib/python/ydb/py3/ydb/_apis.py b/contrib/python/ydb/py3/ydb/_apis.py index 924e14c1b6..9ad2a32f21 100644 --- a/contrib/python/ydb/py3/ydb/_apis.py +++ b/contrib/python/ydb/py3/ydb/_apis.py @@ -11,6 +11,10 @@ try: ydb_topic_v1_pb2_grpc, ) + from ydb.public.api.grpc.draft import ( + ydb_dynamic_config_v1_pb2_grpc, + ) + from ydb.public.api.protos import ( ydb_status_codes_pb2, ydb_discovery_pb2, @@ -20,6 +24,10 @@ try: ydb_operation_pb2, ydb_common_pb2, ) + + from ydb.public.api.protos.draft import ( + ydb_dynamic_config_pb2, + ) except ImportError: from contrib.ydb.public.api.grpc import ( ydb_cms_v1_pb2_grpc, @@ -30,6 +38,10 @@ except ImportError: ydb_topic_v1_pb2_grpc, ) + from contrib.ydb.public.api.grpc.draft import ( + ydb_dynamic_config_v1_pb2_grpc, + ) + from contrib.ydb.public.api.protos import ( ydb_status_codes_pb2, ydb_discovery_pb2, @@ -40,6 +52,10 @@ except ImportError: ydb_common_pb2, ) + from contrib.ydb.public.api.protos.draft import ( + ydb_dynamic_config_pb2, + ) + StatusIds = ydb_status_codes_pb2.StatusIds FeatureFlag = ydb_common_pb2.FeatureFlag @@ -49,6 +65,7 @@ ydb_scheme = ydb_scheme_pb2 ydb_table = ydb_table_pb2 ydb_discovery = ydb_discovery_pb2 ydb_operation = ydb_operation_pb2 +ydb_dynamic_config = ydb_dynamic_config_pb2 class CmsService(object): @@ -108,3 +125,12 @@ class TopicService(object): DropTopic = "DropTopic" StreamRead = "StreamRead" StreamWrite = "StreamWrite" + + +class DynamicConfigService(object): + Stub = ydb_dynamic_config_v1_pb2_grpc.DynamicConfigServiceStub + + ReplaceConfig = "ReplaceConfig" + SetConfig = "SetConfig" + GetConfig = "GetConfig" + GetNodeLabels = "GetNodeLabels" diff --git a/contrib/python/ydb/py3/ydb/draft/__init__.py b/contrib/python/ydb/py3/ydb/draft/__init__.py new file mode 100644 index 0000000000..c34316f2c2 --- /dev/null +++ b/contrib/python/ydb/py3/ydb/draft/__init__.py @@ -0,0 +1 @@ +from .dynamic_config import * # noqa diff --git a/contrib/python/ydb/py3/ydb/draft/dynamic_config.py b/contrib/python/ydb/py3/ydb/draft/dynamic_config.py new file mode 100644 index 0000000000..afec19eca7 --- /dev/null +++ b/contrib/python/ydb/py3/ydb/draft/dynamic_config.py @@ -0,0 +1,173 @@ +import abc +from abc import abstractmethod +from .. import issues, operation, _apis + + +class IDynamicConfigClient(abc.ABC): + @abstractmethod + def __init__(self, driver): + pass + + @abstractmethod + def replace_config(self, config, dry_run, allow_unknown_fields, settings): + pass + + @abstractmethod + def set_config(self, config, dry_run, allow_unknown_fields, settings): + pass + + @abstractmethod + def get_config(self, settings): + pass + + @abstractmethod + def get_node_labels(self, node_id, settings): + pass + + +class DynamicConfig(object): + __slots__ = ("version", "cluster", "config") + + def __init__(self, version, cluster, config, *args, **kwargs): + self.version = version + self.cluster = cluster + self.config = config + + +class NodeLabels(object): + __slots__ = "labels" + + def __init__(self, labels, *args, **kwargs): + self.labels = labels + + +def _replace_config_request_factory(config, dry_run, allow_unknown_fields): + request = _apis.ydb_dynamic_config.ReplaceConfigRequest() + request.config = config + request.dry_run = dry_run + request.allow_unknown_fields = allow_unknown_fields + return request + + +def _set_config_request_factory(config, dry_run, allow_unknown_fields): + request = _apis.ydb_dynamic_config.SetConfigRequest() + request.config = config + request.dry_run = dry_run + request.allow_unknown_fields = allow_unknown_fields + return request + + +def _get_config_request_factory(): + request = _apis.ydb_dynamic_config.GetConfigRequest() + return request + + +def _get_node_labels_request_factory(node_id): + request = _apis.ydb_dynamic_config.GetNodeLabelsRequest() + request.node_id = node_id + return request + + +def _wrap_dynamic_config(config_pb, dynamic_config_cls=None, *args, **kwargs): + dynamic_config_cls = DynamicConfig if dynamic_config_cls is None else dynamic_config_cls + return dynamic_config_cls(config_pb.identity.version, config_pb.identity.cluster, config_pb.config, *args, **kwargs) + + +def _wrap_get_config_response(rpc_state, response): + issues._process_response(response.operation) + message = _apis.ydb_dynamic_config.GetConfigResult() + response.operation.result.Unpack(message) + return _wrap_dynamic_config(message) + + +def _wrap_node_labels(labels_pb, node_labels_cls=None, *args, **kwargs): + node_labels_cls = NodeLabels if node_labels_cls is None else node_labels_cls + return node_labels_cls(dict([(entry.label, entry.value) for entry in labels_pb.labels]), *args, **kwargs) + + +def _wrap_get_node_labels_response(rpc_state, response): + issues._process_response(response.operation) + message = _apis.ydb_dynamic_config.GetNodeLabelsResult() + response.operation.result.Unpack(message) + return _wrap_node_labels(message) + + +class BaseDynamicConfigClient(IDynamicConfigClient): + __slots__ = ("_driver",) + + def __init__(self, driver): + self._driver = driver + + def replace_config(self, config, dry_run, allow_unknown_fields, settings=None): + return self._driver( + _replace_config_request_factory(config, dry_run, allow_unknown_fields), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.ReplaceConfig, + operation.Operation, + settings, + ) + + def set_config(self, config, dry_run, allow_unknown_fields, settings=None): + return self._driver( + _set_config_request_factory(config, dry_run, allow_unknown_fields), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.SetConfig, + operation.Operation, + settings, + ) + + def get_config(self, settings=None): + return self._driver( + _get_config_request_factory(), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.GetConfig, + _wrap_get_config_response, + settings, + ) + + def get_node_labels(self, node_id, settings=None): + return self._driver( + _get_node_labels_request_factory(node_id), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.GetNodeLabels, + _wrap_get_node_labels_response, + settings, + ) + + +class DynamicConfigClient(BaseDynamicConfigClient): + def async_replace_config(self, config, dry_run, allow_unknown_fields, settings=None): + return self._driver.future( + _replace_config_request_factory(config, dry_run, allow_unknown_fields), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.ReplaceConfig, + operation.Operation, + settings, + ) + + def async_set_config(self, config, dry_run, allow_unknown_fields, settings=None): + return self._driver.future( + _set_config_request_factory(config, dry_run, allow_unknown_fields), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.SetConfig, + operation.Operation, + settings, + ) + + def async_get_config(self, settings=None): + return self._driver.future( + _get_config_request_factory(), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.GetConfig, + _wrap_get_config_response, + settings, + ) + + def async_get_node_labels(self, node_id, settings=None): + return self._driver.future( + _get_node_labels_request_factory(node_id), + _apis.DynamicConfigService.Stub, + _apis.DynamicConfigService.GetNodeLabels, + _wrap_get_node_labels_response, + settings, + ) diff --git a/contrib/python/ydb/py3/ydb/ydb_version.py b/contrib/python/ydb/py3/ydb/ydb_version.py index 709cb0a9e5..8173e1e609 100644 --- a/contrib/python/ydb/py3/ydb/ydb_version.py +++ b/contrib/python/ydb/py3/ydb/ydb_version.py @@ -1 +1 @@ -VERSION = "3.7.0" +VERSION = "3.8.0" diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h b/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h index e9b4733872..59aeed7d26 100644 --- a/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h +++ b/contrib/restricted/abseil-cpp/absl/algorithm/algorithm.h @@ -31,92 +31,17 @@ namespace absl { ABSL_NAMESPACE_BEGIN -namespace algorithm_internal { - -// Performs comparisons with operator==, similar to C++14's `std::equal_to<>`. -struct EqualTo { - template <typename T, typename U> - bool operator()(const T& a, const U& b) const { - return a == b; - } -}; - -template <typename InputIter1, typename InputIter2, typename Pred> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred pred, std::input_iterator_tag, - std::input_iterator_tag) { - while (true) { - if (first1 == last1) return first2 == last2; - if (first2 == last2) return false; - if (!pred(*first1, *first2)) return false; - ++first1; - ++first2; - } -} - -template <typename InputIter1, typename InputIter2, typename Pred> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred&& pred, std::random_access_iterator_tag, - std::random_access_iterator_tag) { - return (last1 - first1 == last2 - first2) && - std::equal(first1, last1, first2, std::forward<Pred>(pred)); -} - -// When we are using our own internal predicate that just applies operator==, we -// forward to the non-predicate form of std::equal. This enables an optimization -// in libstdc++ that can result in std::memcmp being used for integer types. -template <typename InputIter1, typename InputIter2> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, algorithm_internal::EqualTo /* unused */, - std::random_access_iterator_tag, - std::random_access_iterator_tag) { - return (last1 - first1 == last2 - first2) && - std::equal(first1, last1, first2); -} - -template <typename It> -It RotateImpl(It first, It middle, It last, std::true_type) { - return std::rotate(first, middle, last); -} - -template <typename It> -It RotateImpl(It first, It middle, It last, std::false_type) { - std::rotate(first, middle, last); - return std::next(first, std::distance(middle, last)); -} - -} // namespace algorithm_internal - // equal() +// rotate() // -// Compares the equality of two ranges specified by pairs of iterators, using -// the given predicate, returning true iff for each corresponding iterator i1 -// and i2 in the first and second range respectively, pred(*i1, *i2) == true -// -// This comparison takes at most min(`last1` - `first1`, `last2` - `first2`) -// invocations of the predicate. Additionally, if InputIter1 and InputIter2 are -// both random-access iterators, and `last1` - `first1` != `last2` - `first2`, -// then the predicate is never invoked and the function returns false. +// Historical note: Abseil once provided implementations of these algorithms +// prior to their adoption in C++14. New code should prefer to use the std +// variants. // -// This is a C++11-compatible implementation of C++14 `std::equal`. See -// https://en.cppreference.com/w/cpp/algorithm/equal for more information. -template <typename InputIter1, typename InputIter2, typename Pred> -bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred&& pred) { - return algorithm_internal::EqualImpl( - first1, last1, first2, last2, std::forward<Pred>(pred), - typename std::iterator_traits<InputIter1>::iterator_category{}, - typename std::iterator_traits<InputIter2>::iterator_category{}); -} - -// Overload of equal() that performs comparison of two ranges specified by pairs -// of iterators using operator==. -template <typename InputIter1, typename InputIter2> -bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2) { - return absl::equal(first1, last1, first2, last2, - algorithm_internal::EqualTo{}); -} +// See the documentation for the STL <algorithm> header for more information: +// https://en.cppreference.com/w/cpp/header/algorithm +using std::equal; +using std::rotate; // linear_search() // @@ -133,26 +58,6 @@ bool linear_search(InputIterator first, InputIterator last, return std::find(first, last, value) != last; } -// rotate() -// -// Performs a left rotation on a range of elements (`first`, `last`) such that -// `middle` is now the first element. `rotate()` returns an iterator pointing to -// the first element before rotation. This function is exactly the same as -// `std::rotate`, but fixes a bug in gcc -// <= 4.9 where `std::rotate` returns `void` instead of an iterator. -// -// The complexity of this algorithm is the same as that of `std::rotate`, but if -// `ForwardIterator` is not a random-access iterator, then `absl::rotate` -// performs an additional pass over the range to construct the return value. -template <typename ForwardIterator> -ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last) { - return algorithm_internal::RotateImpl( - first, middle, last, - std::is_same<decltype(std::rotate(first, middle, last)), - ForwardIterator>()); -} - ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/container.h b/contrib/restricted/abseil-cpp/absl/algorithm/container.h index 679e02676c..c7bafae147 100644 --- a/contrib/restricted/abseil-cpp/absl/algorithm/container.h +++ b/contrib/restricted/abseil-cpp/absl/algorithm/container.h @@ -52,6 +52,7 @@ #include "absl/algorithm/algorithm.h" #include "absl/base/macros.h" +#include "absl/base/nullability.h" #include "absl/meta/type_traits.h" namespace absl { @@ -116,18 +117,6 @@ template <class Key, class Hash, class KeyEqual, class Allocator> struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>> : std::true_type {}; -// container_algorithm_internal::c_size. It is meant for internal use only. - -template <class C> -auto c_size(C& c) -> decltype(c.size()) { - return c.size(); -} - -template <class T, std::size_t N> -constexpr std::size_t c_size(T (&)[N]) { - return N; -} - } // namespace container_algorithm_internal // PUBLIC API @@ -348,20 +337,10 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if( template <typename C1, typename C2> container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1, C2& c2) { - auto first1 = container_algorithm_internal::c_begin(c1); - auto last1 = container_algorithm_internal::c_end(c1); - auto first2 = container_algorithm_internal::c_begin(c2); - auto last2 = container_algorithm_internal::c_end(c2); - - for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { - // Negates equality because Cpp17EqualityComparable doesn't require clients - // to overload both `operator==` and `operator!=`. - if (!(*first1 == *first2)) { - break; - } - } - - return std::make_pair(first1, first2); + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); } // Overload of c_mismatch() for using a predicate evaluation other than `==` as @@ -370,56 +349,33 @@ container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1, template <typename C1, typename C2, typename BinaryPredicate> container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch( C1& c1, C2& c2, BinaryPredicate pred) { - auto first1 = container_algorithm_internal::c_begin(c1); - auto last1 = container_algorithm_internal::c_end(c1); - auto first2 = container_algorithm_internal::c_begin(c2); - auto last2 = container_algorithm_internal::c_end(c2); - - for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { - if (!pred(*first1, *first2)) { - break; - } - } - - return std::make_pair(first1, first2); + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), pred); } // c_equal() // // Container-based version of the <algorithm> `std::equal()` function to // test whether two containers are equal. -// -// NOTE: the semantics of c_equal() are slightly different than those of -// equal(): while the latter iterates over the second container only up to the -// size of the first container, c_equal() also checks whether the container -// sizes are equal. This better matches expectations about c_equal() based on -// its signature. -// -// Example: -// vector v1 = <1, 2, 3>; -// vector v2 = <1, 2, 3, 4>; -// equal(std::begin(v1), std::end(v1), std::begin(v2)) returns true -// c_equal(v1, v2) returns false - template <typename C1, typename C2> bool c_equal(const C1& c1, const C2& c2) { - return ((container_algorithm_internal::c_size(c1) == - container_algorithm_internal::c_size(c2)) && - std::equal(container_algorithm_internal::c_begin(c1), - container_algorithm_internal::c_end(c1), - container_algorithm_internal::c_begin(c2))); + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); } // Overload of c_equal() for using a predicate evaluation other than `==` as // the function's test condition. template <typename C1, typename C2, typename BinaryPredicate> bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { - return ((container_algorithm_internal::c_size(c1) == - container_algorithm_internal::c_size(c2)) && - std::equal(container_algorithm_internal::c_begin(c1), - container_algorithm_internal::c_end(c1), - container_algorithm_internal::c_begin(c2), - std::forward<BinaryPredicate>(pred))); + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward<BinaryPredicate>(pred)); } // c_is_permutation() @@ -428,20 +384,20 @@ bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { // to test whether a container is a permutation of another. template <typename C1, typename C2> bool c_is_permutation(const C1& c1, const C2& c2) { - using std::begin; - using std::end; - return c1.size() == c2.size() && - std::is_permutation(begin(c1), end(c1), begin(c2)); + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); } // Overload of c_is_permutation() for using a predicate evaluation other than // `==` as the function's test condition. template <typename C1, typename C2, typename BinaryPredicate> bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { - using std::begin; - using std::end; - return c1.size() == c2.size() && - std::is_permutation(begin(c1), end(c1), begin(c2), + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), std::forward<BinaryPredicate>(pred)); } @@ -818,6 +774,36 @@ void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) { std::forward<UniformRandomBitGenerator>(gen)); } +// c_sample() +// +// Container-based version of the <algorithm> `std::sample()` function to +// randomly sample elements from the container without replacement using a +// `gen()` uniform random number generator and write them to an iterator range. +template <typename C, typename OutputIterator, typename Distance, + typename UniformRandomBitGenerator> +OutputIterator c_sample(const C& c, OutputIterator result, Distance n, + UniformRandomBitGenerator&& gen) { +#if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L + return std::sample(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, n, + std::forward<UniformRandomBitGenerator>(gen)); +#else + // Fall back to a stable selection-sampling implementation. + auto first = container_algorithm_internal::c_begin(c); + Distance unsampled_elements = c_distance(c); + n = (std::min)(n, unsampled_elements); + for (; n != 0; ++first) { + Distance r = + std::uniform_int_distribution<Distance>(0, --unsampled_elements)(gen); + if (r < n) { + *result++ = *first; + --n; + } + } + return result; +#endif +} + //------------------------------------------------------------------------------ // <algorithm> Partition functions //------------------------------------------------------------------------------ @@ -1657,7 +1643,7 @@ bool c_prev_permutation(C& c, LessThan&& comp) { // // Container-based version of the <numeric> `std::iota()` function // to compute successive values of `value`, as if incremented with `++value` -// after each element is written. and write them to the container. +// after each element is written, and write them to the container. template <typename Sequence, typename T> void c_iota(Sequence& sequence, const T& value) { std::iota(container_algorithm_internal::c_begin(sequence), diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/ya.make b/contrib/restricted/abseil-cpp/absl/algorithm/ya.make index 3b66e3e400..3f9af85fe6 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(20230802.1) +VERSION(20240116.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240116.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 a7f279a025..d4f67a1295 100644 --- a/contrib/restricted/abseil-cpp/absl/base/attributes.h +++ b/contrib/restricted/abseil-cpp/absl/base/attributes.h @@ -687,7 +687,7 @@ // When deprecating Abseil code, it is sometimes necessary to turn off the // warning within Abseil, until the deprecated code is actually removed. The -// deprecated code can be surrounded with these directives to acheive that +// deprecated code can be surrounded with these directives to achieve that // result. // // class ABSL_DEPRECATED("Use Bar instead") Foo; @@ -747,9 +747,52 @@ #define ABSL_CONST_INIT #endif -// These annotations are not available yet due to fear of breaking code. -#define ABSL_ATTRIBUTE_PURE_FUNCTION -#define ABSL_ATTRIBUTE_CONST_FUNCTION +// ABSL_ATTRIBUTE_PURE_FUNCTION +// +// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" +// functions. A function is pure if its return value is only a function of its +// arguments. The pure attribute prohibits a function from modifying the state +// of the program that is observable by means other than inspecting the +// function's return value. Declaring such functions with the pure attribute +// allows the compiler to avoid emitting some calls in repeated invocations of +// the function with the same argument values. +// +// Example: +// +// ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t); +#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] +#elif ABSL_HAVE_ATTRIBUTE(pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) +#else +// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since +// pure functions are useless if its return is ignored. +#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_CONST_FUNCTION +// +// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const" +// functions. A const function is similar to a pure function, with one +// exception: Pure functions may return value that depend on a non-volatile +// object that isn't provided as a function argument, while the const function +// is guaranteed to return the same result given the same arguments. +// +// Example: +// +// ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d); +#if defined(_MSC_VER) && !defined(__clang__) +// Put the MSVC case first since MSVC seems to parse const as a C++ keyword. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]] +#elif ABSL_HAVE_ATTRIBUTE(const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const)) +#else +// Since const functions are more restrictive pure function, we'll fallback to a +// pure function if the const attribute is not handled. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#endif // ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function // parameter or implicit object parameter is retained by the return value of the @@ -800,15 +843,11 @@ // See also the upstream documentation: // https://clang.llvm.org/docs/AttributeReference.html#trivial-abi // -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::trivial_abi) -#define ABSL_ATTRIBUTE_TRIVIAL_ABI [[clang::trivial_abi]] -#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1 -#elif ABSL_HAVE_ATTRIBUTE(trivial_abi) -#define ABSL_ATTRIBUTE_TRIVIAL_ABI __attribute__((trivial_abi)) -#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1 -#else +// b/321691395 - This is currently disabled in open-source builds since +// compiler support differs. If system libraries compiled with GCC are mixed +// with libraries compiled with Clang, types will have different ideas about +// their ABI, leading to hard to debug crashes. #define ABSL_ATTRIBUTE_TRIVIAL_ABI -#endif // ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS // diff --git a/contrib/restricted/abseil-cpp/absl/base/call_once.h b/contrib/restricted/abseil-cpp/absl/base/call_once.h index 08436bac8a..7b0e69ccd5 100644 --- a/contrib/restricted/abseil-cpp/absl/base/call_once.h +++ b/contrib/restricted/abseil-cpp/absl/base/call_once.h @@ -37,6 +37,7 @@ #include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/spinlock_wait.h" #include "absl/base/macros.h" +#include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/base/port.h" @@ -46,7 +47,8 @@ ABSL_NAMESPACE_BEGIN class once_flag; namespace base_internal { -std::atomic<uint32_t>* ControlWord(absl::once_flag* flag); +absl::Nonnull<std::atomic<uint32_t>*> ControlWord( + absl::Nonnull<absl::once_flag*> flag); } // namespace base_internal // call_once() @@ -89,7 +91,8 @@ class once_flag { once_flag& operator=(const once_flag&) = delete; private: - friend std::atomic<uint32_t>* base_internal::ControlWord(once_flag* flag); + friend absl::Nonnull<std::atomic<uint32_t>*> base_internal::ControlWord( + absl::Nonnull<once_flag*> flag); std::atomic<uint32_t> control_; }; @@ -103,7 +106,8 @@ namespace base_internal { // Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to // initialize entities used by the scheduler implementation. template <typename Callable, typename... Args> -void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args); +void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn, + Args&&... args); // Disables scheduling while on stack when scheduling mode is non-cooperative. // No effect for cooperative scheduling modes. @@ -143,10 +147,10 @@ enum { }; template <typename Callable, typename... Args> -ABSL_ATTRIBUTE_NOINLINE -void CallOnceImpl(std::atomic<uint32_t>* control, - base_internal::SchedulingMode scheduling_mode, Callable&& fn, - Args&&... args) { +ABSL_ATTRIBUTE_NOINLINE 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); @@ -185,12 +189,14 @@ void CallOnceImpl(std::atomic<uint32_t>* control, } // else *control is already kOnceDone } -inline std::atomic<uint32_t>* ControlWord(once_flag* flag) { +inline absl::Nonnull<std::atomic<uint32_t>*> ControlWord( + absl::Nonnull<once_flag*> flag) { return &flag->control_; } template <typename Callable, typename... Args> -void LowLevelCallOnce(absl::once_flag* flag, Callable&& fn, Args&&... args) { +void LowLevelCallOnce(absl::Nonnull<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/casts.h b/contrib/restricted/abseil-cpp/absl/base/casts.h index d19588852f..e0b11bbe49 100644 --- a/contrib/restricted/abseil-cpp/absl/base/casts.h +++ b/contrib/restricted/abseil-cpp/absl/base/casts.h @@ -90,7 +90,7 @@ ABSL_NAMESPACE_BEGIN // // Such implicit cast chaining may be useful within template logic. template <typename To> -constexpr To implicit_cast(typename absl::internal::identity_t<To> to) { +constexpr To implicit_cast(typename absl::internal::type_identity_t<To> to) { return to; } diff --git a/contrib/restricted/abseil-cpp/absl/base/config.h b/contrib/restricted/abseil-cpp/absl/base/config.h index 334e2767ac..8bd9a6d586 100644 --- a/contrib/restricted/abseil-cpp/absl/base/config.h +++ b/contrib/restricted/abseil-cpp/absl/base/config.h @@ -75,6 +75,12 @@ #define ABSL_INTERNAL_CPLUSPLUS_LANG __cplusplus #endif +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +// Include library feature test macros. +#include <version> +#endif + #if defined(__APPLE__) // Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED, // __IPHONE_8_0. @@ -111,8 +117,8 @@ // // LTS releases can be obtained from // https://github.com/abseil/abseil-cpp/releases. -#define ABSL_LTS_RELEASE_VERSION 20230802 -#define ABSL_LTS_RELEASE_PATCH_LEVEL 1 +#define ABSL_LTS_RELEASE_VERSION 20240116 +#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 @@ -332,8 +338,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #ifdef ABSL_HAVE_INTRINSIC_INT128 #error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set #elif defined(__SIZEOF_INT128__) -#if (defined(__clang__) && !defined(_WIN32)) || \ - (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ +#if (defined(__clang__) && !defined(_WIN32)) || \ + (defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \ (defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)) #define ABSL_HAVE_INTRINSIC_INT128 1 #elif defined(__CUDACC__) @@ -395,7 +401,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // Windows _WIN32 // NaCL __native_client__ // AsmJS __asmjs__ -// WebAssembly __wasm__ +// WebAssembly (Emscripten) __EMSCRIPTEN__ // Fuchsia __Fuchsia__ // // Note that since Android defines both __ANDROID__ and __linux__, one @@ -407,11 +413,11 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // POSIX.1-2001. #ifdef ABSL_HAVE_MMAP #error ABSL_HAVE_MMAP cannot be directly set -#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(_AIX) || defined(__ros__) || defined(__native_client__) || \ - defined(__asmjs__) || defined(__wasm__) || defined(__Fuchsia__) || \ - defined(__sun) || defined(__ASYLO__) || defined(__myriad2__) || \ - defined(__HAIKU__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ + defined(_AIX) || defined(__ros__) || defined(__native_client__) || \ + defined(__asmjs__) || defined(__EMSCRIPTEN__) || defined(__Fuchsia__) || \ + defined(__sun) || defined(__ASYLO__) || defined(__myriad2__) || \ + defined(__HAIKU__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ defined(__QNX__) || defined(__VXWORKS__) || defined(__hexagon__) #define ABSL_HAVE_MMAP 1 #endif @@ -484,6 +490,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c #elif defined(__EMSCRIPTEN__) // emscripten doesn't support signals +#elif defined(__wasi__) +// WASI doesn't support signals #elif defined(__Fuchsia__) // Signals don't exist on fuchsia. #elif defined(__native_client__) @@ -536,14 +544,14 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // and // https://github.com/llvm/llvm-project/commit/0bc451e7e137c4ccadcd3377250874f641ca514a // The second has the actually correct versions, thus, is what we copy here. -#if defined(__APPLE__) && \ - ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ - __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ +#if defined(__APPLE__) && \ + ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \ __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000)) #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1 #else @@ -555,7 +563,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // Checks whether C++17 std::any is available. #ifdef ABSL_HAVE_STD_ANY #error "ABSL_HAVE_STD_ANY cannot be directly set." -#elif defined(__cpp_lib_any) +#elif defined(__cpp_lib_any) && __cpp_lib_any >= 201606L #define ABSL_HAVE_STD_ANY 1 #elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \ @@ -568,9 +576,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // Checks whether C++17 std::optional is available. #ifdef ABSL_HAVE_STD_OPTIONAL #error "ABSL_HAVE_STD_OPTIONAL cannot be directly set." -#elif defined(__cpp_lib_optional) +#elif defined(__cpp_lib_optional) && __cpp_lib_optional >= 202106L #define ABSL_HAVE_STD_OPTIONAL 1 -#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ +#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \ !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE #define ABSL_HAVE_STD_OPTIONAL 1 @@ -581,7 +589,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // Checks whether C++17 std::variant is available. #ifdef ABSL_HAVE_STD_VARIANT #error "ABSL_HAVE_STD_VARIANT cannot be directly set." -#elif defined(__cpp_lib_variant) +#elif defined(__cpp_lib_variant) && __cpp_lib_variant >= 201606L #define ABSL_HAVE_STD_VARIANT 1 #elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \ @@ -594,13 +602,29 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // Checks whether C++17 std::string_view is available. #ifdef ABSL_HAVE_STD_STRING_VIEW #error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set." -#elif defined(__cpp_lib_string_view) +#elif defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L #define ABSL_HAVE_STD_STRING_VIEW 1 #elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L #define ABSL_HAVE_STD_STRING_VIEW 1 #endif +// ABSL_HAVE_STD_ORDERING +// +// Checks whether C++20 std::{partial,weak,strong}_ordering are available. +// +// __cpp_lib_three_way_comparison is missing on libc++ +// (https://github.com/llvm/llvm-project/issues/73953) so treat it as defined +// when building in C++20 mode. +#ifdef ABSL_HAVE_STD_ORDERING +#error "ABSL_HAVE_STD_ORDERING cannot be directly set." +#elif (defined(__cpp_lib_three_way_comparison) && \ + __cpp_lib_three_way_comparison >= 201907L) || \ + (defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L) +#define ABSL_HAVE_STD_ORDERING 1 +#endif + // ABSL_USES_STD_ANY // // Indicates whether absl::any is an alias for std::any. @@ -663,6 +687,22 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #error options.h is misconfigured. #endif +// ABSL_USES_STD_ORDERING +// +// Indicates whether absl::{partial,weak,strong}_ordering are aliases for the +// std:: ordering types. +#if !defined(ABSL_OPTION_USE_STD_ORDERING) +#error options.h is misconfigured. +#elif ABSL_OPTION_USE_STD_ORDERING == 0 || \ + (ABSL_OPTION_USE_STD_ORDERING == 2 && !defined(ABSL_HAVE_STD_ORDERING)) +#undef ABSL_USES_STD_ORDERING +#elif ABSL_OPTION_USE_STD_ORDERING == 1 || \ + (ABSL_OPTION_USE_STD_ORDERING == 2 && defined(ABSL_HAVE_STD_ORDERING)) +#define ABSL_USES_STD_ORDERING 1 +#else +#error options.h is misconfigured. +#endif + // In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION // SEH exception from emplace for variant<SomeStruct> when constructing the // struct can throw. This defeats some of variant_test and @@ -845,11 +885,30 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || // RTTI support. #ifdef ABSL_INTERNAL_HAS_RTTI #error ABSL_INTERNAL_HAS_RTTI cannot be directly set -#elif (defined(__GNUC__) && defined(__GXX_RTTI)) || \ - (defined(_MSC_VER) && defined(_CPPRTTI)) || \ - (!defined(__GNUC__) && !defined(_MSC_VER)) +#elif ABSL_HAVE_FEATURE(cxx_rtti) +#define ABSL_INTERNAL_HAS_RTTI 1 +#elif defined(__GNUC__) && defined(__GXX_RTTI) #define ABSL_INTERNAL_HAS_RTTI 1 -#endif // !defined(__GNUC__) || defined(__GXX_RTTI) +#elif defined(_MSC_VER) && defined(_CPPRTTI) +#define ABSL_INTERNAL_HAS_RTTI 1 +#elif !defined(__GNUC__) && !defined(_MSC_VER) +// Unknown compiler, default to RTTI +#define ABSL_INTERNAL_HAS_RTTI 1 +#endif + +// `ABSL_INTERNAL_HAS_CXA_DEMANGLE` determines whether `abi::__cxa_demangle` is +// available. +#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE +#error ABSL_INTERNAL_HAS_CXA_DEMANGLE cannot be directly set +#elif defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__)) +#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 0 +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \ + !defined(__mips__) +#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1 +#elif defined(__clang__) && !defined(_MSC_VER) +#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1 +#endif // ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support. // See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of @@ -936,8 +995,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #if __EMSCRIPTEN_tiny__ >= 1000 #error __EMSCRIPTEN_tiny__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION #endif -#define ABSL_INTERNAL_EMSCRIPTEN_VERSION \ - ((__EMSCRIPTEN_major__)*1000000 + (__EMSCRIPTEN_minor__)*1000 + \ +#define ABSL_INTERNAL_EMSCRIPTEN_VERSION \ + ((__EMSCRIPTEN_major__) * 1000000 + (__EMSCRIPTEN_minor__) * 1000 + \ (__EMSCRIPTEN_tiny__)) #endif #endif diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/endian.h b/contrib/restricted/abseil-cpp/absl/base/internal/endian.h index 50747d75ec..943f3d97e7 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/endian.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/endian.h @@ -22,6 +22,7 @@ #include "absl/base/casts.h" #include "absl/base/config.h" #include "absl/base/internal/unaligned_access.h" +#include "absl/base/nullability.h" #include "absl/base/port.h" namespace absl { @@ -160,27 +161,27 @@ inline int64_t ToHost(int64_t x) { } // Functions to do unaligned loads and stores in little-endian order. -inline uint16_t Load16(const void *p) { +inline uint16_t Load16(absl::Nonnull<const void *> p) { return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); } -inline void Store16(void *p, uint16_t v) { +inline void Store16(absl::Nonnull<void *> p, uint16_t v) { ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); } -inline uint32_t Load32(const void *p) { +inline uint32_t Load32(absl::Nonnull<const void *> p) { return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p)); } -inline void Store32(void *p, uint32_t v) { +inline void Store32(absl::Nonnull<void *> p, uint32_t v) { ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); } -inline uint64_t Load64(const void *p) { +inline uint64_t Load64(absl::Nonnull<const void *> p) { return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p)); } -inline void Store64(void *p, uint64_t v) { +inline void Store64(absl::Nonnull<void *> p, uint64_t v) { ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); } @@ -250,27 +251,27 @@ inline int64_t ToHost(int64_t x) { } // Functions to do unaligned loads and stores in big-endian order. -inline uint16_t Load16(const void *p) { +inline uint16_t Load16(absl::Nonnull<const void *> p) { return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); } -inline void Store16(void *p, uint16_t v) { +inline void Store16(absl::Nonnull<void *> p, uint16_t v) { ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v)); } -inline uint32_t Load32(const void *p) { +inline uint32_t Load32(absl::Nonnull<const void *> p) { return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p)); } -inline void Store32(void *p, uint32_t v) { +inline void Store32(absl::Nonnull<void *>p, uint32_t v) { ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v)); } -inline uint64_t Load64(const void *p) { +inline uint64_t Load64(absl::Nonnull<const void *> p) { return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p)); } -inline void Store64(void *p, uint64_t v) { +inline void Store64(absl::Nonnull<void *> p, uint64_t v) { ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v)); } diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/identity.h b/contrib/restricted/abseil-cpp/absl/base/internal/identity.h index a3154ed7bc..365207b7e7 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/identity.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/identity.h @@ -22,13 +22,15 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace internal { +// This is a back-fill of C++20's `std::type_identity`. template <typename T> -struct identity { +struct type_identity { typedef T type; }; +// This is a back-fill of C++20's `std::type_identity_t`. template <typename T> -using identity_t = typename identity<T>::type; +using type_identity_t = typename type_identity<T>::type; } // namespace internal ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h b/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h index df933faff5..09daf0f5b7 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h @@ -63,12 +63,12 @@ // Bug: https://bugs.llvm.org/show_bug.cgi?id=35862 // // Note: -// identity_t is used here so that the const and name are in the +// type_identity_t is used here so that the const and name are in the // appropriate place for pointer types, reference types, function pointer // types, etc.. #if defined(__clang__) #define ABSL_INTERNAL_EXTERN_DECL(type, name) \ - extern const ::absl::internal::identity_t<type> name; + extern const ::absl::internal::type_identity_t<type> name; #else // Otherwise, just define the macro to do nothing. #define ABSL_INTERNAL_EXTERN_DECL(type, name) #endif // defined(__clang__) @@ -76,30 +76,31 @@ // See above comment at top of file for details. #define ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) \ ABSL_INTERNAL_EXTERN_DECL(type, name) \ - inline constexpr ::absl::internal::identity_t<type> name = init + inline constexpr ::absl::internal::type_identity_t<type> name = init #else // See above comment at top of file for details. // // Note: -// identity_t is used here so that the const and name are in the +// type_identity_t is used here so that the const and name are in the // appropriate place for pointer types, reference types, function pointer // types, etc.. -#define ABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \ - template <class /*AbslInternalDummy*/ = void> \ - struct AbslInternalInlineVariableHolder##name { \ - static constexpr ::absl::internal::identity_t<var_type> kInstance = init; \ - }; \ - \ - template <class AbslInternalDummy> \ - constexpr ::absl::internal::identity_t<var_type> \ - AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance; \ - \ - static constexpr const ::absl::internal::identity_t<var_type>& \ - name = /* NOLINT */ \ - AbslInternalInlineVariableHolder##name<>::kInstance; \ - static_assert(sizeof(void (*)(decltype(name))) != 0, \ +#define ABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init) \ + template <class /*AbslInternalDummy*/ = void> \ + struct AbslInternalInlineVariableHolder##name { \ + static constexpr ::absl::internal::type_identity_t<var_type> kInstance = \ + init; \ + }; \ + \ + template <class AbslInternalDummy> \ + constexpr ::absl::internal::type_identity_t<var_type> \ + AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance; \ + \ + static constexpr const ::absl::internal::type_identity_t<var_type>& \ + name = /* NOLINT */ \ + AbslInternalInlineVariableHolder##name<>::kInstance; \ + static_assert(sizeof(void (*)(decltype(name))) != 0, \ "Silence unused variable warnings.") #endif // __cpp_inline_variables diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc b/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc index 6d2cfeac3c..a563f7b9f9 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc +++ b/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc @@ -329,7 +329,7 @@ size_t GetPageSize() { SYSTEM_INFO system_info; GetSystemInfo(&system_info); return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity); -#elif defined(__wasm__) || defined(__asmjs__) +#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__) return getpagesize(); #else return static_cast<size_t>(sysconf(_SC_PAGESIZE)); diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/nullability_impl.h b/contrib/restricted/abseil-cpp/absl/base/internal/nullability_impl.h new file mode 100644 index 0000000000..36e1b33d65 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/base/internal/nullability_impl.h @@ -0,0 +1,106 @@ +// Copyright 2023 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ +#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ + +#include <memory> +#include <type_traits> + +#include "absl/base/attributes.h" +#include "absl/meta/type_traits.h" + +namespace absl { + +namespace nullability_internal { + +// `IsNullabilityCompatible` checks whether its first argument is a class +// explicitly tagged as supporting nullability annotations. The tag is the type +// declaration `absl_nullability_compatible`. +template <typename, typename = void> +struct IsNullabilityCompatible : std::false_type {}; + +template <typename T> +struct IsNullabilityCompatible< + T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type { +}; + +template <typename T> +constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value; + +template <typename T> +constexpr bool IsSupportedType<T*> = true; + +template <typename T, typename U> +constexpr bool IsSupportedType<T U::*> = true; + +template <typename T, typename... Deleter> +constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true; + +template <typename T> +constexpr bool IsSupportedType<std::shared_ptr<T>> = true; + +template <typename T> +struct EnableNullable { + static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, + "Template argument must be a raw or supported smart pointer " + "type. See absl/base/nullability.h."); + using type = T; +}; + +template <typename T> +struct EnableNonnull { + static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, + "Template argument must be a raw or supported smart pointer " + "type. See absl/base/nullability.h."); + using type = T; +}; + +template <typename T> +struct EnableNullabilityUnknown { + static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>, + "Template argument must be a raw or supported smart pointer " + "type. See absl/base/nullability.h."); + using type = T; +}; + +// Note: we do not apply Clang nullability attributes (e.g. _Nullable). These +// only support raw pointers, and conditionally enabling them only for raw +// pointers inhibits template arg deduction. Ideally, they would support all +// pointer-like types. +template <typename T, typename = typename EnableNullable<T>::type> +using NullableImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nullable")]] +#endif + = T; + +template <typename T, typename = typename EnableNonnull<T>::type> +using NonnullImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nonnull")]] +#endif + = T; + +template <typename T, typename = typename EnableNullabilityUnknown<T>::type> +using NullabilityUnknownImpl +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate) + [[clang::annotate("Nullability_Unspecified")]] +#endif + = T; + +} // namespace nullability_internal +} // namespace absl + +#endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ 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 a1ca876d4e..6f68002a3c 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc +++ b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc @@ -42,8 +42,9 @@ // This preprocessor token is also defined in raw_io.cc. If you need to copy // this, consider moving both to config.h instead. #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__Fuchsia__) || defined(__native_client__) || \ - defined(__OpenBSD__) || defined(__EMSCRIPTEN__) || defined(__ASYLO__) + defined(__hexagon__) || defined(__Fuchsia__) || \ + defined(__native_client__) || defined(__OpenBSD__) || \ + defined(__EMSCRIPTEN__) || defined(__ASYLO__) #include <unistd.h> @@ -56,8 +57,7 @@ // ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall // syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len); // for low level operations that want to avoid libc. -#if (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)) && \ - !defined(__ANDROID__) +#if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__) #include <sys/syscall.h> #define ABSL_HAVE_SYSCALL_WRITE 1 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1 @@ -93,8 +93,7 @@ constexpr char kTruncated[] = " ... (message truncated)\n"; bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0); bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) { - if (*size < 0) - return false; + if (*size < 0) return false; int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap); bool result = true; if (n < 0 || n > *size) { @@ -122,8 +121,7 @@ constexpr int kLogBufSize = 3000; bool DoRawLog(char** buf, int* size, const char* format, ...) ABSL_PRINTF_ATTRIBUTE(3, 4); bool DoRawLog(char** buf, int* size, const char* format, ...) { - if (*size < 0) - return false; + if (*size < 0) return false; va_list ap; va_start(ap, format); int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap); @@ -242,8 +240,8 @@ void AsyncSignalSafeWriteError(const char* s, size_t len) { _write(/* stderr */ 2, s, static_cast<unsigned>(len)); #else // stderr logging unsupported on this platform - (void) s; - (void) len; + (void)s; + (void)len; #endif } @@ -258,7 +256,7 @@ void RawLog(absl::LogSeverity severity, const char* file, int line, bool RawLoggingFullySupported() { #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED return true; -#else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED +#else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED return false; #endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED } diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h index b79550b2b7..d7cfbc576b 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h @@ -108,6 +108,7 @@ #define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning #define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError #define ABSL_RAW_LOG_INTERNAL_FATAL ::absl::LogSeverity::kFatal +#define ABSL_RAW_LOG_INTERNAL_DFATAL ::absl::kLogDebugFatal #define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \ ::absl::NormalizeLogSeverity(severity) @@ -115,6 +116,7 @@ #define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_WARNING #define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_ERROR #define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_FATAL ABSL_UNREACHABLE() +#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_DFATAL #define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_LEVEL(severity) namespace absl { diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h index 09ba5824b1..2929cd6f5c 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h @@ -19,10 +19,10 @@ // - for use by Abseil internal code that Mutex itself depends on // - for async signal safety (see below) -// SpinLock is async signal safe. If a spinlock is used within a signal -// handler, all code that acquires the lock must ensure that the signal cannot -// arrive while they are holding the lock. Typically, this is done by blocking -// the signal. +// SpinLock with a base_internal::SchedulingMode::SCHEDULE_KERNEL_ONLY is async +// signal safe. If a spinlock is used within a signal handler, all code that +// acquires the lock must ensure that the signal cannot arrive while they are +// holding the lock. Typically, this is done by blocking the signal. // // Threads waiting on a SpinLock may be woken in an arbitrary order. @@ -41,6 +41,14 @@ #include "absl/base/internal/tsan_mutex_interface.h" #include "absl/base/thread_annotations.h" +namespace tcmalloc { +namespace tcmalloc_internal { + +class AllocationGuardSpinLockHolder; + +} // namespace tcmalloc_internal +} // namespace tcmalloc + namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { @@ -137,6 +145,7 @@ class ABSL_LOCKABLE SpinLock { // Provide access to protected method above. Use for testing only. friend struct SpinLockTest; + friend class tcmalloc::tcmalloc_internal::AllocationGuardSpinLockHolder; private: // lockword_ is used to store the following: @@ -171,6 +180,10 @@ class ABSL_LOCKABLE SpinLock { return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL; } + bool IsCooperative() const { + return lockword_.load(std::memory_order_relaxed) & kSpinLockCooperative; + } + uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles); void SlowLock() ABSL_ATTRIBUTE_COLD; void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD; diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h b/contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h deleted file mode 100644 index 8c5c67e0df..0000000000 --- a/contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2019 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: thread_annotations.h -// ----------------------------------------------------------------------------- -// -// WARNING: This is a backwards compatible header and it will be removed after -// the migration to prefixed thread annotations is finished; please include -// "absl/base/thread_annotations.h". -// -// This header file contains macro definitions for thread safety annotations -// that allow developers to document the locking policies of multi-threaded -// code. The annotations can also help program analysis tools to identify -// potential thread safety issues. -// -// These annotations are implemented using compiler attributes. Using the macros -// defined here instead of raw attributes allow for portability and future -// compatibility. -// -// When referring to mutexes in the arguments of the attributes, you should -// use variable names or more complex expressions (e.g. my_object->mutex_) -// that evaluate to a concrete mutex object whenever possible. If the mutex -// you want to refer to is not in scope, you may use a member pointer -// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object. - -#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_ -#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_ - -// ABSL_LEGACY_THREAD_ANNOTATIONS is a *temporary* compatibility macro that can -// be defined on the compile command-line to restore the legacy spellings of the -// thread annotations macros/functions. The macros in this file are available -// under ABSL_ prefixed spellings in absl/base/thread_annotations.h. This macro -// and the legacy spellings will be removed in the future. -#ifdef ABSL_LEGACY_THREAD_ANNOTATIONS - -#if defined(__clang__) -#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) -#else -#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op -#endif - -// GUARDED_BY() -// -// Documents if a shared field or global variable needs to be protected by a -// mutex. GUARDED_BY() allows the user to specify a particular mutex that -// should be held when accessing the annotated variable. -// -// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to -// local variables, a local variable and its associated mutex can often be -// combined into a small class or struct, thereby allowing the annotation. -// -// Example: -// -// class Foo { -// Mutex mu_; -// int p1_ GUARDED_BY(mu_); -// ... -// }; -#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) - -// PT_GUARDED_BY() -// -// Documents if the memory location pointed to by a pointer should be guarded -// by a mutex when dereferencing the pointer. -// -// Example: -// class Foo { -// Mutex mu_; -// int *p1_ PT_GUARDED_BY(mu_); -// ... -// }; -// -// Note that a pointer variable to a shared memory location could itself be a -// shared variable. -// -// Example: -// -// // `q_`, guarded by `mu1_`, points to a shared memory location that is -// // guarded by `mu2_`: -// int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_); -#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) - -// ACQUIRED_AFTER() / ACQUIRED_BEFORE() -// -// Documents the acquisition order between locks that can be held -// simultaneously by a thread. For any two locks that need to be annotated -// to establish an acquisition order, only one of them needs the annotation. -// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER -// and ACQUIRED_BEFORE.) -// -// As with GUARDED_BY, this is only applicable to mutexes that are shared -// fields or global variables. -// -// Example: -// -// Mutex m1_; -// Mutex m2_ ACQUIRED_AFTER(m1_); -#define ACQUIRED_AFTER(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) - -#define ACQUIRED_BEFORE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) - -// EXCLUSIVE_LOCKS_REQUIRED() / SHARED_LOCKS_REQUIRED() -// -// Documents a function that expects a mutex to be held prior to entry. -// The mutex is expected to be held both on entry to, and exit from, the -// function. -// -// An exclusive lock allows read-write access to the guarded data member(s), and -// only one thread can acquire a lock exclusively at any one time. A shared lock -// allows read-only access, and any number of threads can acquire a shared lock -// concurrently. -// -// Generally, non-const methods should be annotated with -// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with -// SHARED_LOCKS_REQUIRED. -// -// Example: -// -// Mutex mu1, mu2; -// int a GUARDED_BY(mu1); -// int b GUARDED_BY(mu2); -// -// void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... } -// void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... } -#define EXCLUSIVE_LOCKS_REQUIRED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) - -#define SHARED_LOCKS_REQUIRED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) - -// LOCKS_EXCLUDED() -// -// Documents the locks acquired in the body of the function. These locks -// cannot be held when calling this function (as Abseil's `Mutex` locks are -// non-reentrant). -#define LOCKS_EXCLUDED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -// LOCK_RETURNED() -// -// Documents a function that returns a mutex without acquiring it. For example, -// a public getter method that returns a pointer to a private mutex should -// be annotated with LOCK_RETURNED. -#define LOCK_RETURNED(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -// LOCKABLE -// -// Documents if a class/type is a lockable type (such as the `Mutex` class). -#define LOCKABLE \ - THREAD_ANNOTATION_ATTRIBUTE__(lockable) - -// SCOPED_LOCKABLE -// -// Documents if a class does RAII locking (such as the `MutexLock` class). -// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is -// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no -// arguments; the analysis will assume that the destructor unlocks whatever the -// constructor locked. -#define SCOPED_LOCKABLE \ - THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -// EXCLUSIVE_LOCK_FUNCTION() -// -// Documents functions that acquire a lock in the body of a function, and do -// not release it. -#define EXCLUSIVE_LOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) - -// SHARED_LOCK_FUNCTION() -// -// Documents functions that acquire a shared (reader) lock in the body of a -// function, and do not release it. -#define SHARED_LOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) - -// UNLOCK_FUNCTION() -// -// Documents functions that expect a lock to be held on entry to the function, -// and release it in the body of the function. -#define UNLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) - -// EXCLUSIVE_TRYLOCK_FUNCTION() / SHARED_TRYLOCK_FUNCTION() -// -// Documents functions that try to acquire a lock, and return success or failure -// (or a non-boolean value that can be interpreted as a boolean). -// The first argument should be `true` for functions that return `true` on -// success, or `false` for functions that return `false` on success. The second -// argument specifies the mutex that is locked on success. If unspecified, this -// mutex is assumed to be `this`. -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) - -#define SHARED_TRYLOCK_FUNCTION(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) - -// ASSERT_EXCLUSIVE_LOCK() / ASSERT_SHARED_LOCK() -// -// Documents functions that dynamically check to see if a lock is held, and fail -// if it is not held. -#define ASSERT_EXCLUSIVE_LOCK(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) - -#define ASSERT_SHARED_LOCK(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) - -// NO_THREAD_SAFETY_ANALYSIS -// -// Turns off thread safety checking within the body of a particular function. -// This annotation is used to mark functions that are known to be correct, but -// the locking behavior is more complicated than the analyzer can handle. -#define NO_THREAD_SAFETY_ANALYSIS \ - THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) - -//------------------------------------------------------------------------------ -// Tool-Supplied Annotations -//------------------------------------------------------------------------------ - -// TS_UNCHECKED should be placed around lock expressions that are not valid -// C++ syntax, but which are present for documentation purposes. These -// annotations will be ignored by the analysis. -#define TS_UNCHECKED(x) "" - -// TS_FIXME is used to mark lock expressions that are not valid C++ syntax. -// It is used by automated tools to mark and disable invalid expressions. -// The annotation should either be fixed, or changed to TS_UNCHECKED. -#define TS_FIXME(x) "" - -// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of -// a particular function. However, this attribute is used to mark functions -// that are incorrect and need to be fixed. It is used by automated tools to -// avoid breaking the build when the analysis is updated. -// Code owners are expected to eventually fix the routine. -#define NO_THREAD_SAFETY_ANALYSIS_FIXME NO_THREAD_SAFETY_ANALYSIS - -// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a GUARDED_BY -// annotation that needs to be fixed, because it is producing thread safety -// warning. It disables the GUARDED_BY. -#define GUARDED_BY_FIXME(x) - -// Disables warnings for a single read operation. This can be used to avoid -// warnings when it is known that the read is not actually involved in a race, -// but the compiler cannot confirm that. -#define TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x) - - -namespace thread_safety_analysis { - -// Takes a reference to a guarded data member, and returns an unguarded -// reference. -template <typename T> -inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS { - return v; -} - -template <typename T> -inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS { - return v; -} - -} // namespace thread_safety_analysis - -#endif // defined(ABSL_LEGACY_THREAD_ANNOTATIONS) - -#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_ diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.cc b/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.cc index 252443ebcd..0471a25dce 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.cc +++ b/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.cc @@ -16,8 +16,12 @@ #if !defined(_WIN32) || defined(__MINGW32__) #include <pthread.h> +#ifndef __wasi__ +// WASI does not provide this header, either way we disable use +// of signals with it below. #include <signal.h> #endif +#endif #include <atomic> #include <cassert> @@ -80,10 +84,12 @@ void SetCurrentThreadIdentity(ThreadIdentity* identity, absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey, reclaimer); -#if defined(__EMSCRIPTEN__) || defined(__MINGW32__) || defined(__hexagon__) - // Emscripten and MinGW pthread implementations does not support signals. - // See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html - // for more information. +#if defined(__wasi__) || defined(__EMSCRIPTEN__) || defined(__MINGW32__) || \ + defined(__hexagon__) + // Emscripten, WASI and MinGW pthread implementations does not support + // signals. See + // https://kripken.github.io/emscripten-site/docs/porting/pthreads.html for + // more information. pthread_setspecific(thread_identity_pthread_key, reinterpret_cast<void*>(identity)); #else diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/unaligned_access.h b/contrib/restricted/abseil-cpp/absl/base/internal/unaligned_access.h index 093dd9b499..4fea457491 100644 --- a/contrib/restricted/abseil-cpp/absl/base/internal/unaligned_access.h +++ b/contrib/restricted/abseil-cpp/absl/base/internal/unaligned_access.h @@ -23,6 +23,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/nullability.h" // unaligned APIs @@ -35,29 +36,35 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { -inline uint16_t UnalignedLoad16(const void *p) { +inline uint16_t UnalignedLoad16(absl::Nonnull<const void *> p) { uint16_t t; memcpy(&t, p, sizeof t); return t; } -inline uint32_t UnalignedLoad32(const void *p) { +inline uint32_t UnalignedLoad32(absl::Nonnull<const void *> p) { uint32_t t; memcpy(&t, p, sizeof t); return t; } -inline uint64_t UnalignedLoad64(const void *p) { +inline uint64_t UnalignedLoad64(absl::Nonnull<const void *> p) { uint64_t t; memcpy(&t, p, sizeof t); return t; } -inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); } +inline void UnalignedStore16(absl::Nonnull<void *> p, uint16_t v) { + memcpy(p, &v, sizeof v); +} -inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); } +inline void UnalignedStore32(absl::Nonnull<void *> p, uint32_t v) { + memcpy(p, &v, sizeof v); +} -inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); } +inline void UnalignedStore64(absl::Nonnull<void *> p, uint64_t v) { + memcpy(p, &v, sizeof v); +} } // namespace base_internal ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/base/log_severity.cc b/contrib/restricted/abseil-cpp/absl/base/log_severity.cc index 60a8fc1f89..8e7bbbc9e0 100644 --- a/contrib/restricted/abseil-cpp/absl/base/log_severity.cc +++ b/contrib/restricted/abseil-cpp/absl/base/log_severity.cc @@ -17,6 +17,7 @@ #include <ostream> #include "absl/base/attributes.h" +#include "absl/base/config.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/base/log_severity.h b/contrib/restricted/abseil-cpp/absl/base/log_severity.h index 8bdca38b5f..de9702ab68 100644 --- a/contrib/restricted/abseil-cpp/absl/base/log_severity.h +++ b/contrib/restricted/abseil-cpp/absl/base/log_severity.h @@ -64,6 +64,8 @@ ABSL_NAMESPACE_BEGIN // --my_log_level=info // --my_log_level=0 // +// `DFATAL` and `kLogDebugFatal` are similarly accepted. +// // Unparsing a flag produces the same result as `absl::LogSeverityName()` for // the standard levels and a base-ten integer otherwise. enum class LogSeverity : int { @@ -82,18 +84,28 @@ constexpr std::array<absl::LogSeverity, 4> LogSeverities() { absl::LogSeverity::kError, absl::LogSeverity::kFatal}}; } +// `absl::kLogDebugFatal` equals `absl::LogSeverity::kFatal` in debug builds +// (i.e. when `NDEBUG` is not defined) and `absl::LogSeverity::kError` +// otherwise. Avoid ODR-using this variable as it has internal linkage and thus +// distinct storage in different TUs. +#ifdef NDEBUG +static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kError; +#else +static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kFatal; +#endif + // LogSeverityName() // // Returns the all-caps string representation (e.g. "INFO") of the specified // severity level if it is one of the standard levels and "UNKNOWN" otherwise. constexpr const char* LogSeverityName(absl::LogSeverity s) { - return s == absl::LogSeverity::kInfo - ? "INFO" - : s == absl::LogSeverity::kWarning - ? "WARNING" - : s == absl::LogSeverity::kError - ? "ERROR" - : s == absl::LogSeverity::kFatal ? "FATAL" : "UNKNOWN"; + switch (s) { + case absl::LogSeverity::kInfo: return "INFO"; + case absl::LogSeverity::kWarning: return "WARNING"; + case absl::LogSeverity::kError: return "ERROR"; + case absl::LogSeverity::kFatal: return "FATAL"; + } + return "UNKNOWN"; } // NormalizeLogSeverity() @@ -101,9 +113,10 @@ constexpr const char* LogSeverityName(absl::LogSeverity s) { // Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal` // normalize to `kError` (**NOT** `kFatal`). constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) { - return s < absl::LogSeverity::kInfo - ? absl::LogSeverity::kInfo - : s > absl::LogSeverity::kFatal ? absl::LogSeverity::kError : s; + absl::LogSeverity n = s; + if (n < absl::LogSeverity::kInfo) n = absl::LogSeverity::kInfo; + if (n > absl::LogSeverity::kFatal) n = absl::LogSeverity::kError; + return n; } constexpr absl::LogSeverity NormalizeLogSeverity(int s) { return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s)); diff --git a/contrib/restricted/abseil-cpp/absl/base/no_destructor.h b/contrib/restricted/abseil-cpp/absl/base/no_destructor.h new file mode 100644 index 0000000000..d4b16a6e88 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/base/no_destructor.h @@ -0,0 +1,217 @@ +// Copyright 2023 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: no_destructor.h +// ----------------------------------------------------------------------------- +// +// This header file defines the absl::NoDestructor<T> wrapper for defining a +// static type that does not need to be destructed upon program exit. Instead, +// such an object survives during program exit (and can be safely accessed at +// any time). +// +// Objects of such type, if constructed safely and under the right conditions, +// provide two main benefits over other alternatives: +// +// * Global objects not normally allowed due to concerns of destruction order +// (i.e. no "complex globals") can be safely allowed, provided that such +// objects can be constant initialized. +// * Function scope static objects can be optimized to avoid heap allocation, +// pointer chasing, and allow lazy construction. +// +// See below for complete details. + + +#ifndef ABSL_BASE_NO_DESTRUCTOR_H_ +#define ABSL_BASE_NO_DESTRUCTOR_H_ + +#include <new> +#include <type_traits> +#include <utility> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// absl::NoDestructor<T> +// +// NoDestructor<T> is a wrapper around an object of type T that behaves as an +// object of type T but never calls T's destructor. NoDestructor<T> makes it +// safer and/or more efficient to use such objects in static storage contexts: +// as global or function scope static variables. +// +// An instance of absl::NoDestructor<T> has similar type semantics to an +// instance of T: +// +// * Constructs in the same manner as an object of type T through perfect +// forwarding. +// * Provides pointer/reference semantic access to the object of type T via +// `->`, `*`, and `get()`. +// (Note that `const NoDestructor<T>` works like a pointer to const `T`.) +// +// An object of type NoDestructor<T> should be defined in static storage: +// as either a global static object, or as a function scope static variable. +// +// Additionally, NoDestructor<T> provides the following benefits: +// +// * Never calls T's destructor for the object +// * If the object is a function-local static variable, the type can be +// lazily constructed. +// +// An object of type NoDestructor<T> is "trivially destructible" in the notion +// that its destructor is never run. Provided that an object of this type can be +// safely initialized and does not need to be cleaned up on program shutdown, +// NoDestructor<T> allows you to define global static variables, since Google's +// C++ style guide ban on such objects doesn't apply to objects that are +// trivially destructible. +// +// Usage as Global Static Variables +// +// NoDestructor<T> allows declaration of a global object with a non-trivial +// constructor in static storage without needing to add a destructor. +// However, such objects still need to worry about initialization order, so +// such objects should be const initialized: +// +// // Global or namespace scope. +// ABSL_CONST_INIT absl::NoDestructor<MyRegistry> reg{"foo", "bar", 8008}; +// +// Note that if your object already has a trivial destructor, you don't need to +// use NoDestructor<T>. +// +// Usage as Function Scope Static Variables +// +// Function static objects will be lazily initialized within static storage: +// +// // Function scope. +// const std::string& MyString() { +// static const absl::NoDestructor<std::string> x("foo"); +// return *x; +// } +// +// For function static variables, NoDestructor avoids heap allocation and can be +// inlined in static storage, resulting in exactly-once, thread-safe +// construction of an object, and very fast access thereafter (the cost is a few +// extra cycles). +// +// Using NoDestructor<T> in this manner is generally better than other patterns +// which require pointer chasing: +// +// // Prefer using absl::NoDestructor<T> instead for the static variable. +// const std::string& MyString() { +// static const std::string* x = new std::string("foo"); +// return *x; +// } +// +template <typename T> +class NoDestructor { + public: + // Forwards arguments to the T's constructor: calls T(args...). + template <typename... Ts, + // Disable this overload when it might collide with copy/move. + typename std::enable_if<!std::is_same<void(std::decay_t<Ts>&...), + void(NoDestructor&)>::value, + int>::type = 0> + explicit constexpr NoDestructor(Ts&&... args) + : impl_(std::forward<Ts>(args)...) {} + + // Forwards copy and move construction for T. Enables usage like this: + // static NoDestructor<std::array<string, 3>> x{{{"1", "2", "3"}}}; + // static NoDestructor<std::vector<int>> x{{1, 2, 3}}; + explicit constexpr NoDestructor(const T& x) : impl_(x) {} + explicit constexpr NoDestructor(T&& x) + : impl_(std::move(x)) {} + + // No copying. + NoDestructor(const NoDestructor&) = delete; + NoDestructor& operator=(const NoDestructor&) = delete; + + // Pretend to be a smart pointer to T with deep constness. + // Never returns a null pointer. + T& operator*() { return *get(); } + T* operator->() { return get(); } + T* get() { return impl_.get(); } + const T& operator*() const { return *get(); } + const T* operator->() const { return get(); } + const T* get() const { return impl_.get(); } + + private: + class DirectImpl { + public: + template <typename... Args> + explicit constexpr DirectImpl(Args&&... args) + : value_(std::forward<Args>(args)...) {} + const T* get() const { return &value_; } + T* get() { return &value_; } + + private: + T value_; + }; + + class PlacementImpl { + public: + template <typename... Args> + explicit PlacementImpl(Args&&... args) { + new (&space_) T(std::forward<Args>(args)...); + } + const T* get() const { + return Launder(reinterpret_cast<const T*>(&space_)); + } + T* get() { return Launder(reinterpret_cast<T*>(&space_)); } + + private: + template <typename P> + static P* Launder(P* p) { +#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L + return std::launder(p); +#elif ABSL_HAVE_BUILTIN(__builtin_launder) + return __builtin_launder(p); +#else + // When `std::launder` or equivalent are not available, we rely on + // undefined behavior, which works as intended on Abseil's officially + // supported platforms as of Q3 2023. +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + return p; +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif +#endif + } + + alignas(T) unsigned char space_[sizeof(T)]; + }; + + // If the object is trivially destructible we use a member directly to avoid + // potential once-init runtime initialization. It somewhat defeats the + // purpose of NoDestructor in this case, but this makes the class more + // friendly to generic code. + std::conditional_t<std::is_trivially_destructible<T>::value, DirectImpl, + PlacementImpl> + impl_; +}; + +#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION +// Provide 'Class Template Argument Deduction': the type of NoDestructor's T +// will be the same type as the argument passed to NoDestructor's constructor. +template <typename T> +NoDestructor(T) -> NoDestructor<T>; +#endif // ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_BASE_NO_DESTRUCTOR_H_ diff --git a/contrib/restricted/abseil-cpp/absl/base/nullability.h b/contrib/restricted/abseil-cpp/absl/base/nullability.h new file mode 100644 index 0000000000..6f49b6f535 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/base/nullability.h @@ -0,0 +1,224 @@ +// Copyright 2023 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: nullability.h +// ----------------------------------------------------------------------------- +// +// This header file defines a set of "templated annotations" for designating the +// expected nullability of pointers. These annotations allow you to designate +// pointers in one of three classification states: +// +// * "Non-null" (for pointers annotated `Nonnull<T>`), indicating that it is +// invalid for the given pointer to ever be null. +// * "Nullable" (for pointers annotated `Nullable<T>`), indicating that it is +// valid for the given pointer to be null. +// * "Unknown" (for pointers annotated `NullabilityUnknown<T>`), indicating +// that the given pointer has not been yet classified as either nullable or +// non-null. This is the default state of unannotated pointers. +// +// NOTE: unannotated pointers implicitly bear the annotation +// `NullabilityUnknown<T>`; you should rarely, if ever, see this annotation used +// in the codebase explicitly. +// +// ----------------------------------------------------------------------------- +// Nullability and Contracts +// ----------------------------------------------------------------------------- +// +// These nullability annotations allow you to more clearly specify contracts on +// software components by narrowing the *preconditions*, *postconditions*, and +// *invariants* of pointer state(s) in any given interface. It then depends on +// context who is responsible for fulfilling the annotation's requirements. +// +// For example, a function may receive a pointer argument. Designating that +// pointer argument as "non-null" tightens the precondition of the contract of +// that function. It is then the responsibility of anyone calling such a +// function to ensure that the passed pointer is not null. +// +// Similarly, a function may have a pointer as a return value. Designating that +// return value as "non-null" tightens the postcondition of the contract of that +// function. In this case, however, it is the responsibility of the function +// itself to ensure that the returned pointer is not null. +// +// Clearly defining these contracts allows providers (and consumers) of such +// pointers to have more confidence in their null state. If a function declares +// a return value as "non-null", for example, the caller should not need to +// check whether the returned value is `nullptr`; it can simply assume the +// pointer is valid. +// +// Of course most interfaces already have expectations on the nullability state +// of pointers, and these expectations are, in effect, a contract; often, +// however, those contracts are either poorly or partially specified, assumed, +// or misunderstood. These nullability annotations are designed to allow you to +// formalize those contracts within the codebase. +// +// ----------------------------------------------------------------------------- +// Using Nullability Annotations +// ----------------------------------------------------------------------------- +// +// It is important to note that these annotations are not distinct strong +// *types*. They are alias templates defined to be equal to the underlying +// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a +// pointer of type `T*`. Each annotation acts as a form of documentation about +// the contract for the given pointer. Each annotation requires providers or +// consumers of these pointers across API boundaries to take appropriate steps +// when setting or using these pointers: +// +// * "Non-null" pointers should never be null. It is the responsibility of the +// provider of this pointer to ensure that the pointer may never be set to +// null. Consumers of such pointers can treat such pointers as non-null. +// * "Nullable" pointers may or may not be null. Consumers of such pointers +// should precede any usage of that pointer (e.g. a dereference operation) +// with a a `nullptr` check. +// * "Unknown" pointers may be either "non-null" or "nullable" but have not been +// definitively determined to be in either classification state. Providers of +// such pointers across API boundaries should determine -- over time -- to +// annotate the pointer in either of the above two states. Consumers of such +// pointers across an API boundary should continue to treat such pointers as +// they currently do. +// +// Example: +// +// // PaySalary() requires the passed pointer to an `Employee` to be non-null. +// void PaySalary(absl::Nonnull<Employee *> e) { +// pay(e->salary); // OK to dereference +// } +// +// // CompleteTransaction() guarantees the returned pointer to an `Account` to +// // be non-null. +// absl::Nonnull<Account *> balance CompleteTransaction(double fee) { +// ... +// } +// +// // Note that specifying a nullability annotation does not prevent someone +// // from violating the contract: +// +// Nullable<Employee *> find(Map& employees, std::string_view name); +// +// void g(Map& employees) { +// Employee *e = find(employees, "Pat"); +// // `e` can now be null. +// PaySalary(e); // Violates contract, but compiles! +// } +// +// Nullability annotations, in other words, are useful for defining and +// narrowing contracts; *enforcement* of those contracts depends on use and any +// additional (static or dynamic analysis) tooling. +// +// NOTE: The "unknown" annotation state indicates that a pointer's contract has +// not yet been positively identified. The unknown state therefore acts as a +// form of documentation of your technical debt, and a codebase that adopts +// nullability annotations should aspire to annotate every pointer as either +// "non-null" or "nullable". +// +// ----------------------------------------------------------------------------- +// Applicability of Nullability Annotations +// ----------------------------------------------------------------------------- +// +// By default, nullability annotations are applicable to raw and smart +// pointers. User-defined types can indicate compatibility with nullability +// annotations by providing an `absl_nullability_compatible` nested type. The +// actual definition of this inner type is not relevant as it is used merely as +// a marker. It is common to use a using declaration of +// `absl_nullability_compatible` set to void. +// +// // Example: +// struct MyPtr { +// using absl_nullability_compatible = void; +// ... +// }; +// +// DISCLAIMER: +// =========================================================================== +// These nullability annotations are primarily a human readable signal about the +// intended contract of the pointer. They are not *types* and do not currently +// provide any correctness guarantees. For example, a pointer annotated as +// `Nonnull<T*>` is *not guaranteed* to be non-null, and the compiler won't +// alert or prevent assignment of a `Nullable<T*>` to a `Nonnull<T*>`. +// =========================================================================== +#ifndef ABSL_BASE_NULLABILITY_H_ +#define ABSL_BASE_NULLABILITY_H_ + +#include "absl/base/internal/nullability_impl.h" + +namespace absl { + +// absl::Nonnull +// +// The indicated pointer is never null. It is the responsibility of the provider +// of this pointer across an API boundary to ensure that the pointer is never be +// set to null. Consumers of this pointer across an API boundary may safely +// dereference the pointer. +// +// Example: +// +// // `employee` is designated as not null. +// void PaySalary(absl::Nonnull<Employee *> employee) { +// pay(*employee); // OK to dereference +// } +template <typename T> +using Nonnull = nullability_internal::NonnullImpl<T>; + +// absl::Nullable +// +// The indicated pointer may, by design, be either null or non-null. Consumers +// of this pointer across an API boundary should perform a `nullptr` check +// before performing any operation using the pointer. +// +// Example: +// +// // `employee` may be null. +// void PaySalary(absl::Nullable<Employee *> employee) { +// if (employee != nullptr) { +// Pay(*employee); // OK to dereference +// } +// } +template <typename T> +using Nullable = nullability_internal::NullableImpl<T>; + +// absl::NullabilityUnknown (default) +// +// The indicated pointer has not yet been determined to be definitively +// "non-null" or "nullable." Providers of such pointers across API boundaries +// should, over time, annotate such pointers as either "non-null" or "nullable." +// Consumers of these pointers across an API boundary should treat such pointers +// with the same caution they treat currently unannotated pointers. Most +// existing code will have "unknown" pointers, which should eventually be +// migrated into one of the above two nullability states: `Nonnull<T>` or +// `Nullable<T>`. +// +// NOTE: Because this annotation is the global default state, pointers without +// any annotation are assumed to have "unknown" semantics. This assumption is +// designed to minimize churn and reduce clutter within the codebase. +// +// Example: +// +// // `employee`s nullability state is unknown. +// void PaySalary(absl::NullabilityUnknown<Employee *> employee) { +// Pay(*employee); // Potentially dangerous. API provider should investigate. +// } +// +// Note that a pointer without an annotation, by default, is assumed to have the +// annotation `NullabilityUnknown`. +// +// // `employee`s nullability state is unknown. +// void PaySalary(Employee* employee) { +// Pay(*employee); // Potentially dangerous. API provider should investigate. +// } +template <typename T> +using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>; + +} // namespace absl + +#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 ad0121ad3b..f985995899 100644 --- a/contrib/restricted/abseil-cpp/absl/base/optimization.h +++ b/contrib/restricted/abseil-cpp/absl/base/optimization.h @@ -25,6 +25,7 @@ #include <assert.h> #include "absl/base/config.h" +#include "absl/base/options.h" // ABSL_BLOCK_TAIL_CALL_OPTIMIZATION // diff --git a/contrib/restricted/abseil-cpp/absl/base/options.h b/contrib/restricted/abseil-cpp/absl/base/options.h index f308e1bf8b..d7bf8cffe6 100644 --- a/contrib/restricted/abseil-cpp/absl/base/options.h +++ b/contrib/restricted/abseil-cpp/absl/base/options.h @@ -176,6 +176,32 @@ #define ABSL_OPTION_USE_STD_VARIANT 2 +// ABSL_OPTION_USE_STD_ORDERING +// +// This option controls whether absl::{partial,weak,strong}_ordering are +// implemented as aliases to the std:: ordering types, or as an independent +// implementation. +// +// A value of 0 means to use Abseil's implementation. This requires only C++11 +// support, and is expected to work on every toolchain we support. +// +// A value of 1 means to use aliases. This requires that all code using Abseil +// is built in C++20 mode or later. +// +// A value of 2 means to detect the C++ version being used to compile Abseil, +// and use an alias only if working std:: ordering types are available. This +// option is useful when you are building your program from source. It should +// not be used otherwise -- for example, if you are distributing Abseil in a +// binary package manager -- since in mode 2, they will name different types, +// with different mangled names and binary layout, depending on the compiler +// flags passed by the end user. For more info, see +// https://abseil.io/about/design/dropin-types. +// +// User code should not inspect this macro. To check in the preprocessor if +// the ordering types are aliases of std:: ordering types, use the feature macro +// ABSL_USES_STD_ORDERING. + +#define ABSL_OPTION_USE_STD_ORDERING 2 // ABSL_OPTION_USE_INLINE_NAMESPACE // ABSL_OPTION_INLINE_NAMESPACE_NAME @@ -200,7 +226,7 @@ // allowed. #define ABSL_OPTION_USE_INLINE_NAMESPACE 1 -#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20230802 +#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20240116 // ABSL_OPTION_HARDENED // diff --git a/contrib/restricted/abseil-cpp/absl/base/prefetch.h b/contrib/restricted/abseil-cpp/absl/base/prefetch.h index de7a180d60..eb40a4453c 100644 --- a/contrib/restricted/abseil-cpp/absl/base/prefetch.h +++ b/contrib/restricted/abseil-cpp/absl/base/prefetch.h @@ -24,17 +24,19 @@ #ifndef ABSL_BASE_PREFETCH_H_ #define ABSL_BASE_PREFETCH_H_ +#include "absl/base/attributes.h" #include "absl/base/config.h" #if defined(ABSL_INTERNAL_HAVE_SSE) #include <xmmintrin.h> #endif -#if defined(_MSC_VER) && _MSC_VER >= 1900 && \ - (defined(_M_X64) || defined(_M_IX86)) +#if defined(_MSC_VER) #include <intrin.h> +#if defined(ABSL_INTERNAL_HAVE_SSE) #pragma intrinsic(_mm_prefetch) #endif +#endif namespace absl { ABSL_NAMESPACE_BEGIN @@ -140,21 +142,24 @@ void PrefetchToLocalCacheForWrite(const void* addr); // See __builtin_prefetch: // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html. // -inline void PrefetchToLocalCache(const void* addr) { +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache( + const void* addr) { __builtin_prefetch(addr, 0, 3); } -inline void PrefetchToLocalCacheNta(const void* addr) { +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta( + const void* addr) { __builtin_prefetch(addr, 0, 0); } -inline void PrefetchToLocalCacheForWrite(const void* addr) { +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite( + const void* addr) { // [x86] gcc/clang don't generate PREFETCHW for __builtin_prefetch(.., 1) // unless -march=broadwell or newer; this is not generally the default, so we // manually emit prefetchw. PREFETCHW is recognized as a no-op on older Intel // processors and has been present on AMD processors since the K6-2. -#if defined(__x86_64__) - asm("prefetchw (%0)" : : "r"(addr)); +#if defined(__x86_64__) && !defined(__PRFCHW__) + asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr))); #else __builtin_prefetch(addr, 1, 3); #endif @@ -164,15 +169,18 @@ inline void PrefetchToLocalCacheForWrite(const void* addr) { #define ABSL_HAVE_PREFETCH 1 -inline void PrefetchToLocalCache(const void* addr) { +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache( + const void* addr) { _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0); } -inline void PrefetchToLocalCacheNta(const void* addr) { +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta( + const void* addr) { _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA); } -inline void PrefetchToLocalCacheForWrite(const void* addr) { +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite( + const void* addr) { #if defined(_MM_HINT_ET0) _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_ET0); #elif !defined(_MSC_VER) && defined(__x86_64__) @@ -180,15 +188,18 @@ inline void PrefetchToLocalCacheForWrite(const void* addr) { // up, PREFETCHW is recognized as a no-op on older Intel processors // and has been present on AMD processors since the K6-2. We have this // disabled for MSVC compilers as this miscompiles on older MSVC compilers. - asm("prefetchw (%0)" : : "r"(addr)); + asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr))); #endif } #else -inline void PrefetchToLocalCache(const void* addr) {} -inline void PrefetchToLocalCacheNta(const void* addr) {} -inline void PrefetchToLocalCacheForWrite(const void* addr) {} +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache( + const void* addr) {} +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta( + const void* addr) {} +ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite( + const void* addr) {} #endif diff --git a/contrib/restricted/abseil-cpp/absl/base/thread_annotations.h b/contrib/restricted/abseil-cpp/absl/base/thread_annotations.h index bc8a620347..4a3f3e33e9 100644 --- a/contrib/restricted/abseil-cpp/absl/base/thread_annotations.h +++ b/contrib/restricted/abseil-cpp/absl/base/thread_annotations.h @@ -36,8 +36,6 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" -// TODO(mbonadei): Remove after the backward compatibility period. -#include "absl/base/internal/thread_annotations.h" // IWYU pragma: export // ABSL_GUARDED_BY() // 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 8f4d993911..acd013b026 100644 --- a/contrib/restricted/abseil-cpp/absl/container/flat_hash_map.h +++ b/contrib/restricted/abseil-cpp/absl/container/flat_hash_map.h @@ -64,7 +64,7 @@ struct FlatHashMapPolicy; // `insert()`, provided that the map is provided a compatible heterogeneous // hashing function and equality operator. // * Invalidates any references and pointers to elements within the table after -// `rehash()`. +// `rehash()` and when the table is moved. // * Contains a `capacity()` member function indicating the number of element // slots (open, deleted, and empty) within the hash map. // * Returns `void` from the `erase(iterator)` overload. @@ -579,9 +579,9 @@ struct FlatHashMapPolicy { } template <class Allocator> - static void transfer(Allocator* alloc, slot_type* new_slot, + static auto transfer(Allocator* alloc, slot_type* new_slot, slot_type* old_slot) { - slot_policy::transfer(alloc, new_slot, old_slot); + return slot_policy::transfer(alloc, new_slot, old_slot); } template <class F, class... Args> 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 c789c7ef54..a94a82a0bf 100644 --- a/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h +++ b/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h @@ -60,7 +60,7 @@ struct FlatHashSetPolicy; // that the set is provided a compatible heterogeneous hashing function and // equality operator. // * Invalidates any references and pointers to elements within the table after -// `rehash()`. +// `rehash()` and when the table is moved. // * Contains a `capacity()` member function indicating the number of element // slots (open, deleted, and empty) within the hash set. // * Returns `void` from the `erase(iterator)` overload. 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 3558a5439b..57eac678fa 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 @@ -93,11 +93,13 @@ struct common_policy_traits { struct Rank0 : Rank1 {}; // Use auto -> decltype as an enabler. + // P::transfer returns std::true_type if transfer uses memcpy (e.g. in + // node_slot_policy). template <class Alloc, class P = Policy> static auto transfer_impl(Alloc* alloc, slot_type* new_slot, slot_type* old_slot, Rank0) - -> decltype((void)P::transfer(alloc, new_slot, old_slot)) { - P::transfer(alloc, new_slot, old_slot); + -> decltype(P::transfer(alloc, new_slot, old_slot)) { + return P::transfer(alloc, new_slot, old_slot); } #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 // This overload returns true_type for the trait below. 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 f59ca4ee22..3262d4eb8d 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h @@ -122,10 +122,10 @@ auto TupleRefImpl(T&& t, absl::index_sequence<Is...>) // Returns a tuple of references to the elements of the input tuple. T must be a // tuple. template <class T> -auto TupleRef(T&& t) -> decltype( - TupleRefImpl(std::forward<T>(t), - absl::make_index_sequence< - std::tuple_size<typename std::decay<T>::type>::value>())) { +auto TupleRef(T&& t) -> decltype(TupleRefImpl( + std::forward<T>(t), + absl::make_index_sequence< + std::tuple_size<typename std::decay<T>::type>::value>())) { return TupleRefImpl( std::forward<T>(t), absl::make_index_sequence< @@ -156,8 +156,8 @@ void ConstructFromTuple(Alloc* alloc, T* ptr, Tuple&& t) { // Constructs T using the args specified in the tuple and calls F with the // constructed value. template <class T, class Tuple, class F> -decltype(std::declval<F>()(std::declval<T>())) WithConstructed( - Tuple&& t, F&& f) { +decltype(std::declval<F>()(std::declval<T>())) WithConstructed(Tuple&& t, + F&& f) { return memory_internal::WithConstructedImpl<T>( std::forward<Tuple>(t), absl::make_index_sequence< @@ -423,16 +423,19 @@ struct map_slot_policy { } template <class Allocator> - static void transfer(Allocator* alloc, slot_type* new_slot, + static auto transfer(Allocator* alloc, slot_type* new_slot, slot_type* old_slot) { + auto is_relocatable = + typename absl::is_trivially_relocatable<value_type>::type(); + emplace(new_slot); #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 - if (absl::is_trivially_relocatable<value_type>()) { + if (is_relocatable) { // TODO(b/247130232,b/251814870): remove casts after fixing warnings. std::memcpy(static_cast<void*>(std::launder(&new_slot->value)), static_cast<const void*>(&old_slot->value), sizeof(value_type)); - return; + return is_relocatable; } #endif @@ -444,6 +447,7 @@ struct map_slot_policy { std::move(old_slot->value)); } destroy(alloc, old_slot); + return is_relocatable; } }; diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h b/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h index d8fd8f34f9..e41ee2d747 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h @@ -137,18 +137,7 @@ class HashtablezInfoHandle { UnsampleSlow(info_); } - HashtablezInfoHandle(const HashtablezInfoHandle&) = delete; - HashtablezInfoHandle& operator=(const HashtablezInfoHandle&) = delete; - - HashtablezInfoHandle(HashtablezInfoHandle&& o) noexcept - : info_(absl::exchange(o.info_, nullptr)) {} - HashtablezInfoHandle& operator=(HashtablezInfoHandle&& o) noexcept { - if (ABSL_PREDICT_FALSE(info_ != nullptr)) { - UnsampleSlow(info_); - } - info_ = absl::exchange(o.info_, nullptr); - return *this; - } + inline bool IsSampled() const { return ABSL_PREDICT_FALSE(info_ != nullptr); } inline void RecordStorageChanged(size_t size, size_t capacity) { if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; @@ -198,6 +187,7 @@ class HashtablezInfoHandle { explicit HashtablezInfoHandle(std::nullptr_t) {} inline void Unregister() {} + inline bool IsSampled() const { return false; } inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {} inline void RecordRehash(size_t /*total_probe_length*/) {} inline void RecordReservation(size_t /*target_capacity*/) {} 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 b2a602db7e..0eb9c34ddd 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h @@ -26,6 +26,7 @@ #include <utility> #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/container/internal/compressed_tuple.h" #include "absl/memory/memory.h" @@ -384,7 +385,17 @@ class Storage { bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; } - Pointer<A> GetAllocatedData() { return data_.allocated.allocated_data; } + Pointer<A> GetAllocatedData() { + // GCC 12 has a false-positive -Wmaybe-uninitialized warning here. +#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + return data_.allocated.allocated_data; +#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0) +#pragma GCC diagnostic pop +#endif + } ConstPointer<A> GetAllocatedData() const { return data_.allocated.allocated_data; diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/layout.h b/contrib/restricted/abseil-cpp/absl/container/internal/layout.h deleted file mode 100644 index a59a243059..0000000000 --- a/contrib/restricted/abseil-cpp/absl/container/internal/layout.h +++ /dev/null @@ -1,743 +0,0 @@ -// Copyright 2018 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. -// -// MOTIVATION AND TUTORIAL -// -// If you want to put in a single heap allocation N doubles followed by M ints, -// it's easy if N and M are known at compile time. -// -// struct S { -// double a[N]; -// int b[M]; -// }; -// -// S* p = new S; -// -// But what if N and M are known only in run time? Class template Layout to the -// rescue! It's a portable generalization of the technique known as struct hack. -// -// // This object will tell us everything we need to know about the memory -// // layout of double[N] followed by int[M]. It's structurally identical to -// // size_t[2] that stores N and M. It's very cheap to create. -// const Layout<double, int> layout(N, M); -// -// // Allocate enough memory for both arrays. `AllocSize()` tells us how much -// // memory is needed. We are free to use any allocation function we want as -// // long as it returns aligned memory. -// std::unique_ptr<unsigned char[]> p(new unsigned char[layout.AllocSize()]); -// -// // Obtain the pointer to the array of doubles. -// // Equivalent to `reinterpret_cast<double*>(p.get())`. -// // -// // We could have written layout.Pointer<0>(p) instead. If all the types are -// // unique you can use either form, but if some types are repeated you must -// // use the index form. -// double* a = layout.Pointer<double>(p.get()); -// -// // Obtain the pointer to the array of ints. -// // Equivalent to `reinterpret_cast<int*>(p.get() + N * 8)`. -// int* b = layout.Pointer<int>(p); -// -// If we are unable to specify sizes of all fields, we can pass as many sizes as -// we can to `Partial()`. In return, it'll allow us to access the fields whose -// locations and sizes can be computed from the provided information. -// `Partial()` comes in handy when the array sizes are embedded into the -// allocation. -// -// // size_t[1] containing N, size_t[1] containing M, double[N], int[M]. -// using L = Layout<size_t, size_t, double, int>; -// -// unsigned char* Allocate(size_t n, size_t m) { -// const L layout(1, 1, n, m); -// unsigned char* p = new unsigned char[layout.AllocSize()]; -// *layout.Pointer<0>(p) = n; -// *layout.Pointer<1>(p) = m; -// return p; -// } -// -// void Use(unsigned char* p) { -// // First, extract N and M. -// // Specify that the first array has only one element. Using `prefix` we -// // can access the first two arrays but not more. -// constexpr auto prefix = L::Partial(1); -// size_t n = *prefix.Pointer<0>(p); -// size_t m = *prefix.Pointer<1>(p); -// -// // Now we can get pointers to the payload. -// const L layout(1, 1, n, m); -// double* a = layout.Pointer<double>(p); -// int* b = layout.Pointer<int>(p); -// } -// -// The layout we used above combines fixed-size with dynamically-sized fields. -// This is quite common. Layout is optimized for this use case and generates -// optimal code. All computations that can be performed at compile time are -// indeed performed at compile time. -// -// Efficiency tip: The order of fields matters. In `Layout<T1, ..., TN>` try to -// ensure that `alignof(T1) >= ... >= alignof(TN)`. This way you'll have no -// padding in between arrays. -// -// You can manually override the alignment of an array by wrapping the type in -// `Aligned<T, N>`. `Layout<..., Aligned<T, N>, ...>` has exactly the same API -// and behavior as `Layout<..., T, ...>` except that the first element of the -// array of `T` is aligned to `N` (the rest of the elements follow without -// padding). `N` cannot be less than `alignof(T)`. -// -// `AllocSize()` and `Pointer()` are the most basic methods for dealing with -// memory layouts. Check out the reference or code below to discover more. -// -// EXAMPLE -// -// // Immutable move-only string with sizeof equal to sizeof(void*). The -// // string size and the characters are kept in the same heap allocation. -// class CompactString { -// public: -// CompactString(const char* s = "") { -// const size_t size = strlen(s); -// // size_t[1] followed by char[size + 1]. -// const L layout(1, size + 1); -// p_.reset(new unsigned char[layout.AllocSize()]); -// // If running under ASAN, mark the padding bytes, if any, to catch -// // memory errors. -// layout.PoisonPadding(p_.get()); -// // Store the size in the allocation. -// *layout.Pointer<size_t>(p_.get()) = size; -// // Store the characters in the allocation. -// memcpy(layout.Pointer<char>(p_.get()), s, size + 1); -// } -// -// size_t size() const { -// // Equivalent to reinterpret_cast<size_t&>(*p). -// return *L::Partial().Pointer<size_t>(p_.get()); -// } -// -// const char* c_str() const { -// // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)). -// // The argument in Partial(1) specifies that we have size_t[1] in front -// // of the characters. -// return L::Partial(1).Pointer<char>(p_.get()); -// } -// -// private: -// // Our heap allocation contains a size_t followed by an array of chars. -// using L = Layout<size_t, char>; -// std::unique_ptr<unsigned char[]> p_; -// }; -// -// int main() { -// CompactString s = "hello"; -// assert(s.size() == 5); -// assert(strcmp(s.c_str(), "hello") == 0); -// } -// -// DOCUMENTATION -// -// The interface exported by this file consists of: -// - class `Layout<>` and its public members. -// - The public members of class `internal_layout::LayoutImpl<>`. That class -// isn't intended to be used directly, and its name and template parameter -// list are internal implementation details, but the class itself provides -// most of the functionality in this file. See comments on its members for -// detailed documentation. -// -// `Layout<T1,... Tn>::Partial(count1,..., countm)` (where `m` <= `n`) returns a -// `LayoutImpl<>` object. `Layout<T1,..., Tn> layout(count1,..., countn)` -// creates a `Layout` object, which exposes the same functionality by inheriting -// from `LayoutImpl<>`. - -#ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_ -#define ABSL_CONTAINER_INTERNAL_LAYOUT_H_ - -#include <assert.h> -#include <stddef.h> -#include <stdint.h> - -#include <ostream> -#include <string> -#include <tuple> -#include <type_traits> -#include <typeinfo> -#include <utility> - -#include "absl/base/config.h" -#include "absl/meta/type_traits.h" -#include "absl/strings/str_cat.h" -#include "absl/types/span.h" -#include "absl/utility/utility.h" - -#ifdef ABSL_HAVE_ADDRESS_SANITIZER -#include <sanitizer/asan_interface.h> -#endif - -#if defined(__GXX_RTTI) -#define ABSL_INTERNAL_HAS_CXA_DEMANGLE -#endif - -#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE -#include <cxxabi.h> -#endif - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace container_internal { - -// A type wrapper that instructs `Layout` to use the specific alignment for the -// array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API -// and behavior as `Layout<..., T, ...>` except that the first element of the -// array of `T` is aligned to `N` (the rest of the elements follow without -// padding). -// -// Requires: `N >= alignof(T)` and `N` is a power of 2. -template <class T, size_t N> -struct Aligned; - -namespace internal_layout { - -template <class T> -struct NotAligned {}; - -template <class T, size_t N> -struct NotAligned<const Aligned<T, N>> { - static_assert(sizeof(T) == 0, "Aligned<T, N> cannot be const-qualified"); -}; - -template <size_t> -using IntToSize = size_t; - -template <class> -using TypeToSize = size_t; - -template <class T> -struct Type : NotAligned<T> { - using type = T; -}; - -template <class T, size_t N> -struct Type<Aligned<T, N>> { - using type = T; -}; - -template <class T> -struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {}; - -template <class T, size_t N> -struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {}; - -// Note: workaround for https://gcc.gnu.org/PR88115 -template <class T> -struct AlignOf : NotAligned<T> { - static constexpr size_t value = alignof(T); -}; - -template <class T, size_t N> -struct AlignOf<Aligned<T, N>> { - static_assert(N % alignof(T) == 0, - "Custom alignment can't be lower than the type's alignment"); - static constexpr size_t value = N; -}; - -// Does `Ts...` contain `T`? -template <class T, class... Ts> -using Contains = absl::disjunction<std::is_same<T, Ts>...>; - -template <class From, class To> -using CopyConst = - typename std::conditional<std::is_const<From>::value, const To, To>::type; - -// Note: We're not qualifying this with absl:: because it doesn't compile under -// MSVC. -template <class T> -using SliceType = Span<T>; - -// This namespace contains no types. It prevents functions defined in it from -// being found by ADL. -namespace adl_barrier { - -template <class Needle, class... Ts> -constexpr size_t Find(Needle, Needle, Ts...) { - static_assert(!Contains<Needle, Ts...>(), "Duplicate element type"); - return 0; -} - -template <class Needle, class T, class... Ts> -constexpr size_t Find(Needle, T, Ts...) { - return adl_barrier::Find(Needle(), Ts()...) + 1; -} - -constexpr bool IsPow2(size_t n) { return !(n & (n - 1)); } - -// Returns `q * m` for the smallest `q` such that `q * m >= n`. -// Requires: `m` is a power of two. It's enforced by IsLegalElementType below. -constexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); } - -constexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; } - -constexpr size_t Max(size_t a) { return a; } - -template <class... Ts> -constexpr size_t Max(size_t a, size_t b, Ts... rest) { - return adl_barrier::Max(b < a ? a : b, rest...); -} - -template <class T> -std::string TypeName() { - std::string out; - int status = 0; - char* demangled = nullptr; -#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE - demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status); -#endif - if (status == 0 && demangled != nullptr) { // Demangling succeeded. - absl::StrAppend(&out, "<", demangled, ">"); - free(demangled); - } else { -#if defined(__GXX_RTTI) || defined(_CPPRTTI) - absl::StrAppend(&out, "<", typeid(T).name(), ">"); -#endif - } - return out; -} - -} // namespace adl_barrier - -template <bool C> -using EnableIf = typename std::enable_if<C, int>::type; - -// Can `T` be a template argument of `Layout`? -template <class T> -using IsLegalElementType = std::integral_constant< - bool, !std::is_reference<T>::value && !std::is_volatile<T>::value && - !std::is_reference<typename Type<T>::type>::value && - !std::is_volatile<typename Type<T>::type>::value && - adl_barrier::IsPow2(AlignOf<T>::value)>; - -template <class Elements, class SizeSeq, class OffsetSeq> -class LayoutImpl; - -// Public base class of `Layout` and the result type of `Layout::Partial()`. -// -// `Elements...` contains all template arguments of `Layout` that created this -// instance. -// -// `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is the number of arguments -// passed to `Layout::Partial()` or `Layout::Layout()`. -// -// `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is -// `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we -// can compute offsets). -template <class... Elements, size_t... SizeSeq, size_t... OffsetSeq> -class LayoutImpl<std::tuple<Elements...>, absl::index_sequence<SizeSeq...>, - absl::index_sequence<OffsetSeq...>> { - private: - static_assert(sizeof...(Elements) > 0, "At least one field is required"); - static_assert(absl::conjunction<IsLegalElementType<Elements>...>::value, - "Invalid element type (see IsLegalElementType)"); - - enum { - NumTypes = sizeof...(Elements), - NumSizes = sizeof...(SizeSeq), - NumOffsets = sizeof...(OffsetSeq), - }; - - // These are guaranteed by `Layout`. - static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1), - "Internal error"); - static_assert(NumTypes > 0, "Internal error"); - - // Returns the index of `T` in `Elements...`. Results in a compilation error - // if `Elements...` doesn't contain exactly one instance of `T`. - template <class T> - static constexpr size_t ElementIndex() { - static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(), - "Type not found"); - return adl_barrier::Find(Type<T>(), - Type<typename Type<Elements>::type>()...); - } - - template <size_t N> - using ElementAlignment = - AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>; - - public: - // Element types of all arrays packed in a tuple. - using ElementTypes = std::tuple<typename Type<Elements>::type...>; - - // Element type of the Nth array. - template <size_t N> - using ElementType = typename std::tuple_element<N, ElementTypes>::type; - - constexpr explicit LayoutImpl(IntToSize<SizeSeq>... sizes) - : size_{sizes...} {} - - // Alignment of the layout, equal to the strictest alignment of all elements. - // All pointers passed to the methods of layout must be aligned to this value. - static constexpr size_t Alignment() { - return adl_barrier::Max(AlignOf<Elements>::value...); - } - - // Offset in bytes of the Nth array. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Offset<0>() == 0); // The ints starts from 0. - // assert(x.Offset<1>() == 16); // The doubles starts from 16. - // - // Requires: `N <= NumSizes && N < sizeof...(Ts)`. - template <size_t N, EnableIf<N == 0> = 0> - constexpr size_t Offset() const { - return 0; - } - - template <size_t N, EnableIf<N != 0> = 0> - constexpr size_t Offset() const { - static_assert(N < NumOffsets, "Index out of bounds"); - return adl_barrier::Align( - Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * size_[N - 1], - ElementAlignment<N>::value); - } - - // Offset in bytes of the array with the specified element type. There must - // be exactly one such array and its zero-based index must be at most - // `NumSizes`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Offset<int>() == 0); // The ints starts from 0. - // assert(x.Offset<double>() == 16); // The doubles starts from 16. - template <class T> - constexpr size_t Offset() const { - return Offset<ElementIndex<T>()>(); - } - - // Offsets in bytes of all arrays for which the offsets are known. - constexpr std::array<size_t, NumOffsets> Offsets() const { - return {{Offset<OffsetSeq>()...}}; - } - - // The number of elements in the Nth array. This is the Nth argument of - // `Layout::Partial()` or `Layout::Layout()` (zero-based). - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Size<0>() == 3); - // assert(x.Size<1>() == 4); - // - // Requires: `N < NumSizes`. - template <size_t N> - constexpr size_t Size() const { - static_assert(N < NumSizes, "Index out of bounds"); - return size_[N]; - } - - // The number of elements in the array with the specified element type. - // There must be exactly one such array and its zero-based index must be - // at most `NumSizes`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // assert(x.Size<int>() == 3); - // assert(x.Size<double>() == 4); - template <class T> - constexpr size_t Size() const { - return Size<ElementIndex<T>()>(); - } - - // The number of elements of all arrays for which they are known. - constexpr std::array<size_t, NumSizes> Sizes() const { - return {{Size<SizeSeq>()...}}; - } - - // Pointer to the beginning of the Nth array. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // int* ints = x.Pointer<0>(p); - // double* doubles = x.Pointer<1>(p); - // - // Requires: `N <= NumSizes && N < sizeof...(Ts)`. - // Requires: `p` is aligned to `Alignment()`. - template <size_t N, class Char> - CopyConst<Char, ElementType<N>>* Pointer(Char* p) const { - using C = typename std::remove_const<Char>::type; - static_assert( - std::is_same<C, char>() || std::is_same<C, unsigned char>() || - std::is_same<C, signed char>(), - "The argument must be a pointer to [const] [signed|unsigned] char"); - constexpr size_t alignment = Alignment(); - (void)alignment; - assert(reinterpret_cast<uintptr_t>(p) % alignment == 0); - return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>()); - } - - // Pointer to the beginning of the array with the specified element type. - // There must be exactly one such array and its zero-based index must be at - // most `NumSizes`. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // int* ints = x.Pointer<int>(p); - // double* doubles = x.Pointer<double>(p); - // - // Requires: `p` is aligned to `Alignment()`. - template <class T, class Char> - CopyConst<Char, T>* Pointer(Char* p) const { - return Pointer<ElementIndex<T>()>(p); - } - - // Pointers to all arrays for which pointers are known. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // - // int* ints; - // double* doubles; - // std::tie(ints, doubles) = x.Pointers(p); - // - // Requires: `p` is aligned to `Alignment()`. - // - // Note: We're not using ElementType alias here because it does not compile - // under MSVC. - template <class Char> - std::tuple<CopyConst< - Char, typename std::tuple_element<OffsetSeq, ElementTypes>::type>*...> - Pointers(Char* p) const { - return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>( - Pointer<OffsetSeq>(p)...); - } - - // The Nth array. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // Span<int> ints = x.Slice<0>(p); - // Span<double> doubles = x.Slice<1>(p); - // - // Requires: `N < NumSizes`. - // Requires: `p` is aligned to `Alignment()`. - template <size_t N, class Char> - SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p) const { - return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>()); - } - - // The array with the specified element type. There must be exactly one - // such array and its zero-based index must be less than `NumSizes`. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // Span<int> ints = x.Slice<int>(p); - // Span<double> doubles = x.Slice<double>(p); - // - // Requires: `p` is aligned to `Alignment()`. - template <class T, class Char> - SliceType<CopyConst<Char, T>> Slice(Char* p) const { - return Slice<ElementIndex<T>()>(p); - } - - // All arrays with known sizes. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; - // - // Span<int> ints; - // Span<double> doubles; - // std::tie(ints, doubles) = x.Slices(p); - // - // Requires: `p` is aligned to `Alignment()`. - // - // Note: We're not using ElementType alias here because it does not compile - // under MSVC. - template <class Char> - std::tuple<SliceType<CopyConst< - Char, typename std::tuple_element<SizeSeq, ElementTypes>::type>>...> - Slices(Char* p) const { - // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63875 (fixed - // in 6.1). - (void)p; - return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>( - Slice<SizeSeq>(p)...); - } - - // The size of the allocation that fits all arrays. - // - // // int[3], 4 bytes of padding, double[4]. - // Layout<int, double> x(3, 4); - // unsigned char* p = new unsigned char[x.AllocSize()]; // 48 bytes - // - // Requires: `NumSizes == sizeof...(Ts)`. - constexpr size_t AllocSize() const { - static_assert(NumTypes == NumSizes, "You must specify sizes of all fields"); - return Offset<NumTypes - 1>() + - SizeOf<ElementType<NumTypes - 1>>::value * size_[NumTypes - 1]; - } - - // If built with --config=asan, poisons padding bytes (if any) in the - // allocation. The pointer must point to a memory block at least - // `AllocSize()` bytes in length. - // - // `Char` must be `[const] [signed|unsigned] char`. - // - // Requires: `p` is aligned to `Alignment()`. - template <class Char, size_t N = NumOffsets - 1, EnableIf<N == 0> = 0> - void PoisonPadding(const Char* p) const { - Pointer<0>(p); // verify the requirements on `Char` and `p` - } - - template <class Char, size_t N = NumOffsets - 1, EnableIf<N != 0> = 0> - void PoisonPadding(const Char* p) const { - static_assert(N < NumOffsets, "Index out of bounds"); - (void)p; -#ifdef ABSL_HAVE_ADDRESS_SANITIZER - PoisonPadding<Char, N - 1>(p); - // The `if` is an optimization. It doesn't affect the observable behaviour. - if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) { - size_t start = - Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * size_[N - 1]; - ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start); - } -#endif - } - - // Human-readable description of the memory layout. Useful for debugging. - // Slow. - // - // // char[5], 3 bytes of padding, int[3], 4 bytes of padding, followed - // // by an unknown number of doubles. - // auto x = Layout<char, int, double>::Partial(5, 3); - // assert(x.DebugString() == - // "@0<char>(1)[5]; @8<int>(4)[3]; @24<double>(8)"); - // - // Each field is in the following format: @offset<type>(sizeof)[size] (<type> - // may be missing depending on the target platform). For example, - // @8<int>(4)[3] means that at offset 8 we have an array of ints, where each - // int is 4 bytes, and we have 3 of those ints. The size of the last field may - // be missing (as in the example above). Only fields with known offsets are - // described. Type names may differ across platforms: one compiler might - // produce "unsigned*" where another produces "unsigned int *". - std::string DebugString() const { - const auto offsets = Offsets(); - const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>::value...}; - const std::string types[] = { - adl_barrier::TypeName<ElementType<OffsetSeq>>()...}; - std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")"); - for (size_t i = 0; i != NumOffsets - 1; ++i) { - absl::StrAppend(&res, "[", size_[i], "]; @", offsets[i + 1], types[i + 1], - "(", sizes[i + 1], ")"); - } - // NumSizes is a constant that may be zero. Some compilers cannot see that - // inside the if statement "size_[NumSizes - 1]" must be valid. - int last = static_cast<int>(NumSizes) - 1; - if (NumTypes == NumSizes && last >= 0) { - absl::StrAppend(&res, "[", size_[last], "]"); - } - return res; - } - - private: - // Arguments of `Layout::Partial()` or `Layout::Layout()`. - size_t size_[NumSizes > 0 ? NumSizes : 1]; -}; - -template <size_t NumSizes, class... Ts> -using LayoutType = LayoutImpl< - std::tuple<Ts...>, absl::make_index_sequence<NumSizes>, - absl::make_index_sequence<adl_barrier::Min(sizeof...(Ts), NumSizes + 1)>>; - -} // namespace internal_layout - -// Descriptor of arrays of various types and sizes laid out in memory one after -// another. See the top of the file for documentation. -// -// Check out the public API of internal_layout::LayoutImpl above. The type is -// internal to the library but its methods are public, and they are inherited -// by `Layout`. -template <class... Ts> -class Layout : public internal_layout::LayoutType<sizeof...(Ts), Ts...> { - public: - static_assert(sizeof...(Ts) > 0, "At least one field is required"); - static_assert( - absl::conjunction<internal_layout::IsLegalElementType<Ts>...>::value, - "Invalid element type (see IsLegalElementType)"); - - // The result type of `Partial()` with `NumSizes` arguments. - template <size_t NumSizes> - using PartialType = internal_layout::LayoutType<NumSizes, Ts...>; - - // `Layout` knows the element types of the arrays we want to lay out in - // memory but not the number of elements in each array. - // `Partial(size1, ..., sizeN)` allows us to specify the latter. The - // resulting immutable object can be used to obtain pointers to the - // individual arrays. - // - // It's allowed to pass fewer array sizes than the number of arrays. E.g., - // if all you need is to the offset of the second array, you only need to - // pass one argument -- the number of elements in the first array. - // - // // int[3] followed by 4 bytes of padding and an unknown number of - // // doubles. - // auto x = Layout<int, double>::Partial(3); - // // doubles start at byte 16. - // assert(x.Offset<1>() == 16); - // - // If you know the number of elements in all arrays, you can still call - // `Partial()` but it's more convenient to use the constructor of `Layout`. - // - // Layout<int, double> x(3, 5); - // - // Note: The sizes of the arrays must be specified in number of elements, - // not in bytes. - // - // Requires: `sizeof...(Sizes) <= sizeof...(Ts)`. - // Requires: all arguments are convertible to `size_t`. - template <class... Sizes> - static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) { - static_assert(sizeof...(Sizes) <= sizeof...(Ts), ""); - return PartialType<sizeof...(Sizes)>(absl::forward<Sizes>(sizes)...); - } - - // Creates a layout with the sizes of all arrays specified. If you know - // only the sizes of the first N arrays (where N can be zero), you can use - // `Partial()` defined above. The constructor is essentially equivalent to - // calling `Partial()` and passing in all array sizes; the constructor is - // provided as a convenient abbreviation. - // - // Note: The sizes of the arrays must be specified in number of elements, - // not in bytes. - constexpr explicit Layout(internal_layout::TypeToSize<Ts>... sizes) - : internal_layout::LayoutType<sizeof...(Ts), Ts...>(sizes...) {} -}; - -} // namespace container_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_ diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_map.h b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_map.h index 2d5a8710ad..97182bc7bd 100644 --- a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_map.h +++ b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_map.h @@ -19,6 +19,8 @@ #include <type_traits> #include <utility> +#include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/throw_delegate.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export @@ -175,13 +177,20 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> { template <class K = key_type, class P = Policy, K* = nullptr> MappedReference<P> operator[](key_arg<K>&& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { - return Policy::value(&*try_emplace(std::forward<K>(key)).first); + // It is safe to use unchecked_deref here because try_emplace + // will always return an iterator pointing to a valid item in the table, + // since it inserts if nothing is found for the given key. + return Policy::value( + &this->unchecked_deref(try_emplace(std::forward<K>(key)).first)); } template <class K = key_type, class P = Policy> MappedReference<P> operator[](const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { - return Policy::value(&*try_emplace(key).first); + // It is safe to use unchecked_deref here because try_emplace + // will always return an iterator pointing to a valid item in the table, + // since it inserts if nothing is found for the given key. + return Policy::value(&this->unchecked_deref(try_emplace(key).first)); } private: 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 2ff95b6182..9f8ea51987 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 @@ -17,11 +17,13 @@ #include <atomic> #include <cassert> #include <cstddef> +#include <cstdint> #include <cstring> #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" +#include "absl/container/internal/container_memory.h" #include "absl/hash/hash.h" namespace absl { @@ -67,6 +69,16 @@ inline size_t RandomSeed() { return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter)); } +bool ShouldRehashForBugDetection(const ctrl_t* ctrl, size_t capacity) { + // Note: we can't use the abseil-random library because abseil-random + // depends on swisstable. We want to return true with probability + // `min(1, RehashProbabilityConstant() / capacity())`. In order to do this, + // we probe based on a random hash and see if the offset is less than + // RehashProbabilityConstant(). + return probe(ctrl, capacity, absl::HashOf(RandomSeed())).offset() < + RehashProbabilityConstant(); +} + } // namespace GenerationType* EmptyGeneration() { @@ -84,13 +96,12 @@ bool CommonFieldsGenerationInfoEnabled:: size_t capacity) const { if (reserved_growth_ == kReservedGrowthJustRanOut) return true; if (reserved_growth_ > 0) return false; - // Note: we can't use the abseil-random library because abseil-random - // depends on swisstable. We want to return true with probability - // `min(1, RehashProbabilityConstant() / capacity())`. In order to do this, - // we probe based on a random hash and see if the offset is less than - // RehashProbabilityConstant(). - return probe(ctrl, capacity, absl::HashOf(RandomSeed())).offset() < - RehashProbabilityConstant(); + return ShouldRehashForBugDetection(ctrl, capacity); +} + +bool CommonFieldsGenerationInfoEnabled::should_rehash_for_bug_detection_on_move( + const ctrl_t* ctrl, size_t capacity) const { + return ShouldRehashForBugDetection(ctrl, capacity); } bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl) { @@ -117,14 +128,6 @@ FindInfo find_first_non_full_outofline(const CommonFields& common, return find_first_non_full(common, hash); } -// Returns the address of the ith slot in slots where each slot occupies -// slot_size. -static inline void* SlotAddress(void* slot_array, size_t slot, - size_t slot_size) { - return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot_array) + - (slot * slot_size)); -} - // Returns the address of the slot just after slot assuming each slot has the // specified size. static inline void* NextSlot(void* slot, size_t slot_size) { @@ -218,26 +221,35 @@ void DropDeletesWithoutResize(CommonFields& common, common.infoz().RecordRehash(total_probe_length); } -void EraseMetaOnly(CommonFields& c, ctrl_t* it, size_t slot_size) { - assert(IsFull(*it) && "erasing a dangling iterator"); - c.set_size(c.size() - 1); - const auto index = static_cast<size_t>(it - c.control()); +static bool WasNeverFull(CommonFields& c, size_t index) { + if (is_single_group(c.capacity())) { + return true; + } const size_t index_before = (index - Group::kWidth) & c.capacity(); - const auto empty_after = Group(it).MaskEmpty(); + const auto empty_after = Group(c.control() + index).MaskEmpty(); const auto empty_before = Group(c.control() + index_before).MaskEmpty(); // We count how many consecutive non empties we have to the right and to the // left of `it`. If the sum is >= kWidth then there is at least one probe // window that might have seen a full group. - bool was_never_full = empty_before && empty_after && - static_cast<size_t>(empty_after.TrailingZeros()) + - empty_before.LeadingZeros() < - Group::kWidth; - - SetCtrl(c, index, was_never_full ? ctrl_t::kEmpty : ctrl_t::kDeleted, - slot_size); - c.set_growth_left(c.growth_left() + (was_never_full ? 1 : 0)); + return empty_before && empty_after && + static_cast<size_t>(empty_after.TrailingZeros()) + + empty_before.LeadingZeros() < + Group::kWidth; +} + +void EraseMetaOnly(CommonFields& c, size_t index, size_t slot_size) { + assert(IsFull(c.control()[index]) && "erasing a dangling iterator"); + c.decrement_size(); c.infoz().RecordErase(); + + if (WasNeverFull(c, index)) { + SetCtrl(c, index, ctrl_t::kEmpty, slot_size); + c.set_growth_left(c.growth_left() + 1); + return; + } + + SetCtrl(c, index, ctrl_t::kDeleted, slot_size); } void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy, @@ -245,19 +257,124 @@ void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy, c.set_size(0); if (reuse) { ResetCtrl(c, policy.slot_size); + ResetGrowthLeft(c); c.infoz().RecordStorageChanged(0, c.capacity()); } else { + // We need to record infoz before calling dealloc, which will unregister + // infoz. + c.infoz().RecordClearedReservation(); + c.infoz().RecordStorageChanged(0, 0); (*policy.dealloc)(c, policy); c.set_control(EmptyGroup()); c.set_generation_ptr(EmptyGeneration()); c.set_slots(nullptr); c.set_capacity(0); - c.infoz().RecordClearedReservation(); - assert(c.size() == 0); - c.infoz().RecordStorageChanged(0, 0); } } +void HashSetResizeHelper::GrowIntoSingleGroupShuffleControlBytes( + ctrl_t* new_ctrl, size_t new_capacity) const { + assert(is_single_group(new_capacity)); + constexpr size_t kHalfWidth = Group::kWidth / 2; + assert(old_capacity_ < kHalfWidth); + + const size_t half_old_capacity = old_capacity_ / 2; + + // NOTE: operations are done with compile time known size = kHalfWidth. + // Compiler optimizes that into single ASM operation. + + // Copy second half of bytes to the beginning. + // 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_ctrl = 0S0EEEEEEE... + // new_ctrl = S0EEEEEEEE... + // + // old_ctrl = 01S01EEEEE... + // new_ctrl = 1S01EEEEEE... + // + // old_ctrl = 0123456S0123456EE... + // new_ctrl = 456S0123?????????... + std::memcpy(new_ctrl, old_ctrl_ + half_old_capacity + 1, kHalfWidth); + // Clean up copied kSentinel from old_ctrl. + new_ctrl[half_old_capacity] = ctrl_t::kEmpty; + + // Clean up damaged or uninitialized bytes. + + // Clean bytes after the intended size of the copy. + // Example: + // new_ctrl = 1E01EEEEEEE???? + // *new_ctrl= 1E0EEEEEEEE???? + // position / + std::memset(new_ctrl + old_capacity_ + 1, static_cast<int8_t>(ctrl_t::kEmpty), + kHalfWidth); + // Clean non-mirrored bytes that are not initialized. + // For small old_capacity that may be inside of mirrored bytes zone. + // Examples: + // new_ctrl = 1E0EEEEEEEE??????????.... + // *new_ctrl= 1E0EEEEEEEEEEEEE?????.... + // position / + // + // new_ctrl = 456E0123???????????... + // *new_ctrl= 456E0123EEEEEEEE???... + // position / + std::memset(new_ctrl + kHalfWidth, static_cast<int8_t>(ctrl_t::kEmpty), + kHalfWidth); + // Clean last mirrored bytes that are not initialized + // and will not be overwritten by mirroring. + // Examples: + // new_ctrl = 1E0EEEEEEEEEEEEE???????? + // *new_ctrl= 1E0EEEEEEEEEEEEEEEEEEEEE + // position S / + // + // new_ctrl = 456E0123EEEEEEEE??????????????? + // *new_ctrl= 456E0123EEEEEEEE???????EEEEEEEE + // position S / + std::memset(new_ctrl + new_capacity + kHalfWidth, + static_cast<int8_t>(ctrl_t::kEmpty), kHalfWidth); + + // Create mirrored bytes. old_capacity_ < kHalfWidth + // Example: + // new_ctrl = 456E0123EEEEEEEE???????EEEEEEEE + // *new_ctrl= 456E0123EEEEEEEE456E0123EEEEEEE + // position S/ + ctrl_t g[kHalfWidth]; + std::memcpy(g, new_ctrl, kHalfWidth); + std::memcpy(new_ctrl + new_capacity + 1, g, kHalfWidth); + + // Finally set sentinel to its place. + new_ctrl[new_capacity] = ctrl_t::kSentinel; +} + +void HashSetResizeHelper::GrowIntoSingleGroupShuffleTransferableSlots( + void* old_slots, void* new_slots, size_t slot_size) const { + assert(old_capacity_ > 0); + const size_t half_old_capacity = old_capacity_ / 2; + + 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)); +} + +void HashSetResizeHelper::GrowSizeIntoSingleGroupTransferable( + CommonFields& c, void* old_slots, size_t slot_size) { + assert(old_capacity_ < Group::kWidth / 2); + assert(is_single_group(c.capacity())); + assert(IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity())); + + GrowIntoSingleGroupShuffleControlBytes(c.control(), c.capacity()); + GrowIntoSingleGroupShuffleTransferableSlots(old_slots, c.slot_array(), + slot_size); + + // We poison since GrowIntoSingleGroupShuffleTransferableSlots + // may leave empty slots unpoisoned. + PoisonSingleGroupEmptySlots(c, slot_size); +} + } // 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 5f89d8efee..3518bc3404 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 @@ -62,6 +62,9 @@ // pseudo-struct: // // struct BackingArray { +// // Sampling handler. This field isn't present when the sampling is +// // disabled or this allocation hasn't been selected for sampling. +// HashtablezInfoHandle infoz_; // // The number of elements we can insert before growing the capacity. // size_t growth_left; // // Control bytes for the "real" slots. @@ -175,25 +178,29 @@ #define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_ #include <algorithm> +#include <cassert> #include <cmath> #include <cstddef> #include <cstdint> #include <cstring> +#include <initializer_list> #include <iterator> #include <limits> #include <memory> -#include <string> #include <tuple> #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/raw_logging.h" +#include "absl/base/macros.h" #include "absl/base/optimization.h" +#include "absl/base/options.h" #include "absl/base/port.h" #include "absl/base/prefetch.h" -#include "absl/container/internal/common.h" +#include "absl/container/internal/common.h" // IWYU pragma: export // for node_handle #include "absl/container/internal/compressed_tuple.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_policy_traits.h" @@ -227,6 +234,7 @@ namespace container_internal { #ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS #error ABSL_SWISSTABLE_ENABLE_GENERATIONS cannot be directly set #elif defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ + defined(ABSL_HAVE_HWADDRESS_SANITIZER) || \ defined(ABSL_HAVE_MEMORY_SANITIZER) // When compiled in sanitizer mode, we add generation integers to the backing // array and iterators. In the backing array, we store the generation between @@ -262,8 +270,21 @@ void SwapAlloc(AllocType& lhs, AllocType& rhs, swap(lhs, rhs); } template <typename AllocType> -void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/, - std::false_type /* propagate_on_container_swap */) {} +void SwapAlloc(AllocType& lhs, AllocType& rhs, + std::false_type /* propagate_on_container_swap */) { + (void)lhs; + (void)rhs; + assert(lhs == rhs && + "It's UB to call swap with unequal non-propagating allocators."); +} + +template <typename AllocType> +void CopyAlloc(AllocType& lhs, AllocType& rhs, + std::true_type /* propagate_alloc */) { + lhs = rhs; +} +template <typename AllocType> +void CopyAlloc(AllocType&, AllocType&, std::false_type /* propagate_alloc */) {} // The state for a probe sequence. // @@ -361,7 +382,7 @@ uint32_t TrailingZeros(T x) { // width of an abstract bit in the representation. // This mask provides operations for any number of real bits set in an abstract // bit. To add iteration on top of that, implementation must guarantee no more -// than one real bit is set in an abstract bit. +// than the most significant real bit is set in a set abstract bit. template <class T, int SignificantBits, int Shift = 0> class NonIterableBitMask { public: @@ -388,7 +409,9 @@ class NonIterableBitMask { uint32_t LeadingZeros() const { constexpr int total_significant_bits = SignificantBits << Shift; constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits; - return static_cast<uint32_t>(countl_zero(mask_ << extra_bits)) >> Shift; + return static_cast<uint32_t>( + countl_zero(static_cast<T>(mask_ << extra_bits))) >> + Shift; } T mask_; @@ -418,6 +441,10 @@ class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> { using const_iterator = BitMask; BitMask& operator++() { + if (Shift == 3) { + constexpr uint64_t msbs = 0x8080808080808080ULL; + this->mask_ &= msbs; + } this->mask_ &= (this->mask_ - 1); return *this; } @@ -590,29 +617,39 @@ struct GroupSse2Impl { } // Returns a bitmask representing the positions of slots that match hash. - BitMask<uint32_t, kWidth> Match(h2_t hash) const { + BitMask<uint16_t, kWidth> Match(h2_t hash) const { auto match = _mm_set1_epi8(static_cast<char>(hash)); - return BitMask<uint32_t, kWidth>( - static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl)))); + BitMask<uint16_t, kWidth> result = BitMask<uint16_t, kWidth>(0); + result = 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. - NonIterableBitMask<uint32_t, kWidth> MaskEmpty() const { + NonIterableBitMask<uint16_t, kWidth> MaskEmpty() const { #ifdef ABSL_INTERNAL_HAVE_SSSE3 // This only works because ctrl_t::kEmpty is -128. - return NonIterableBitMask<uint32_t, kWidth>( - static_cast<uint32_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl)))); + return NonIterableBitMask<uint16_t, kWidth>( + static_cast<uint16_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl)))); #else auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty)); - return NonIterableBitMask<uint32_t, kWidth>( - static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl)))); + return NonIterableBitMask<uint16_t, kWidth>( + static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl)))); #endif } + // Returns a bitmask representing the positions of full slots. + // Note: for `is_small()` tables group may contain the "same" slot twice: + // original and mirrored. + BitMask<uint16_t, kWidth> MaskFull() const { + return BitMask<uint16_t, kWidth>( + static_cast<uint16_t>(_mm_movemask_epi8(ctrl) ^ 0xffff)); + } + // Returns a bitmask representing the positions of empty or deleted slots. - NonIterableBitMask<uint32_t, kWidth> MaskEmptyOrDeleted() const { + NonIterableBitMask<uint16_t, kWidth> MaskEmptyOrDeleted() const { auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel)); - return NonIterableBitMask<uint32_t, kWidth>(static_cast<uint32_t>( + return NonIterableBitMask<uint16_t, kWidth>(static_cast<uint16_t>( _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)))); } @@ -651,9 +688,8 @@ struct GroupAArch64Impl { BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const { uint8x8_t dup = vdup_n_u8(hash); auto mask = vceq_u8(ctrl, dup); - constexpr uint64_t msbs = 0x8080808080808080ULL; return BitMask<uint64_t, kWidth, 3>( - vget_lane_u64(vreinterpret_u64_u8(mask), 0) & msbs); + vget_lane_u64(vreinterpret_u64_u8(mask), 0)); } NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const { @@ -665,6 +701,17 @@ struct GroupAArch64Impl { return NonIterableBitMask<uint64_t, kWidth, 3>(mask); } + // Returns a bitmask representing the positions of full slots. + // Note: for `is_small()` tables group may contain the "same" slot twice: + // original and mirrored. + BitMask<uint64_t, kWidth, 3> MaskFull() const { + uint64_t mask = vget_lane_u64( + vreinterpret_u64_u8(vcge_s8(vreinterpret_s8_u8(ctrl), + vdup_n_s8(static_cast<int8_t>(0)))), + 0); + return BitMask<uint64_t, kWidth, 3>(mask); + } + NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const { uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(vcgt_s8( @@ -729,13 +776,21 @@ struct GroupPortableImpl { NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const { constexpr uint64_t msbs = 0x8080808080808080ULL; - return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & (~ctrl << 6)) & + return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 6)) & msbs); } + // Returns a bitmask representing the positions of full slots. + // Note: for `is_small()` tables group may contain the "same" slot twice: + // original and mirrored. + BitMask<uint64_t, kWidth, 3> MaskFull() const { + constexpr uint64_t msbs = 0x8080808080808080ULL; + return BitMask<uint64_t, kWidth, 3>((ctrl ^ msbs) & msbs); + } + NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const { constexpr uint64_t msbs = 0x8080808080808080ULL; - return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & (~ctrl << 7)) & + return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 7)) & msbs); } @@ -760,10 +815,21 @@ struct GroupPortableImpl { #ifdef ABSL_INTERNAL_HAVE_SSE2 using Group = GroupSse2Impl; +using GroupEmptyOrDeleted = GroupSse2Impl; #elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN) using Group = GroupAArch64Impl; +// For Aarch64, we use the portable implementation for counting and masking +// empty or deleted group elements. This is to avoid the latency of moving +// between data GPRs and Neon registers when it does not provide a benefit. +// Using Neon is profitable when we call Match(), but is not when we don't, +// which is the case when we do *EmptyOrDeleted operations. It is difficult to +// make a similar approach beneficial on other architectures such as x86 since +// they have much lower GPR <-> vector register transfer latency and 16-wide +// Groups. +using GroupEmptyOrDeleted = GroupPortableImpl; #else using Group = GroupPortableImpl; +using GroupEmptyOrDeleted = GroupPortableImpl; #endif // When there is an insertion with no reserved growth, we rehash with @@ -802,15 +868,19 @@ class CommonFieldsGenerationInfoEnabled { // whenever reserved_growth_ is zero. bool should_rehash_for_bug_detection_on_insert(const ctrl_t* ctrl, size_t capacity) const; + // Similar to above, except that we don't depend on reserved_growth_. + bool should_rehash_for_bug_detection_on_move(const ctrl_t* ctrl, + size_t capacity) const; void maybe_increment_generation_on_insert() { if (reserved_growth_ == kReservedGrowthJustRanOut) reserved_growth_ = 0; if (reserved_growth_ > 0) { if (--reserved_growth_ == 0) reserved_growth_ = kReservedGrowthJustRanOut; } else { - *generation_ = NextGeneration(*generation_); + increment_generation(); } } + void increment_generation() { *generation_ = NextGeneration(*generation_); } void reset_reserved_growth(size_t reservation, size_t size) { reserved_growth_ = reservation - size; } @@ -856,7 +926,11 @@ class CommonFieldsGenerationInfoDisabled { bool should_rehash_for_bug_detection_on_insert(const ctrl_t*, size_t) const { return false; } + bool should_rehash_for_bug_detection_on_move(const ctrl_t*, size_t) const { + return false; + } void maybe_increment_generation_on_insert() {} + void increment_generation() {} void reset_reserved_growth(size_t, size_t) {} size_t reserved_growth() const { return 0; } void set_reserved_growth(size_t) {} @@ -909,9 +983,11 @@ using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoDisabled; // A valid capacity is a non-zero integer `2^m - 1`. inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; } -// Computes the offset from the start of the backing allocation of the control -// bytes. growth_left is stored at the beginning of the backing array. -inline size_t ControlOffset() { return sizeof(size_t); } +// Computes the offset from the start of the backing allocation of control. +// infoz and growth_left are stored at the beginning of the backing array. +inline size_t ControlOffset(bool has_infoz) { + return (has_infoz ? sizeof(HashtablezInfoHandle) : 0) + sizeof(size_t); +} // Returns the number of "cloned control bytes". // @@ -922,24 +998,26 @@ constexpr size_t NumClonedBytes() { return Group::kWidth - 1; } // Given the capacity of a table, computes the offset (from the start of the // backing allocation) of the generation counter (if it exists). -inline size_t GenerationOffset(size_t capacity) { +inline size_t GenerationOffset(size_t capacity, bool has_infoz) { assert(IsValidCapacity(capacity)); const size_t num_control_bytes = capacity + 1 + NumClonedBytes(); - return ControlOffset() + num_control_bytes; + return ControlOffset(has_infoz) + num_control_bytes; } // Given the capacity of a table, computes the offset (from the start of the // backing allocation) at which the slots begin. -inline size_t SlotOffset(size_t capacity, size_t slot_align) { +inline size_t SlotOffset(size_t capacity, size_t slot_align, bool has_infoz) { assert(IsValidCapacity(capacity)); - return (GenerationOffset(capacity) + NumGenerationBytes() + slot_align - 1) & + return (GenerationOffset(capacity, has_infoz) + NumGenerationBytes() + + slot_align - 1) & (~slot_align + 1); } // Given the capacity of a table, computes the total size of the backing // array. -inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align) { - return SlotOffset(capacity, slot_align) + capacity * slot_size; +inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align, + bool has_infoz) { + return SlotOffset(capacity, slot_align, has_infoz) + capacity * slot_size; } // CommonFields hold the fields in raw_hash_set that do not depend @@ -954,28 +1032,15 @@ class CommonFields : public CommonFieldsGenerationInfo { CommonFields& operator=(const CommonFields&) = delete; // Movable - CommonFields(CommonFields&& that) - : CommonFieldsGenerationInfo( - std::move(static_cast<CommonFieldsGenerationInfo&&>(that))), - // Explicitly copying fields into "this" and then resetting "that" - // fields generates less code then calling absl::exchange per field. - control_(that.control()), - slots_(that.slot_array()), - capacity_(that.capacity()), - compressed_tuple_(that.size(), std::move(that.infoz())) { - that.set_control(EmptyGroup()); - that.set_slots(nullptr); - that.set_capacity(0); - that.set_size(0); - } + CommonFields(CommonFields&& that) = default; CommonFields& operator=(CommonFields&&) = default; ctrl_t* control() const { return control_; } void set_control(ctrl_t* c) { control_ = c; } void* backing_array_start() const { - // growth_left is stored before control bytes. + // growth_left (and maybe infoz) is stored before control bytes. assert(reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0); - return control() - sizeof(size_t); + return control() - ControlOffset(has_infoz()); } // Note: we can't use slots() because Qt defines "slots" as a macro. @@ -983,8 +1048,18 @@ class CommonFields : public CommonFieldsGenerationInfo { void set_slots(void* s) { slots_ = s; } // The number of filled slots. - size_t size() const { return compressed_tuple_.template get<0>(); } - void set_size(size_t s) { compressed_tuple_.template get<0>() = s; } + size_t size() const { return size_ >> HasInfozShift(); } + void set_size(size_t s) { + size_ = (s << HasInfozShift()) | (size_ & HasInfozMask()); + } + void increment_size() { + assert(size() < capacity()); + size_ += size_t{1} << HasInfozShift(); + } + void decrement_size() { + assert(size() > 0); + size_ -= size_t{1} << HasInfozShift(); + } // The total number of available slots. size_t capacity() const { return capacity_; } @@ -996,28 +1071,52 @@ class CommonFields : public CommonFieldsGenerationInfo { // The number of slots we can still fill without needing to rehash. // This is stored in the heap allocation before the control bytes. size_t growth_left() const { - return *reinterpret_cast<size_t*>(backing_array_start()); + const size_t* gl_ptr = reinterpret_cast<size_t*>(control()) - 1; + assert(reinterpret_cast<uintptr_t>(gl_ptr) % alignof(size_t) == 0); + return *gl_ptr; } void set_growth_left(size_t gl) { - *reinterpret_cast<size_t*>(backing_array_start()) = gl; + size_t* gl_ptr = reinterpret_cast<size_t*>(control()) - 1; + assert(reinterpret_cast<uintptr_t>(gl_ptr) % alignof(size_t) == 0); + *gl_ptr = gl; } - HashtablezInfoHandle& infoz() { return compressed_tuple_.template get<1>(); } - const HashtablezInfoHandle& infoz() const { - return compressed_tuple_.template get<1>(); + bool has_infoz() const { + return ABSL_PREDICT_FALSE((size_ & HasInfozMask()) != 0); + } + void set_has_infoz(bool has_infoz) { + size_ = (size() << HasInfozShift()) | static_cast<size_t>(has_infoz); + } + + HashtablezInfoHandle infoz() { + return has_infoz() + ? *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start()) + : HashtablezInfoHandle(); + } + void set_infoz(HashtablezInfoHandle infoz) { + assert(has_infoz()); + *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start()) = infoz; } bool should_rehash_for_bug_detection_on_insert() const { return CommonFieldsGenerationInfo:: should_rehash_for_bug_detection_on_insert(control(), capacity()); } + bool should_rehash_for_bug_detection_on_move() const { + return CommonFieldsGenerationInfo:: + should_rehash_for_bug_detection_on_move(control(), capacity()); + } + void maybe_increment_generation_on_move() { + if (capacity() == 0) return; + increment_generation(); + } void reset_reserved_growth(size_t reservation) { CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size()); } // The size of the backing array allocation. size_t alloc_size(size_t slot_size, size_t slot_align) const { - return AllocSize(capacity(), slot_size, slot_align); + return AllocSize(capacity(), slot_size, slot_align, has_infoz()); } // Returns the number of control bytes set to kDeleted. For testing only. @@ -1027,9 +1126,14 @@ class CommonFields : public CommonFieldsGenerationInfo { } private: - // TODO(b/259599413): Investigate removing some of these fields: + // We store the has_infoz bit in the lowest bit of size_. + static constexpr size_t HasInfozShift() { return 1; } + static constexpr size_t HasInfozMask() { + return (size_t{1} << HasInfozShift()) - 1; + } + + // TODO(b/182800944): Investigate removing some of these fields: // - control/slots can be derived from each other - // - we can use 6 bits for capacity since it's always a power of two minus 1 // The control bytes (and, also, a pointer near to the base of the backing // array). @@ -1044,12 +1148,16 @@ class CommonFields : public CommonFieldsGenerationInfo { // `control`. May be null for empty tables. void* slots_ = nullptr; + // The number of slots in the backing array. This is always 2^N-1 for an + // integer N. NOTE: we tried experimenting with compressing the capacity and + // storing it together with size_: (a) using 6 bits to store the corresponding + // power (N in 2^N-1), and (b) storing 2^N as the most significant bit of + // size_ and storing size in the low bits. Both of these experiments were + // regressions, presumably because we need capacity to do find operations. size_t capacity_ = 0; - // Bundle together size and HashtablezInfoHandle to ensure EBO for - // HashtablezInfoHandle when sampling is turned off. - absl::container_internal::CompressedTuple<size_t, HashtablezInfoHandle> - compressed_tuple_{0u, HashtablezInfoHandle{}}; + // The size and also has one bit that stores whether we have infoz. + size_t size_ = 0; }; template <class Policy, class Hash, class Eq, class Alloc> @@ -1139,35 +1247,39 @@ inline void AssertIsFull(const ctrl_t* ctrl, GenerationType generation, const GenerationType* generation_ptr, const char* operation) { if (!SwisstableDebugEnabled()) return; - if (ctrl == nullptr) { - ABSL_INTERNAL_LOG(FATAL, - std::string(operation) + " called on end() iterator."); - } - if (ctrl == EmptyGroup()) { - ABSL_INTERNAL_LOG(FATAL, std::string(operation) + - " called on default-constructed iterator."); + // `SwisstableDebugEnabled()` is also true for release builds with hardening + // enabled. To minimize their impact in those builds: + // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout + // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve + // the chances that the hot paths will be inlined. + if (ABSL_PREDICT_FALSE(ctrl == nullptr)) { + ABSL_RAW_LOG(FATAL, "%s called on end() iterator.", operation); + } + if (ABSL_PREDICT_FALSE(ctrl == EmptyGroup())) { + ABSL_RAW_LOG(FATAL, "%s called on default-constructed iterator.", + operation); } if (SwisstableGenerationsEnabled()) { - if (generation != *generation_ptr) { - ABSL_INTERNAL_LOG(FATAL, - std::string(operation) + - " called on invalid iterator. The table could have " - "rehashed since this iterator was initialized."); + if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) { + ABSL_RAW_LOG(FATAL, + "%s called on invalid iterator. The table could have " + "rehashed or moved since this iterator was initialized.", + operation); } - if (!IsFull(*ctrl)) { - ABSL_INTERNAL_LOG( + if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) { + ABSL_RAW_LOG( FATAL, - std::string(operation) + - " called on invalid iterator. The element was likely erased."); + "%s called on invalid iterator. The element was likely erased.", + operation); } } else { - if (!IsFull(*ctrl)) { - ABSL_INTERNAL_LOG( + if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) { + ABSL_RAW_LOG( FATAL, - std::string(operation) + - " called on invalid iterator. The element might have been erased " - "or the table might have rehashed. Consider running with " - "--config=asan to diagnose rehashing issues."); + "%s called on invalid iterator. The element might have been erased " + "or the table might have rehashed. Consider running with " + "--config=asan to diagnose rehashing issues.", + operation); } } } @@ -1180,13 +1292,13 @@ inline void AssertIsValidForComparison(const ctrl_t* ctrl, const bool ctrl_is_valid_for_comparison = ctrl == nullptr || ctrl == EmptyGroup() || IsFull(*ctrl); if (SwisstableGenerationsEnabled()) { - if (generation != *generation_ptr) { - ABSL_INTERNAL_LOG(FATAL, - "Invalid iterator comparison. The table could have " - "rehashed since this iterator was initialized."); + if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) { + ABSL_RAW_LOG(FATAL, + "Invalid iterator comparison. The table could have rehashed " + "or moved since this iterator was initialized."); } - if (!ctrl_is_valid_for_comparison) { - ABSL_INTERNAL_LOG( + if (ABSL_PREDICT_FALSE(!ctrl_is_valid_for_comparison)) { + ABSL_RAW_LOG( FATAL, "Invalid iterator comparison. The element was likely erased."); } } else { @@ -1226,10 +1338,15 @@ inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b, const GenerationType* generation_ptr_a, const GenerationType* generation_ptr_b) { if (!SwisstableDebugEnabled()) return; + // `SwisstableDebugEnabled()` is also true for release builds with hardening + // enabled. To minimize their impact in those builds: + // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout + // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve + // the chances that the hot paths will be inlined. const bool a_is_default = ctrl_a == EmptyGroup(); const bool b_is_default = ctrl_b == EmptyGroup(); - if (a_is_default != b_is_default) { - ABSL_INTERNAL_LOG( + if (ABSL_PREDICT_FALSE(a_is_default != b_is_default)) { + ABSL_RAW_LOG( FATAL, "Invalid iterator comparison. Comparing default-constructed iterator " "with non-default-constructed iterator."); @@ -1237,36 +1354,36 @@ inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b, if (a_is_default && b_is_default) return; if (SwisstableGenerationsEnabled()) { - if (generation_ptr_a == generation_ptr_b) return; + if (ABSL_PREDICT_TRUE(generation_ptr_a == generation_ptr_b)) return; const bool a_is_empty = IsEmptyGeneration(generation_ptr_a); const bool b_is_empty = IsEmptyGeneration(generation_ptr_b); if (a_is_empty != b_is_empty) { - ABSL_INTERNAL_LOG(FATAL, - "Invalid iterator comparison. Comparing iterator from " - "a non-empty hashtable with an iterator from an empty " - "hashtable."); + ABSL_RAW_LOG(FATAL, + "Invalid iterator comparison. Comparing iterator from a " + "non-empty hashtable with an iterator from an empty " + "hashtable."); } if (a_is_empty && b_is_empty) { - ABSL_INTERNAL_LOG(FATAL, - "Invalid iterator comparison. Comparing iterators from " - "different empty hashtables."); + ABSL_RAW_LOG(FATAL, + "Invalid iterator comparison. Comparing iterators from " + "different empty hashtables."); } const bool a_is_end = ctrl_a == nullptr; const bool b_is_end = ctrl_b == nullptr; if (a_is_end || b_is_end) { - ABSL_INTERNAL_LOG(FATAL, - "Invalid iterator comparison. Comparing iterator with " - "an end() iterator from a different hashtable."); + ABSL_RAW_LOG(FATAL, + "Invalid iterator comparison. Comparing iterator with an " + "end() iterator from a different hashtable."); } - ABSL_INTERNAL_LOG(FATAL, - "Invalid iterator comparison. Comparing non-end() " - "iterators from different hashtables."); + ABSL_RAW_LOG(FATAL, + "Invalid iterator comparison. Comparing non-end() iterators " + "from different hashtables."); } else { ABSL_HARDENING_ASSERT( 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. Consider running " - "with --config=asan to diagnose rehashing issues."); + "containers or the container might have rehashed or moved. Consider " + "running with --config=asan to diagnose issues."); } } @@ -1289,6 +1406,12 @@ struct FindInfo { // `ShouldInsertBackwards()` for small tables. inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; } +// Whether a table fits entirely into a probing group. +// Arbitrary order of elements in such tables is correct. +inline bool is_single_group(size_t capacity) { + return capacity <= Group::kWidth; +} + // Begins a probing operation on `common.control`, using `hash`. inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, const size_t capacity, size_t hash) { @@ -1310,7 +1433,7 @@ inline FindInfo find_first_non_full(const CommonFields& common, size_t hash) { auto seq = probe(common, hash); const ctrl_t* ctrl = common.control(); while (true) { - Group g{ctrl + seq.offset()}; + GroupEmptyOrDeleted g{ctrl + seq.offset()}; auto mask = g.MaskEmptyOrDeleted(); if (mask) { #if !defined(NDEBUG) @@ -1351,7 +1474,6 @@ inline void ResetCtrl(CommonFields& common, size_t slot_size) { capacity + 1 + NumClonedBytes()); ctrl[capacity] = ctrl_t::kSentinel; SanitizerPoisonMemoryRegion(common.slot_array(), slot_size * capacity); - ResetGrowthLeft(common); } // Sets `ctrl[i]` to `h`. @@ -1386,38 +1508,263 @@ constexpr size_t BackingArrayAlignment(size_t align_of_slot) { return (std::max)(align_of_slot, alignof(size_t)); } -template <typename Alloc, size_t SizeOfSlot, size_t AlignOfSlot> -ABSL_ATTRIBUTE_NOINLINE void InitializeSlots(CommonFields& c, Alloc alloc) { - assert(c.capacity()); - // Folks with custom allocators often make unwarranted assumptions about the - // behavior of their classes vis-a-vis trivial destructability and what - // calls they will or won't make. Avoid sampling for people with custom - // allocators to get us out of this mess. This is not a hard guarantee but - // a workaround while we plan the exact guarantee we want to provide. - const size_t sample_size = - (std::is_same<Alloc, std::allocator<char>>::value && - c.slot_array() == nullptr) - ? SizeOfSlot - : 0; - - const size_t cap = c.capacity(); - const size_t alloc_size = AllocSize(cap, SizeOfSlot, AlignOfSlot); - // growth_left (which is a size_t) is stored with the backing array. - char* mem = static_cast<char*>( - Allocate<BackingArrayAlignment(AlignOfSlot)>(&alloc, alloc_size)); - const GenerationType old_generation = c.generation(); - c.set_generation_ptr( - reinterpret_cast<GenerationType*>(mem + GenerationOffset(cap))); - c.set_generation(NextGeneration(old_generation)); - c.set_control(reinterpret_cast<ctrl_t*>(mem + ControlOffset())); - c.set_slots(mem + SlotOffset(cap, AlignOfSlot)); - ResetCtrl(c, SizeOfSlot); - if (sample_size) { - c.infoz() = Sample(sample_size); - } - c.infoz().RecordStorageChanged(c.size(), cap); +// Returns the address of the ith slot in slots where each slot occupies +// slot_size. +inline void* SlotAddress(void* slot_array, size_t slot, size_t slot_size) { + return reinterpret_cast<void*>(reinterpret_cast<char*>(slot_array) + + (slot * slot_size)); } +// Helper class to perform resize of the hash set. +// +// It contains special optimizations for small group resizes. +// See GrowIntoSingleGroupShuffleControlBytes for details. +class HashSetResizeHelper { + public: + explicit HashSetResizeHelper(CommonFields& c) + : old_ctrl_(c.control()), + old_capacity_(c.capacity()), + had_infoz_(c.has_infoz()) {} + + // Optimized for small groups version of `find_first_non_full` applicable + // only right after calling `raw_hash_set::resize`. + // It has implicit assumption that `resize` will call + // `GrowSizeIntoSingleGroup*` in case `IsGrowingIntoSingleGroupApplicable`. + // Falls back to `find_first_non_full` in case of big groups, so it is + // safe to use after `rehash_and_grow_if_necessary`. + 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}; + } + + ctrl_t* old_ctrl() const { return old_ctrl_; } + size_t old_capacity() const { return old_capacity_; } + + // Allocates a backing array for the hashtable. + // Reads `capacity` and updates all other fields based on the result of + // the allocation. + // + // It also may do the folowing actions: + // 1. initialize control bytes + // 2. initialize slots + // 3. deallocate old slots. + // + // We are bundling a lot of functionality + // in one ABSL_ATTRIBUTE_NOINLINE function in order to minimize binary code + // duplication in raw_hash_set<>::resize. + // + // `c.capacity()` must be nonzero. + // POSTCONDITIONS: + // 1. CommonFields is initialized. + // + // if IsGrowingIntoSingleGroupApplicable && TransferUsesMemcpy + // Both control bytes and slots are fully initialized. + // old_slots are deallocated. + // infoz.RecordRehash is called. + // + // if IsGrowingIntoSingleGroupApplicable && !TransferUsesMemcpy + // Control bytes are fully initialized. + // infoz.RecordRehash is called. + // GrowSizeIntoSingleGroup must be called to finish slots initialization. + // + // if !IsGrowingIntoSingleGroupApplicable + // Control bytes are initialized to empty table via ResetCtrl. + // raw_hash_set<>::resize must insert elements regularly. + // infoz.RecordRehash is called if old_capacity == 0. + // + // Returns IsGrowingIntoSingleGroupApplicable result to avoid recomputation. + template <typename Alloc, size_t SizeOfSlot, bool TransferUsesMemcpy, + size_t AlignOfSlot> + ABSL_ATTRIBUTE_NOINLINE bool InitializeSlots(CommonFields& c, void* old_slots, + Alloc alloc) { + assert(c.capacity()); + // Folks with custom allocators often make unwarranted assumptions about the + // behavior of their classes vis-a-vis trivial destructability and what + // calls they will or won't make. Avoid sampling for people with custom + // allocators to get us out of this mess. This is not a hard guarantee but + // a workaround while we plan the exact guarantee we want to provide. + const size_t sample_size = + (std::is_same<Alloc, std::allocator<char>>::value && + c.slot_array() == nullptr) + ? SizeOfSlot + : 0; + HashtablezInfoHandle infoz = + sample_size > 0 ? Sample(sample_size) : c.infoz(); + + const bool has_infoz = infoz.IsSampled(); + const size_t cap = c.capacity(); + const size_t alloc_size = + AllocSize(cap, SizeOfSlot, AlignOfSlot, has_infoz); + char* mem = static_cast<char*>( + Allocate<BackingArrayAlignment(AlignOfSlot)>(&alloc, alloc_size)); + const GenerationType old_generation = c.generation(); + c.set_generation_ptr(reinterpret_cast<GenerationType*>( + mem + GenerationOffset(cap, has_infoz))); + c.set_generation(NextGeneration(old_generation)); + c.set_control(reinterpret_cast<ctrl_t*>(mem + ControlOffset(has_infoz))); + c.set_slots(mem + SlotOffset(cap, AlignOfSlot, has_infoz)); + ResetGrowthLeft(c); + + const bool grow_single_group = + IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity()); + if (old_capacity_ != 0 && grow_single_group) { + if (TransferUsesMemcpy) { + GrowSizeIntoSingleGroupTransferable(c, old_slots, SizeOfSlot); + DeallocateOld<AlignOfSlot>(alloc, SizeOfSlot, old_slots); + } else { + GrowIntoSingleGroupShuffleControlBytes(c.control(), c.capacity()); + } + } else { + ResetCtrl(c, SizeOfSlot); + } + + c.set_has_infoz(has_infoz); + if (has_infoz) { + infoz.RecordStorageChanged(c.size(), cap); + if (grow_single_group || old_capacity_ == 0) { + infoz.RecordRehash(0); + } + c.set_infoz(infoz); + } + return grow_single_group; + } + + // Relocates slots into new single group consistent with + // GrowIntoSingleGroupShuffleControlBytes. + // + // PRECONDITIONS: + // 1. GrowIntoSingleGroupShuffleControlBytes was already called. + template <class PolicyTraits, class Alloc> + void GrowSizeIntoSingleGroup(CommonFields& c, Alloc& alloc_ref, + typename PolicyTraits::slot_type* old_slots) { + assert(old_capacity_ < Group::kWidth / 2); + assert(IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity())); + using slot_type = typename PolicyTraits::slot_type; + assert(is_single_group(c.capacity())); + + auto* new_slots = reinterpret_cast<slot_type*>(c.slot_array()); + + 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 + i); + } + } + PoisonSingleGroupEmptySlots(c, sizeof(slot_type)); + } + + // Deallocates old backing array. + template <size_t AlignOfSlot, class CharAlloc> + void DeallocateOld(CharAlloc alloc_ref, size_t slot_size, void* old_slots) { + SanitizerUnpoisonMemoryRegion(old_slots, slot_size * old_capacity_); + Deallocate<BackingArrayAlignment(AlignOfSlot)>( + &alloc_ref, old_ctrl_ - ControlOffset(had_infoz_), + AllocSize(old_capacity_, slot_size, AlignOfSlot, had_infoz_)); + } + + private: + // Returns true if `GrowSizeIntoSingleGroup` can be used for resizing. + static bool IsGrowingIntoSingleGroupApplicable(size_t old_capacity, + size_t new_capacity) { + // NOTE that `old_capacity < new_capacity` in order to have + // `old_capacity < Group::kWidth / 2` to make faster copies of 8 bytes. + return is_single_group(new_capacity) && old_capacity < new_capacity; + } + + // Relocates control bytes and slots into new single group for + // transferable objects. + // Must be called only if IsGrowingIntoSingleGroupApplicable returned true. + void GrowSizeIntoSingleGroupTransferable(CommonFields& c, void* old_slots, + size_t slot_size); + + // Shuffle control bits deterministically to the next capacity. + // Returns offset for newly added element with given hash. + // + // PRECONDITIONs: + // 1. new_ctrl is allocated for new_capacity, + // but not initialized. + // 2. new_capacity is a single group. + // + // 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. + // + // Examples: + // S = kSentinel, E = kEmpty + // + // old_ctrl = SEEEEEEEE... + // new_ctrl = ESEEEEEEE... + // + // old_ctrl = 0SEEEEEEE... + // new_ctrl = E0ESE0EEE... + // + // old_ctrl = 012S012EEEEEEEEE... + // new_ctrl = 2E01EEES2E01EEE... + // + // old_ctrl = 0123456S0123456EEEEEEEEEEE... + // new_ctrl = 456E0123EEEEEES456E0123EEE... + void GrowIntoSingleGroupShuffleControlBytes(ctrl_t* new_ctrl, + size_t new_capacity) const; + + // Shuffle trivially transferable slots in the way consistent with + // GrowIntoSingleGroupShuffleControlBytes. + // + // PRECONDITIONs: + // 1. old_capacity must be non-zero. + // 2. new_ctrl is fully initialized using + // GrowIntoSingleGroupShuffleControlBytes. + // 3. new_slots is allocated and *not* poisoned. + // + // POSTCONDITIONS: + // 1. new_slots are transferred from old_slots_ consistent with + // GrowIntoSingleGroupShuffleControlBytes. + // 2. Empty new_slots are *not* poisoned. + void GrowIntoSingleGroupShuffleTransferableSlots(void* old_slots, + void* new_slots, + size_t slot_size) const; + + // Poison empty slots that were transferred using the deterministic algorithm + // described above. + // PRECONDITIONs: + // 1. new_ctrl is fully initialized using + // GrowIntoSingleGroupShuffleControlBytes. + // 2. new_slots is fully initialized consistent with + // GrowIntoSingleGroupShuffleControlBytes. + void PoisonSingleGroupEmptySlots(CommonFields& c, size_t slot_size) const { + // poison non full items + for (size_t i = 0; i < c.capacity(); ++i) { + if (!IsFull(c.control()[i])) { + SanitizerPoisonMemoryRegion(SlotAddress(c.slot_array(), i, slot_size), + slot_size); + } + } + } + + ctrl_t* old_ctrl_; + size_t old_capacity_; + bool had_infoz_; +}; + // PolicyFunctions bundles together some information for a particular // raw_hash_set<T, ...> instantiation. This information is passed to // type-erased functions that want to do small amounts of type-specific @@ -1442,7 +1789,7 @@ void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy, bool reuse); // Type-erased version of raw_hash_set::erase_meta_only. -void EraseMetaOnly(CommonFields& c, ctrl_t* it, size_t slot_size); +void EraseMetaOnly(CommonFields& c, size_t index, size_t slot_size); // Function to place in PolicyFunctions::dealloc for raw_hash_sets // that are using std::allocator. This allows us to share the same @@ -1456,6 +1803,7 @@ ABSL_ATTRIBUTE_NOINLINE void DeallocateStandard(CommonFields& common, policy.slot_size * common.capacity()); std::allocator<char> alloc; + common.infoz().Unregister(); Deallocate<BackingArrayAlignment(AlignOfSlot)>( &alloc, common.backing_array_start(), common.alloc_size(policy.slot_size, AlignOfSlot)); @@ -1534,6 +1882,11 @@ class raw_hash_set { using AllocTraits = absl::allocator_traits<allocator_type>; using SlotAlloc = typename absl::allocator_traits< allocator_type>::template rebind_alloc<slot_type>; + // People are often sloppy with the exact type of their allocator (sometimes + // it has an extra const or is missing the pair, but rebinds made it work + // anyway). + using CharAlloc = + typename absl::allocator_traits<Alloc>::template rebind_alloc<char>; using SlotAllocTraits = typename absl::allocator_traits< allocator_type>::template rebind_traits<slot_type>; @@ -1590,7 +1943,7 @@ class raw_hash_set { // PRECONDITION: not an end() iterator. reference operator*() const { AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()"); - return PolicyTraits::element(slot_); + return unchecked_deref(); } // PRECONDITION: not an end() iterator. @@ -1645,13 +1998,17 @@ class raw_hash_set { // If a sentinel is reached, we null `ctrl_` out instead. void skip_empty_or_deleted() { while (IsEmptyOrDeleted(*ctrl_)) { - uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted(); + uint32_t shift = + GroupEmptyOrDeleted{ctrl_}.CountLeadingEmptyOrDeleted(); ctrl_ += shift; slot_ += shift; } if (ABSL_PREDICT_FALSE(*ctrl_ == ctrl_t::kSentinel)) ctrl_ = nullptr; } + ctrl_t* control() const { return ctrl_; } + slot_type* slot() const { return slot_; } + // We use EmptyGroup() for default-constructed iterators so that they can // be distinguished from end iterators, which have nullptr ctrl_. ctrl_t* ctrl_ = EmptyGroup(); @@ -1660,10 +2017,23 @@ class raw_hash_set { union { slot_type* slot_; }; + + // An equality check which skips ABSL Hardening iterator invalidation + // checks. + // Should be used when the lifetimes of the iterators are well-enough + // understood to prove that they cannot be invalid. + bool unchecked_equals(const iterator& b) { return ctrl_ == b.control(); } + + // Dereferences the iterator without ABSL Hardening iterator invalidation + // checks. + reference unchecked_deref() const { return PolicyTraits::element(slot_); } }; class const_iterator { friend class raw_hash_set; + template <class Container, typename Enabler> + friend struct absl::container_internal::hashtable_debug_internal:: + HashtableDebugAccess; public: using iterator_category = typename iterator::iterator_category; @@ -1697,8 +2067,14 @@ class raw_hash_set { const GenerationType* gen) : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot), gen) { } + ctrl_t* control() const { return inner_.control(); } + slot_type* slot() const { return inner_.slot(); } iterator inner_; + + bool unchecked_equals(const const_iterator& b) { + return inner_.unchecked_equals(b.inner_); + } }; using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>; @@ -1717,8 +2093,7 @@ class raw_hash_set { const allocator_type& alloc = allocator_type()) : settings_(CommonFields{}, hash, eq, alloc) { if (bucket_count) { - common().set_capacity(NormalizeCapacity(bucket_count)); - initialize_slots(); + resize(NormalizeCapacity(bucket_count)); } } @@ -1843,28 +2218,35 @@ 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. - settings_(absl::exchange(that.common(), CommonFields{}), - that.hash_ref(), that.eq_ref(), that.alloc_ref()) {} + // TODO(b/296061262): move instead of copying hash/eq/alloc. + // Note: we avoid using exchange for better generated code. + settings_(std::move(that.common()), that.hash_ref(), that.eq_ref(), + that.alloc_ref()) { + that.common() = CommonFields{}; + maybe_increment_generation_or_rehash_on_move(); + } raw_hash_set(raw_hash_set&& that, const allocator_type& a) : settings_(CommonFields{}, that.hash_ref(), that.eq_ref(), a) { if (a == that.alloc_ref()) { std::swap(common(), that.common()); + maybe_increment_generation_or_rehash_on_move(); } else { - reserve(that.size()); - // Note: this will copy elements of dense_set and unordered_set instead of - // moving them. This can be fixed if it ever becomes an issue. - for (auto& elem : that) insert(std::move(elem)); + move_elements_allocs_unequal(std::move(that)); } } raw_hash_set& operator=(const raw_hash_set& that) { - raw_hash_set tmp(that, - AllocTraits::propagate_on_container_copy_assignment::value - ? that.alloc_ref() - : alloc_ref()); - swap(tmp); - return *this; + if (ABSL_PREDICT_FALSE(this == &that)) return *this; + constexpr bool propagate_alloc = + AllocTraits::propagate_on_container_copy_assignment::value; + // TODO(ezb): maybe avoid allocating a new backing array if this->capacity() + // is an exact match for that.size(). If this->capacity() is too big, then + // it would make iteration very slow to reuse the allocation. Maybe we can + // do the same heuristic as clear() and reuse if it's small enough. + raw_hash_set tmp(that, propagate_alloc ? that.alloc_ref() : alloc_ref()); + // NOLINTNEXTLINE: not returning *this for performance. + return assign_impl<propagate_alloc>(std::move(tmp)); } raw_hash_set& operator=(raw_hash_set&& that) noexcept( @@ -1879,19 +2261,7 @@ class raw_hash_set { typename AllocTraits::propagate_on_container_move_assignment()); } - ~raw_hash_set() { - const size_t cap = capacity(); - if (!cap) return; - destroy_slots(); - - // Unpoison before returning the memory to the allocator. - SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * cap); - Deallocate<BackingArrayAlignment(alignof(slot_type))>( - &alloc_ref(), common().backing_array_start(), - AllocSize(cap, sizeof(slot_type), alignof(slot_type))); - - infoz().Unregister(); - } + ~raw_hash_set() { destructor_impl(); } iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { auto it = iterator_at(0); @@ -1937,17 +2307,6 @@ class raw_hash_set { common().set_reservation_size(0); } - inline void destroy_slots() { - const size_t cap = capacity(); - const ctrl_t* ctrl = control(); - slot_type* slot = slot_array(); - for (size_t i = 0; i != cap; ++i) { - if (IsFull(ctrl[i])) { - PolicyTraits::destroy(&alloc_ref(), slot + i); - } - } - } - // This overload kicks in when the argument is an rvalue of insertable and // decomposable type other than init_type. // @@ -2075,7 +2434,7 @@ class raw_hash_set { alignas(slot_type) unsigned char raw[sizeof(slot_type)]; slot_type* slot = reinterpret_cast<slot_type*>(&raw); - PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...); + construct(slot, std::forward<Args>(args)...); const auto& elem = PolicyTraits::element(slot); return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem); } @@ -2179,8 +2538,8 @@ class raw_hash_set { // 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) { - AssertIsFull(it.ctrl_, it.generation(), it.generation_ptr(), "erase()"); - PolicyTraits::destroy(&alloc_ref(), it.slot_); + AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()"); + destroy(it.slot()); erase_meta_only(it); } @@ -2211,8 +2570,8 @@ class raw_hash_set { assert(this != &src); for (auto it = src.begin(), e = src.end(); it != e;) { auto next = std::next(it); - if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot_)}, - PolicyTraits::element(it.slot_)) + if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot())}, + PolicyTraits::element(it.slot())) .second) { src.erase_meta_only(it); } @@ -2226,10 +2585,9 @@ class raw_hash_set { } node_type extract(const_iterator position) { - AssertIsFull(position.inner_.ctrl_, position.inner_.generation(), + AssertIsFull(position.control(), position.inner_.generation(), position.inner_.generation_ptr(), "extract()"); - auto node = - CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_); + auto node = CommonAccess::Transfer<node_type>(alloc_ref(), position.slot()); erase_meta_only(position); return node; } @@ -2364,7 +2722,11 @@ class raw_hash_set { template <class K = key_type> bool contains(const key_arg<K>& key) const { - return find(key) != end(); + // Here neither the iterator returned by `find()` nor `end()` can be invalid + // outside of potential thread-safety issues. + // `find()`'s return value is constructed, used, and then destructed + // all in this context. + return !find(key).unchecked_equals(end()); } template <class K = key_type> @@ -2400,8 +2762,10 @@ class raw_hash_set { const raw_hash_set* outer = &a; const raw_hash_set* inner = &b; if (outer->capacity() > inner->capacity()) std::swap(outer, inner); - for (const value_type& elem : *outer) - if (!inner->has_element(elem)) return false; + for (const value_type& elem : *outer) { + auto it = PolicyTraits::apply(FindElement{*inner}, elem); + if (it == inner->end() || !(*it == elem)) return false; + } return true; } @@ -2471,10 +2835,9 @@ class raw_hash_set { std::pair<iterator, bool> operator()(const K& key, Args&&...) && { auto res = s.find_or_prepare_insert(key); if (res.second) { - PolicyTraits::transfer(&s.alloc_ref(), s.slot_array() + res.first, - &slot); + s.transfer(s.slot_array() + res.first, &slot); } else if (do_destroy) { - PolicyTraits::destroy(&s.alloc_ref(), &slot); + s.destroy(&slot); } return {s.iterator_at(res.first), res.second}; } @@ -2483,58 +2846,111 @@ 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)...); + } + inline void destroy(slot_type* slot) { + PolicyTraits::destroy(&alloc_ref(), slot); + } + inline void transfer(slot_type* to, slot_type* from) { + PolicyTraits::transfer(&alloc_ref(), to, from); + } + + inline void destroy_slots() { + const size_t cap = capacity(); + const ctrl_t* ctrl = control(); + slot_type* slot = slot_array(); + for (size_t i = 0; i != cap; ++i) { + if (IsFull(ctrl[i])) { + destroy(slot + i); + } + } + } + + inline void dealloc() { + assert(capacity() != 0); + // Unpoison before returning the memory to the allocator. + SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * capacity()); + infoz().Unregister(); + Deallocate<BackingArrayAlignment(alignof(slot_type))>( + &alloc_ref(), common().backing_array_start(), + common().alloc_size(sizeof(slot_type), alignof(slot_type))); + } + + inline void destructor_impl() { + if (capacity() == 0) return; + destroy_slots(); + dealloc(); + } + // Erases, but does not destroy, the value pointed to by `it`. // // 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) { - EraseMetaOnly(common(), it.inner_.ctrl_, sizeof(slot_type)); + EraseMetaOnly(common(), static_cast<size_t>(it.control() - control()), + sizeof(slot_type)); } - // Allocates a backing array for `self` and initializes its control bytes. - // This reads `capacity` and updates all other fields based on the result of - // the allocation. + // Resizes table to the new capacity and move all elements to the new + // positions accordingly. // - // This does not free the currently held array; `capacity` must be nonzero. - inline void initialize_slots() { - // People are often sloppy with the exact type of their allocator (sometimes - // it has an extra const or is missing the pair, but rebinds made it work - // anyway). - using CharAlloc = - typename absl::allocator_traits<Alloc>::template rebind_alloc<char>; - InitializeSlots<CharAlloc, sizeof(slot_type), alignof(slot_type)>( - common(), CharAlloc(alloc_ref())); - } - + // Note that for better performance instead of + // find_first_non_full(common(), hash), + // HashSetResizeHelper::FindFirstNonFullAfterResize( + // common(), old_capacity, hash) + // can be called right after `resize`. ABSL_ATTRIBUTE_NOINLINE void resize(size_t new_capacity) { assert(IsValidCapacity(new_capacity)); - auto* old_ctrl = control(); + HashSetResizeHelper resize_helper(common()); auto* old_slots = slot_array(); - const size_t old_capacity = common().capacity(); common().set_capacity(new_capacity); - initialize_slots(); - - auto* new_slots = slot_array(); - size_t total_probe_length = 0; - for (size_t i = 0; i != old_capacity; ++i) { - if (IsFull(old_ctrl[i])) { - size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, - PolicyTraits::element(old_slots + i)); - auto target = find_first_non_full(common(), hash); - size_t new_i = target.offset; - total_probe_length += target.probe_length; - SetCtrl(common(), new_i, H2(hash), sizeof(slot_type)); - PolicyTraits::transfer(&alloc_ref(), new_slots + new_i, old_slots + i); - } + // Note that `InitializeSlots` does different number initialization steps + // depending on the values of `transfer_uses_memcpy` and capacities. + // Refer to the comment in `InitializeSlots` for more details. + const bool grow_single_group = + resize_helper.InitializeSlots<CharAlloc, sizeof(slot_type), + PolicyTraits::transfer_uses_memcpy(), + alignof(slot_type)>( + common(), const_cast<std::remove_const_t<slot_type>*>(old_slots), + CharAlloc(alloc_ref())); + + if (resize_helper.old_capacity() == 0) { + // InitializeSlots did all the work including infoz().RecordRehash(). + return; } - if (old_capacity) { - SanitizerUnpoisonMemoryRegion(old_slots, - sizeof(slot_type) * old_capacity); - Deallocate<BackingArrayAlignment(alignof(slot_type))>( - &alloc_ref(), old_ctrl - ControlOffset(), - AllocSize(old_capacity, sizeof(slot_type), alignof(slot_type))); + + if (grow_single_group) { + if (PolicyTraits::transfer_uses_memcpy()) { + // InitializeSlots did all the work. + return; + } + // We want GrowSizeIntoSingleGroup to be called here in order to make + // InitializeSlots not depend on PolicyTraits. + resize_helper.GrowSizeIntoSingleGroup<PolicyTraits>(common(), alloc_ref(), + old_slots); + } else { + // InitializeSlots prepares control bytes to correspond to empty table. + auto* new_slots = slot_array(); + size_t total_probe_length = 0; + for (size_t i = 0; i != resize_helper.old_capacity(); ++i) { + if (IsFull(resize_helper.old_ctrl()[i])) { + size_t hash = PolicyTraits::apply( + HashElement{hash_ref()}, PolicyTraits::element(old_slots + i)); + auto target = find_first_non_full(common(), hash); + size_t new_i = target.offset; + total_probe_length += target.probe_length; + SetCtrl(common(), new_i, H2(hash), sizeof(slot_type)); + transfer(new_slots + new_i, old_slots + i); + } + } + infoz().RecordRehash(total_probe_length); } - infoz().RecordRehash(total_probe_length); + resize_helper.DeallocateOld<alignof(slot_type)>( + CharAlloc(alloc_ref()), sizeof(slot_type), + const_cast<std::remove_const_t<slot_type>*>(old_slots)); } // Prunes control bytes to remove as many tombstones as possible. @@ -2604,36 +3020,64 @@ class raw_hash_set { } } - bool has_element(const value_type& elem) const { - size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, elem); - auto seq = probe(common(), hash); - const ctrl_t* ctrl = control(); - while (true) { - Group g{ctrl + seq.offset()}; - for (uint32_t i : g.Match(H2(hash))) { - if (ABSL_PREDICT_TRUE( - PolicyTraits::element(slot_array() + seq.offset(i)) == elem)) - return true; - } - if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return false; - seq.next(); - assert(seq.index() <= capacity() && "full table!"); + void maybe_increment_generation_or_rehash_on_move() { + common().maybe_increment_generation_on_move(); + if (!empty() && common().should_rehash_for_bug_detection_on_move()) { + resize(capacity()); } - return false; } - // TODO(alkis): Optimize this assuming *this and that don't overlap. - raw_hash_set& move_assign(raw_hash_set&& that, std::true_type) { - raw_hash_set tmp(std::move(that)); - swap(tmp); + template<bool propagate_alloc> + raw_hash_set& assign_impl(raw_hash_set&& that) { + // We don't bother checking for this/that aliasing. We just need to avoid + // breaking the invariants in that case. + destructor_impl(); + 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{}; + maybe_increment_generation_or_rehash_on_move(); return *this; } - raw_hash_set& move_assign(raw_hash_set&& that, std::false_type) { - raw_hash_set tmp(std::move(that), alloc_ref()); - swap(tmp); + + raw_hash_set& move_elements_allocs_unequal(raw_hash_set&& that) { + const size_t size = that.size(); + if (size == 0) return *this; + reserve(size); + for (iterator it = that.begin(); it != that.end(); ++it) { + insert(std::move(PolicyTraits::element(it.slot()))); + that.destroy(it.slot()); + } + that.dealloc(); + that.common() = CommonFields{}; + maybe_increment_generation_or_rehash_on_move(); return *this; } + raw_hash_set& move_assign(raw_hash_set&& that, + std::true_type /*propagate_alloc*/) { + return assign_impl<true>(std::move(that)); + } + raw_hash_set& move_assign(raw_hash_set&& that, + std::false_type /*propagate_alloc*/) { + if (alloc_ref() == that.alloc_ref()) { + return assign_impl<false>(std::move(that)); + } + // Aliasing can't happen here because allocs would compare equal above. + assert(this != &that); + destructor_impl(); + // 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)); + } + protected: // Attempts to find `key` in the table; if it isn't found, returns a slot that // the value can be inserted into, with the control byte already set to @@ -2675,10 +3119,19 @@ class raw_hash_set { if (!rehash_for_bug_detection && ABSL_PREDICT_FALSE(growth_left() == 0 && !IsDeleted(control()[target.offset]))) { + size_t old_capacity = capacity(); rehash_and_grow_if_necessary(); - target = find_first_non_full(common(), hash); + // NOTE: It is safe to use `FindFirstNonFullAfterResize`. + // `FindFirstNonFullAfterResize` must be called right after resize. + // `rehash_and_grow_if_necessary` may *not* call `resize` + // and perform `drop_deletes_without_resize` instead. But this + // could happen only on big tables. + // For big tables `FindFirstNonFullAfterResize` will always + // fallback to normal `find_first_non_full`, so it is safe to use it. + target = HashSetResizeHelper::FindFirstNonFullAfterResize( + common(), old_capacity, hash); } - common().set_size(common().size() + 1); + common().increment_size(); set_growth_left(growth_left() - IsEmpty(control()[target.offset])); SetCtrl(common(), target.offset, H2(hash), sizeof(slot_type)); common().maybe_increment_generation_on_insert(); @@ -2696,8 +3149,7 @@ class raw_hash_set { // POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...). template <class... Args> void emplace_at(size_t i, Args&&... args) { - PolicyTraits::construct(&alloc_ref(), slot_array() + i, - std::forward<Args>(args)...); + construct(slot_array() + i, std::forward<Args>(args)...); assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) == iterator_at(i) && @@ -2711,6 +3163,8 @@ class raw_hash_set { return {control() + i, slot_array() + i, common().generation_ptr()}; } + reference unchecked_deref(iterator it) { return it.unchecked_deref(); } + private: friend struct RawHashSetTestOnlyAccess; @@ -2743,7 +3197,7 @@ class raw_hash_set { slot_type* slot_array() const { return static_cast<slot_type*>(common().slot_array()); } - HashtablezInfoHandle& infoz() { return common().infoz(); } + HashtablezInfoHandle infoz() { return common().infoz(); } hasher& hash_ref() { return settings_.template get<1>(); } const hasher& hash_ref() const { return settings_.template get<1>(); } @@ -2763,8 +3217,7 @@ class raw_hash_set { } static void transfer_slot_fn(void* set, void* dst, void* src) { auto* h = static_cast<raw_hash_set*>(set); - PolicyTraits::transfer(&h->alloc_ref(), static_cast<slot_type*>(dst), - static_cast<slot_type*>(src)); + h->transfer(static_cast<slot_type*>(dst), static_cast<slot_type*>(src)); } // Note: dealloc_fn will only be used if we have a non-standard allocator. static void dealloc_fn(CommonFields& common, const PolicyFunctions&) { @@ -2774,6 +3227,7 @@ class raw_hash_set { SanitizerUnpoisonMemoryRegion(common.slot_array(), sizeof(slot_type) * common.capacity()); + common.infoz().Unregister(); Deallocate<BackingArrayAlignment(alignof(slot_type))>( &set->alloc_ref(), common.backing_array_start(), common.alloc_size(sizeof(slot_type), alignof(slot_type))); @@ -2847,33 +3301,18 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> { static size_t AllocatedByteSize(const Set& c) { size_t capacity = c.capacity(); if (capacity == 0) return 0; - size_t m = AllocSize(capacity, sizeof(Slot), alignof(Slot)); + size_t m = c.common().alloc_size(sizeof(Slot), alignof(Slot)); size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr)); if (per_slot != ~size_t{}) { m += per_slot * c.size(); } else { - const ctrl_t* ctrl = c.control(); - for (size_t i = 0; i != capacity; ++i) { - if (container_internal::IsFull(ctrl[i])) { - m += Traits::space_used(c.slot_array() + i); - } + for (auto it = c.begin(); it != c.end(); ++it) { + m += Traits::space_used(it.slot()); } } return m; } - - static size_t LowerBoundAllocatedByteSize(size_t size) { - size_t capacity = GrowthToLowerboundCapacity(size); - if (capacity == 0) return 0; - size_t m = - AllocSize(NormalizeCapacity(capacity), sizeof(Slot), alignof(Slot)); - size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr)); - if (per_slot != ~size_t{}) { - m += per_slot * size; - } - return m; - } }; } // namespace hashtable_debug_internal 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 838380854f..d7eedd1ca4 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc @@ -189,8 +189,14 @@ CpuType GetAmdCpuType() { break; case 0x19: switch (model_num) { + case 0x0: // Stepping Ax case 0x1: // Stepping B0 return CpuType::kAmdMilan; + case 0x10: // Stepping A0 + case 0x11: // Stepping B0 + return CpuType::kAmdGenoa; + case 0x44: // Stepping A0 + return CpuType::kAmdRyzenV3000; default: return CpuType::kUnknown; } @@ -237,8 +243,26 @@ CpuType GetCpuType() { ABSL_INTERNAL_AARCH64_ID_REG_READ(MIDR_EL1, midr); uint32_t implementer = (midr >> 24) & 0xff; uint32_t part_number = (midr >> 4) & 0xfff; - if (implementer == 0x41 && part_number == 0xd0c) { - return CpuType::kArmNeoverseN1; + switch (implementer) { + case 0x41: + switch (part_number) { + case 0xd0c: return CpuType::kArmNeoverseN1; + case 0xd40: return CpuType::kArmNeoverseV1; + case 0xd49: return CpuType::kArmNeoverseN2; + case 0xd4f: return CpuType::kArmNeoverseV2; + default: + return CpuType::kUnknown; + } + break; + case 0xc0: + switch (part_number) { + case 0xac3: return CpuType::kAmpereSiryn; + default: + return CpuType::kUnknown; + } + break; + default: + return CpuType::kUnknown; } } return CpuType::kUnknown; diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h index 6054f6960d..01e19590ca 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h @@ -29,6 +29,8 @@ enum class CpuType { kAmdRome, kAmdNaples, kAmdMilan, + kAmdGenoa, + kAmdRyzenV3000, kIntelCascadelakeXeon, kIntelSkylakeXeon, kIntelBroadwell, @@ -37,6 +39,10 @@ enum class CpuType { kIntelSandybridge, kIntelWestmere, kArmNeoverseN1, + kArmNeoverseV1, + kAmpereSiryn, + kArmNeoverseN2, + kArmNeoverseV2 }; // Returns the type of host CPU this code is running on. Returns kUnknown if diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h index 39e53dd08e..59995ae3e2 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h @@ -59,6 +59,8 @@ namespace crc_internal { #if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) using V128 = uint64x2_t; #else +// Note: Do not use __m128i_u, it is not portable. +// Use V128_LoadU() perform an unaligned load from __m128i*. using V128 = __m128i; #endif @@ -78,6 +80,9 @@ V128 V128_Load(const V128* src); // Load 128 bits of integer data. |src| does not need to be aligned. V128 V128_LoadU(const V128* src); +// Store 128 bits of integer data. |src| must be 16-byte aligned. +void V128_Store(V128* dst, V128 data); + // Polynomially multiplies the high 64 bits of |l| and |r|. V128 V128_PMulHi(const V128 l, const V128 r); @@ -109,6 +114,10 @@ V128 V128_ShiftRight(const V128 l); template <int imm> int V128_Extract32(const V128 l); +// Extracts a 64-bit integer from |l|, selected with |imm|. +template <int imm> +uint64_t V128_Extract64(const V128 l); + // Extracts the low 64 bits from V128. int64_t V128_Low64(const V128 l); @@ -139,6 +148,8 @@ inline V128 V128_Load(const V128* src) { return _mm_load_si128(src); } inline V128 V128_LoadU(const V128* src) { return _mm_loadu_si128(src); } +inline void V128_Store(V128* dst, V128 data) { _mm_store_si128(dst, data); } + inline V128 V128_PMulHi(const V128 l, const V128 r) { return _mm_clmulepi64_si128(l, r, 0x11); } @@ -173,6 +184,11 @@ inline int V128_Extract32(const V128 l) { return _mm_extract_epi32(l, imm); } +template <int imm> +inline uint64_t V128_Extract64(const V128 l) { + return static_cast<uint64_t>(_mm_extract_epi64(l, imm)); +} + inline int64_t V128_Low64(const V128 l) { return _mm_cvtsi128_si64(l); } inline V128 V128_ShiftLeft64(const V128 l, const V128 r) { @@ -203,10 +219,14 @@ inline V128 V128_LoadU(const V128* src) { return vld1q_u64(reinterpret_cast<const uint64_t*>(src)); } +inline void V128_Store(V128* dst, V128 data) { + vst1q_u64(reinterpret_cast<uint64_t*>(dst), data); +} + // Using inline assembly as clang does not generate the pmull2 instruction and // performance drops by 15-20%. -// TODO(b/193678732): Investigate why the compiler decides not to generate -// such instructions and why it becomes so much worse. +// TODO(b/193678732): Investigate why there is a slight performance hit when +// using intrinsics instead of inline assembly. inline V128 V128_PMulHi(const V128 l, const V128 r) { uint64x2_t res; __asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t" @@ -215,10 +235,14 @@ inline V128 V128_PMulHi(const V128 l, const V128 r) { return res; } +// TODO(b/193678732): Investigate why the compiler decides to move the constant +// loop multiplicands from GPR to Neon registers every loop iteration. inline V128 V128_PMulLow(const V128 l, const V128 r) { - return reinterpret_cast<V128>(vmull_p64( - reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(l))), - reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(r))))); + uint64x2_t res; + __asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t" + : "=w"(res) + : "w"(l), "w"(r)); + return res; } inline V128 V128_PMul01(const V128 l, const V128 r) { @@ -252,6 +276,11 @@ inline int V128_Extract32(const V128 l) { return vgetq_lane_s32(vreinterpretq_s32_u64(l), imm); } +template <int imm> +inline uint64_t V128_Extract64(const V128 l) { + return vgetq_lane_u64(l, imm); +} + inline int64_t V128_Low64(const V128 l) { return vgetq_lane_s64(vreinterpretq_s64_u64(l), 0); } diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h index 4909d43366..a0fed65afa 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h @@ -20,12 +20,15 @@ #include "absl/base/config.h" #include "absl/crc/crc32c.h" +#include "absl/crc/internal/crc32_x86_arm_combined_simd.h" // Defined if the class AcceleratedCrcMemcpyEngine exists. -#if defined(__x86_64__) && defined(__SSE4_2__) -#define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1 -#elif defined(_MSC_VER) && defined(__AVX__) +// TODO(b/299127771): Consider relaxing the pclmul requirement once the other +// intrinsics are conditionally compiled without it. +#if defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD) #define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1 +#elif defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) +#define ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE 1 #endif namespace absl { diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc index 15b4b05594..07795504e3 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc @@ -54,7 +54,8 @@ absl::crc32c_t FallbackCrcMemcpyEngine::Compute(void* __restrict dst, } // Compile the following only if we don't have -#ifndef ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE +#if !defined(ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE) && \ + !defined(ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE) CrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() { CrcMemcpy::ArchSpecificEngines engines; @@ -68,7 +69,8 @@ std::unique_ptr<CrcMemcpyEngine> CrcMemcpy::GetTestEngine(int /*vector*/, return std::make_unique<FallbackCrcMemcpyEngine>(); } -#endif // ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE +#endif // !ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE && + // !ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE } // namespace crc_internal ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_arm_combined.cc index d42b08dc9f..968e9ae359 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_arm_combined.cc @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Simultaneous memcopy and CRC-32C for x86-64. Uses integer registers because -// XMM registers do not support the CRC instruction (yet). While copying, -// compute the running CRC of the data being copied. +// Simultaneous memcopy and CRC-32C for x86-64 and ARM 64. Uses integer +// registers because XMM registers do not support the CRC instruction (yet). +// While copying, compute the running CRC of the data being copied. // // It is assumed that any CPU running this code has SSE4.2 instructions // available (for CRC32C). This file will do nothing if that is not true. @@ -49,17 +49,20 @@ #include <array> #include <cstddef> #include <cstdint> -#include <type_traits> +#include <cstring> +#include <memory> -#include "absl/base/dynamic_annotations.h" +#include "absl/base/config.h" #include "absl/base/optimization.h" #include "absl/base/prefetch.h" #include "absl/crc/crc32c.h" #include "absl/crc/internal/cpu_detect.h" +#include "absl/crc/internal/crc32_x86_arm_combined_simd.h" #include "absl/crc/internal/crc_memcpy.h" #include "absl/strings/string_view.h" -#ifdef ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE +#if defined(ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE) || \ + defined(ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE) namespace absl { ABSL_NAMESPACE_BEGIN @@ -74,7 +77,7 @@ inline crc32c_t ShortCrcCopy(char* dst, const char* src, std::size_t length, uint32_t crc_uint32 = static_cast<uint32_t>(crc); for (std::size_t i = 0; i < length; i++) { uint8_t data = *reinterpret_cast<const uint8_t*>(src); - crc_uint32 = _mm_crc32_u8(crc_uint32, data); + crc_uint32 = CRC32_u8(crc_uint32, data); *reinterpret_cast<uint8_t*>(dst) = data; ++src; ++dst; @@ -82,36 +85,35 @@ inline crc32c_t ShortCrcCopy(char* dst, const char* src, std::size_t length, return crc32c_t{crc_uint32}; } -constexpr size_t kIntLoadsPerVec = sizeof(__m128i) / sizeof(uint64_t); +constexpr size_t kIntLoadsPerVec = sizeof(V128) / sizeof(uint64_t); // Common function for copying the tails of multiple large regions. template <size_t vec_regions, size_t int_regions> inline void LargeTailCopy(crc32c_t* crcs, char** dst, const char** src, size_t region_size, size_t copy_rounds) { - std::array<__m128i, vec_regions> data; + std::array<V128, vec_regions> data; std::array<uint64_t, kIntLoadsPerVec * int_regions> int_data; while (copy_rounds > 0) { for (size_t i = 0; i < vec_regions; i++) { size_t region = i; - auto* vsrc = - reinterpret_cast<const __m128i*>(*src + region_size * region); - auto* vdst = reinterpret_cast<__m128i*>(*dst + region_size * region); + auto* vsrc = reinterpret_cast<const V128*>(*src + region_size * region); + auto* vdst = reinterpret_cast<V128*>(*dst + region_size * region); // Load the blocks, unaligned - data[i] = _mm_loadu_si128(vsrc); + data[i] = V128_LoadU(vsrc); // Store the blocks, aligned - _mm_store_si128(vdst, data[i]); + V128_Store(vdst, data[i]); // Compute the running CRC crcs[region] = crc32c_t{static_cast<uint32_t>( - _mm_crc32_u64(static_cast<uint32_t>(crcs[region]), - static_cast<uint64_t>(_mm_extract_epi64(data[i], 0))))}; + CRC32_u64(static_cast<uint32_t>(crcs[region]), + static_cast<uint64_t>(V128_Extract64<0>(data[i]))))}; crcs[region] = crc32c_t{static_cast<uint32_t>( - _mm_crc32_u64(static_cast<uint32_t>(crcs[region]), - static_cast<uint64_t>(_mm_extract_epi64(data[i], 1))))}; + CRC32_u64(static_cast<uint32_t>(crcs[region]), + static_cast<uint64_t>(V128_Extract64<1>(data[i]))))}; } for (size_t i = 0; i < int_regions; i++) { @@ -125,7 +127,7 @@ inline void LargeTailCopy(crc32c_t* crcs, char** dst, const char** src, size_t data_index = i * kIntLoadsPerVec + j; int_data[data_index] = *(usrc + j); - crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64( + crcs[region] = crc32c_t{static_cast<uint32_t>(CRC32_u64( static_cast<uint32_t>(crcs[region]), int_data[data_index]))}; *(udst + j) = int_data[data_index]; @@ -133,8 +135,8 @@ inline void LargeTailCopy(crc32c_t* crcs, char** dst, const char** src, } // Increment pointers - *src += sizeof(__m128i); - *dst += sizeof(__m128i); + *src += sizeof(V128); + *dst += sizeof(V128); --copy_rounds; } } @@ -158,8 +160,9 @@ crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute( void* __restrict dst, const void* __restrict src, std::size_t length, crc32c_t initial_crc) const { constexpr std::size_t kRegions = vec_regions + int_regions; + static_assert(kRegions > 0, "Must specify at least one region."); constexpr uint32_t kCrcDataXor = uint32_t{0xffffffff}; - constexpr std::size_t kBlockSize = sizeof(__m128i); + constexpr std::size_t kBlockSize = sizeof(V128); constexpr std::size_t kCopyRoundSize = kRegions * kBlockSize; // Number of blocks per cacheline. @@ -235,7 +238,7 @@ crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute( const std::size_t tail_size = length - (kRegions * region_size); // Holding registers for data in each region. - std::array<__m128i, vec_regions> vec_data; + std::array<V128, vec_regions> vec_data; std::array<uint64_t, int_regions * kIntLoadsPerVec> int_data; // Main loop. @@ -243,7 +246,10 @@ crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute( // Prefetch kPrefetchAhead bytes ahead of each pointer. for (size_t i = 0; i < kRegions; i++) { absl::PrefetchToLocalCache(src_bytes + kPrefetchAhead + region_size * i); +#ifdef ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE + // TODO(b/297082454): investigate dropping prefetch on x86. absl::PrefetchToLocalCache(dst_bytes + kPrefetchAhead + region_size * i); +#endif } // Load and store data, computing CRC on the way. @@ -256,21 +262,20 @@ crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute( size_t region = (j + i) % kRegions; auto* vsrc = - reinterpret_cast<const __m128i*>(src_bytes + region_size * region); - auto* vdst = - reinterpret_cast<__m128i*>(dst_bytes + region_size * region); + reinterpret_cast<const V128*>(src_bytes + region_size * region); + auto* vdst = reinterpret_cast<V128*>(dst_bytes + region_size * region); // Load and CRC data. - vec_data[j] = _mm_loadu_si128(vsrc + i); - crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64( - static_cast<uint32_t>(crcs[region]), - static_cast<uint64_t>(_mm_extract_epi64(vec_data[j], 0))))}; - crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64( - static_cast<uint32_t>(crcs[region]), - static_cast<uint64_t>(_mm_extract_epi64(vec_data[j], 1))))}; + vec_data[j] = V128_LoadU(vsrc + i); + crcs[region] = crc32c_t{static_cast<uint32_t>( + CRC32_u64(static_cast<uint32_t>(crcs[region]), + static_cast<uint64_t>(V128_Extract64<0>(vec_data[j]))))}; + crcs[region] = crc32c_t{static_cast<uint32_t>( + CRC32_u64(static_cast<uint32_t>(crcs[region]), + static_cast<uint64_t>(V128_Extract64<1>(vec_data[j]))))}; // Store the data. - _mm_store_si128(vdst + i, vec_data[j]); + V128_Store(vdst + i, vec_data[j]); } // Preload the partial CRCs for the CLMUL subregions. @@ -290,7 +295,7 @@ crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute( // Load and CRC the data. int_data[data_index] = *(usrc + i * kIntLoadsPerVec + k); - crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64( + crcs[region] = crc32c_t{static_cast<uint32_t>(CRC32_u64( static_cast<uint32_t>(crcs[region]), int_data[data_index]))}; // Store the data. @@ -313,6 +318,21 @@ crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute( src_bytes += region_size * (kRegions - 1); dst_bytes += region_size * (kRegions - 1); + // Copy and CRC the tail through the XMM registers. + std::size_t tail_blocks = tail_size / kBlockSize; + LargeTailCopy<0, 1>(&crcs[kRegions - 1], &dst_bytes, &src_bytes, 0, + tail_blocks); + + // Final tail copy for under 16 bytes. + crcs[kRegions - 1] = + ShortCrcCopy(dst_bytes, src_bytes, tail_size - tail_blocks * kBlockSize, + crcs[kRegions - 1]); + + if (kRegions == 1) { + // If there is only one region, finalize and return its CRC. + return crc32c_t{static_cast<uint32_t>(crcs[0]) ^ kCrcDataXor}; + } + // Finalize the first CRCs: XOR the internal CRCs by the XOR mask to undo the // XOR done before doing block copy + CRCs. for (size_t i = 0; i + 1 < kRegions; i++) { @@ -325,16 +345,6 @@ crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute( full_crc = ConcatCrc32c(full_crc, crcs[i], region_size); } - // Copy and CRC the tail through the XMM registers. - std::size_t tail_blocks = tail_size / kBlockSize; - LargeTailCopy<0, 1>(&crcs[kRegions - 1], &dst_bytes, &src_bytes, 0, - tail_blocks); - - // Final tail copy for under 16 bytes. - crcs[kRegions - 1] = - ShortCrcCopy(dst_bytes, src_bytes, tail_size - tail_blocks * kBlockSize, - crcs[kRegions - 1]); - // Finalize and concatenate the final CRC, then return. crcs[kRegions - 1] = crc32c_t{static_cast<uint32_t>(crcs[kRegions - 1]) ^ kCrcDataXor}; @@ -347,9 +357,11 @@ CrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() { // Get the underlying architecture. CpuType cpu_type = GetCpuType(); switch (cpu_type) { - case CpuType::kUnknown: case CpuType::kAmdRome: case CpuType::kAmdNaples: + case CpuType::kAmdMilan: + case CpuType::kAmdGenoa: + case CpuType::kAmdRyzenV3000: case CpuType::kIntelCascadelakeXeon: case CpuType::kIntelSkylakeXeon: case CpuType::kIntelSkylake: @@ -385,6 +397,9 @@ CrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() { // strided access to each region, and do the right thing. case CpuType::kAmdRome: case CpuType::kAmdNaples: + case CpuType::kAmdMilan: + case CpuType::kAmdGenoa: + case CpuType::kAmdRyzenV3000: return { /*.temporal=*/new AcceleratedCrcMemcpyEngine<1, 2>(), /*.non_temporal=*/new CrcNonTemporalMemcpyAVXEngine(), @@ -421,6 +436,8 @@ std::unique_ptr<CrcMemcpyEngine> CrcMemcpy::GetTestEngine(int vector, return std::make_unique<AcceleratedCrcMemcpyEngine<3, 0>>(); } else if (vector == 1 && integer == 2) { return std::make_unique<AcceleratedCrcMemcpyEngine<1, 2>>(); + } else if (vector == 1 && integer == 0) { + return std::make_unique<AcceleratedCrcMemcpyEngine<1, 0>>(); } return nullptr; } @@ -429,4 +446,5 @@ std::unique_ptr<CrcMemcpyEngine> CrcMemcpy::GetTestEngine(int vector, ABSL_NAMESPACE_END } // namespace absl -#endif // ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE +#endif // ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE || + // ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc index ef521d22d1..51eff4eddc 100644 --- a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc +++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc @@ -16,14 +16,14 @@ #include <cstddef> #include <cstdint> +#include <memory> +#include <vector> #include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/base/dynamic_annotations.h" #include "absl/base/internal/endian.h" #include "absl/base/prefetch.h" #include "absl/crc/internal/cpu_detect.h" -#include "absl/crc/internal/crc.h" #include "absl/crc/internal/crc32_x86_arm_combined_simd.h" #include "absl/crc/internal/crc_internal.h" #include "absl/memory/memory.h" @@ -634,8 +634,16 @@ CRCImpl* TryNewCRC32AcceleratedX86ARMCombined() { return new CRC32AcceleratedX86ARMCombinedMultipleStreams< 3, 0, CutoffStrategy::Fold3>(); case CpuType::kArmNeoverseN1: + case CpuType::kArmNeoverseN2: + case CpuType::kArmNeoverseV1: return new CRC32AcceleratedX86ARMCombinedMultipleStreams< 1, 1, CutoffStrategy::Unroll64CRC>(); + case CpuType::kAmpereSiryn: + return new CRC32AcceleratedX86ARMCombinedMultipleStreams< + 3, 2, CutoffStrategy::Fold3>(); + case CpuType::kArmNeoverseV2: + return new CRC32AcceleratedX86ARMCombinedMultipleStreams< + 1, 2, CutoffStrategy::Unroll64CRC>(); #if defined(__aarch64__) default: // Not all ARM processors support the needed instructions, so check here 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 992c89c390..570d1e504d 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc +++ b/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc @@ -54,7 +54,7 @@ #include "absl/debugging/internal/examine_stack.h" #include "absl/debugging/stacktrace.h" -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__wasi__) #define ABSL_HAVE_SIGACTION // Apple WatchOS and TVOS don't allow sigaltstack // Apple macOS has sigaltstack, but using it makes backtrace() unusable. diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc b/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc index 91eaa76f8a..be17a10591 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc @@ -50,8 +50,10 @@ namespace debugging_internal { // NOTE: any new system calls here may also require sandbox reconfiguration. // bool AddressIsReadable(const void *addr) { - // Align address on 8-byte boundary. On aarch64, checking last - // byte before inaccessible page returned unexpected EFAULT. + // rt_sigprocmask below checks 8 contiguous bytes. If addr resides in the + // last 7 bytes of a page (unaligned), rt_sigprocmask would additionally + // check the readability of the next page, which is not desired. Align + // address on 8-byte boundary to check only the current page. const uintptr_t u_addr = reinterpret_cast<uintptr_t>(addr) & ~uintptr_t{7}; addr = reinterpret_cast<const void *>(u_addr); diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc index f2832915bf..381a2b504b 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc @@ -21,7 +21,15 @@ #include <cstdint> #include <cstdio> +#include <cstdlib> #include <limits> +#include <string> + +#include "absl/base/config.h" + +#if ABSL_INTERNAL_HAS_CXA_DEMANGLE +#include <cxxabi.h> +#endif namespace absl { ABSL_NAMESPACE_BEGIN @@ -1983,6 +1991,22 @@ bool Demangle(const char* mangled, char* out, size_t out_size) { state.parse_state.out_cur_idx > 0; } +std::string DemangleString(const char* mangled) { + std::string out; + int status = 0; + char* demangled = nullptr; +#if ABSL_INTERNAL_HAS_CXA_DEMANGLE + demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status); +#endif + if (status == 0 && demangled != nullptr) { + out.append(demangled); + free(demangled); + } else { + out.append(mangled); + } + return out; +} + } // namespace debugging_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h index e1f156989f..146d1150ef 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h +++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h @@ -12,13 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -// An async-signal-safe and thread-safe demangler for Itanium C++ ABI -// (aka G++ V3 ABI). +#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ +#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ + +#include <string> +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +// Demangle `mangled`. On success, return true and write the +// demangled symbol name to `out`. Otherwise, return false. +// `out` is modified even if demangling is unsuccessful. // -// The demangler is implemented to be used in async signal handlers to -// symbolize stack traces. We cannot use libstdc++'s -// abi::__cxa_demangle() in such signal handlers since it's not async -// signal safe (it uses malloc() internally). +// This function provides an alternative to libstdc++'s abi::__cxa_demangle, +// which is not async signal safe (it uses malloc internally). It's intended to +// be used in async signal handlers to symbolize stack traces. // // Note that this demangler doesn't support full demangling. More // specifically, it doesn't print types of function parameters and @@ -30,40 +40,32 @@ // // Example: // -// | Mangled Name | The Demangler | abi::__cxa_demangle() -// |---------------|---------------|----------------------- -// | _Z1fv | f() | f() -// | _Z1fi | f() | f(int) -// | _Z3foo3bar | foo() | foo(bar) -// | _Z1fIiEvi | f<>() | void f<int>(int) -// | _ZN1N1fE | N::f | N::f -// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar() -// | _Zrm1XS_" | operator%() | operator%(X, X) -// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo() -// | _Z1fSs | f() | f(std::basic_string<char, -// | | | std::char_traits<char>, -// | | | std::allocator<char> >) +// | Mangled Name | Demangle | DemangleString +// |---------------|-------------|----------------------- +// | _Z1fv | f() | f() +// | _Z1fi | f() | f(int) +// | _Z3foo3bar | foo() | foo(bar) +// | _Z1fIiEvi | f<>() | void f<int>(int) +// | _ZN1N1fE | N::f | N::f +// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar() +// | _Zrm1XS_" | operator%() | operator%(X, X) +// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo() +// | _Z1fSs | f() | f(std::basic_string<char, +// | | | std::char_traits<char>, +// | | | std::allocator<char> >) // // See the unit test for more examples. // // Note: we might want to write demanglers for ABIs other than Itanium // C++ ABI in the future. -// - -#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ -#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ - -#include "absl/base/config.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace debugging_internal { - -// Demangle `mangled`. On success, return true and write the -// demangled symbol name to `out`. Otherwise, return false. -// `out` is modified even if demangling is unsuccessful. bool Demangle(const char* mangled, char* out, size_t out_size); +// A wrapper around `abi::__cxa_demangle()`. On success, returns the demangled +// name. On failure, returns the input mangled name. +// +// This function is not async-signal-safe. +std::string DemangleString(const char* mangled); + } // namespace debugging_internal ABSL_NAMESPACE_END } // namespace absl 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 3f08716202..1caf7bbe35 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 @@ -4,6 +4,7 @@ // Generate stack tracer for aarch64 #if defined(__linux__) +#include <signal.h> #include <sys/mman.h> #include <ucontext.h> #include <unistd.h> @@ -70,7 +71,7 @@ static const unsigned char* GetKernelRtSigreturnAddress() { // Compute the size of a stack frame in [low..high). We assume that // low < high. Return size of kUnknownFrameSize. template<typename T> -static inline size_t ComputeStackFrameSize(const T* low, +static size_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); @@ -78,6 +79,20 @@ static inline size_t ComputeStackFrameSize(const T* low, : kUnknownFrameSize; } +// Saves stack info that is expensive to calculate to avoid recalculating per frame. +struct StackInfo { + uintptr_t stack_low; + uintptr_t stack_high; + uintptr_t sig_stack_low; + uintptr_t sig_stack_high; +}; + +static bool InsideSignalStack(void** ptr, const StackInfo* stack_info) { + uintptr_t comparable_ptr = reinterpret_cast<uintptr_t>(ptr); + return (comparable_ptr >= stack_info->sig_stack_low && + comparable_ptr < stack_info->sig_stack_high); +} + // Given a pointer to a stack frame, locate and return the calling // stackframe, or return null if no stackframe can be found. Perform sanity // checks (the strictness of which is controlled by the boolean parameter @@ -86,9 +101,8 @@ template<bool STRICT_UNWINDING, bool WITH_CONTEXT> ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack. ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack. static void **NextStackFrame(void **old_frame_pointer, const void *uc, - size_t stack_low, size_t stack_high) { + const StackInfo *stack_info) { void **new_frame_pointer = reinterpret_cast<void**>(*old_frame_pointer); - bool check_frame_size = true; #if defined(__linux__) if (WITH_CONTEXT && uc != nullptr) { @@ -114,10 +128,6 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc, if (!absl::debugging_internal::AddressIsReadable( new_frame_pointer)) return nullptr; - - // Skip frame size check if we return from a signal. We may be using a - // an alternate stack for signals. - check_frame_size = false; } } #endif @@ -126,9 +136,11 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc, if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 7) != 0) return nullptr; - // 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. - if (check_frame_size) { + // Only check the size if both frames are in the same stack. + if (InsideSignalStack(new_frame_pointer, stack_info) == + InsideSignalStack(old_frame_pointer, stack_info)) { + // 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 size_t max_size = STRICT_UNWINDING ? 100000 : 1000000; const size_t frame_size = ComputeStackFrameSize(old_frame_pointer, new_frame_pointer); @@ -136,15 +148,21 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc, return nullptr; // A very large frame may mean corrupt memory or an erroneous frame // pointer. But also maybe just a plain-old large frame. Assume that if the - // frame is within the known stack, then it is valid. + // frame is within a known stack, then it is valid. if (frame_size > max_size) { - if (stack_high < kUnknownStackEnd && + size_t stack_low = stack_info->stack_low; + size_t stack_high = stack_info->stack_high; + if (InsideSignalStack(new_frame_pointer, stack_info)) { + stack_low = stack_info->sig_stack_low; + stack_high = stack_info->sig_stack_high; + } + if (stack_high < kUnknownStackEnd && static_cast<size_t>(getpagesize()) < stack_low) { const uintptr_t new_fp_u = reinterpret_cast<uintptr_t>(new_frame_pointer); // Stack bounds are known. if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) { - // new_frame_pointer is not within the known stack. + // new_frame_pointer is not within a known stack. return nullptr; } } else { @@ -158,6 +176,9 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc, } 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 +ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack. ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack. static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, @@ -171,8 +192,11 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, int n = 0; // Assume that the first page is not stack. - size_t stack_low = static_cast<size_t>(getpagesize()); - size_t stack_high = kUnknownStackEnd; + StackInfo stack_info; + stack_info.stack_low = static_cast<uintptr_t>(getpagesize()); + stack_info.stack_high = kUnknownStackEnd; + stack_info.sig_stack_low = stack_info.stack_low; + stack_info.sig_stack_high = kUnknownStackEnd; // The frame pointer points to low address of a frame. The first 64-bit // word of a frame points to the next frame up the call chain, which normally @@ -207,7 +231,7 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, // that is as complete as possible (even if it contains a few bogus // entries in some rare cases). frame_pointer = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>( - frame_pointer, ucp, stack_low, stack_high); + frame_pointer, ucp, &stack_info); } if (min_dropped_frames != nullptr) { @@ -222,7 +246,7 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, num_dropped_frames++; } frame_pointer = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>( - frame_pointer, ucp, stack_low, stack_high); + frame_pointer, ucp, &stack_info); } *min_dropped_frames = num_dropped_frames; } diff --git a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc index 30638cb2dc..ae75cd4153 100644 --- a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc +++ b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc @@ -289,6 +289,30 @@ ObjFile *AddrMap::Add() { return new (&obj_[size_++]) ObjFile; } +class CachingFile { + public: + // Setup reader for fd that uses buf[0, buf_size-1] as a cache. + CachingFile(int fd, char *buf, size_t buf_size) + : fd_(fd), + cache_(buf), + cache_size_(buf_size), + cache_start_(0), + cache_limit_(0) {} + + int fd() const { return fd_; } + ssize_t ReadFromOffset(void *buf, size_t count, off_t offset); + bool ReadFromOffsetExact(void *buf, size_t count, off_t offset); + + private: + // Bytes [cache_start_, cache_limit_-1] from fd_ are stored in + // a prefix of cache_[0, cache_size_-1]. + int fd_; + char *cache_; + size_t cache_size_; + off_t cache_start_; + off_t cache_limit_; +}; + // --------------------------------------------------------------- enum FindSymbolResult { SYMBOL_NOT_FOUND = 1, SYMBOL_TRUNCATED, SYMBOL_FOUND }; @@ -330,6 +354,7 @@ class Symbolizer { SYMBOL_BUF_SIZE = 3072, TMP_BUF_SIZE = 1024, SYMBOL_CACHE_LINES = 128, + FILE_CACHE_SIZE = 8192, }; AddrMap addr_map_; @@ -338,6 +363,7 @@ class Symbolizer { bool addr_map_read_; char symbol_buf_[SYMBOL_BUF_SIZE]; + char file_cache_[FILE_CACHE_SIZE]; // tmp_buf_ will be used to store arrays of ElfW(Shdr) and ElfW(Sym) // so we ensure that tmp_buf_ is properly aligned to store either. @@ -436,34 +462,58 @@ static ssize_t ReadPersistent(int fd, void *buf, size_t count) { return static_cast<ssize_t>(num_bytes); } -// Read up to "count" bytes from "offset" in the file pointed by file -// descriptor "fd" into the buffer starting at "buf". On success, -// return the number of bytes read. Otherwise, return -1. -static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count, - const off_t offset) { - off_t off = lseek(fd, offset, SEEK_SET); - if (off == (off_t)-1) { - ABSL_RAW_LOG(WARNING, "lseek(%d, %jd, SEEK_SET) failed: errno=%d", fd, - static_cast<intmax_t>(offset), errno); - return -1; +// Read up to "count" bytes from "offset" into the buffer starting at "buf", +// while handling short reads and EINTR. On success, return the number of bytes +// read. Otherwise, return -1. +ssize_t CachingFile::ReadFromOffset(void *buf, size_t count, off_t offset) { + char *dst = static_cast<char *>(buf); + size_t read = 0; + while (read < count) { + // Look in cache first. + if (offset >= cache_start_ && offset < cache_limit_) { + const char *hit_start = &cache_[offset - cache_start_]; + const size_t n = + std::min(count - read, static_cast<size_t>(cache_limit_ - offset)); + memcpy(dst, hit_start, n); + dst += n; + read += static_cast<size_t>(n); + offset += static_cast<off_t>(n); + continue; + } + + cache_start_ = 0; + cache_limit_ = 0; + ssize_t n = pread(fd_, cache_, cache_size_, offset); + if (n < 0) { + if (errno == EINTR) { + continue; + } + ABSL_RAW_LOG(WARNING, "read failed: errno=%d", errno); + return -1; + } + if (n == 0) { // Reached EOF. + break; + } + + cache_start_ = offset; + cache_limit_ = offset + static_cast<off_t>(n); + // Next iteration will copy from cache into dst. } - return ReadPersistent(fd, buf, count); + return static_cast<ssize_t>(read); } -// Try reading exactly "count" bytes from "offset" bytes in a file -// pointed by "fd" into the buffer starting at "buf" while handling -// short reads and EINTR. On success, return true. Otherwise, return -// false. -static bool ReadFromOffsetExact(const int fd, void *buf, const size_t count, - const off_t offset) { - ssize_t len = ReadFromOffset(fd, buf, count, offset); +// Try reading exactly "count" bytes from "offset" bytes into the buffer +// starting at "buf" while handling short reads and EINTR. On success, return +// true. Otherwise, return false. +bool CachingFile::ReadFromOffsetExact(void *buf, size_t count, off_t offset) { + ssize_t len = ReadFromOffset(buf, count, offset); return len >= 0 && static_cast<size_t>(len) == count; } // Returns elf_header.e_type if the file pointed by fd is an ELF binary. -static int FileGetElfType(const int fd) { +static int FileGetElfType(CachingFile *file) { ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { + if (!file->ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) { return -1; } if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) { @@ -478,8 +528,8 @@ static int FileGetElfType(const int fd) { // To keep stack consumption low, we would like this function to not get // inlined. static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType( - const int fd, ElfW(Half) sh_num, const off_t sh_offset, ElfW(Word) type, - ElfW(Shdr) * out, char *tmp_buf, size_t tmp_buf_size) { + CachingFile *file, ElfW(Half) sh_num, const off_t sh_offset, + ElfW(Word) type, ElfW(Shdr) * out, char *tmp_buf, size_t tmp_buf_size) { ElfW(Shdr) *buf = reinterpret_cast<ElfW(Shdr) *>(tmp_buf); const size_t buf_entries = tmp_buf_size / sizeof(buf[0]); const size_t buf_bytes = buf_entries * sizeof(buf[0]); @@ -490,7 +540,7 @@ static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType( const size_t num_bytes_to_read = (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 = ReadFromOffset(fd, buf, num_bytes_to_read, offset); + const ssize_t len = file->ReadFromOffset(buf, num_bytes_to_read, offset); if (len < 0) { ABSL_RAW_LOG( WARNING, @@ -524,11 +574,17 @@ static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType( // but there has (as yet) been no need for anything longer either. const int kMaxSectionNameLen = 64; +// Small cache to use for miscellaneous file reads. +const int kSmallFileCacheSize = 100; + bool ForEachSection(int fd, const std::function<bool(absl::string_view name, const ElfW(Shdr) &)> &callback) { + char buf[kSmallFileCacheSize]; + CachingFile file(fd, buf, sizeof(buf)); + ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { + if (!file.ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) { return false; } @@ -540,7 +596,7 @@ bool ForEachSection(int fd, ElfW(Shdr) shstrtab; off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * elf_header.e_shstrndx; - if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) { + if (!file.ReadFromOffsetExact(&shstrtab, sizeof(shstrtab), shstrtab_offset)) { return false; } @@ -548,13 +604,13 @@ bool ForEachSection(int fd, ElfW(Shdr) out; off_t section_header_offset = static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i; - if (!ReadFromOffsetExact(fd, &out, sizeof(out), section_header_offset)) { + if (!file.ReadFromOffsetExact(&out, sizeof(out), section_header_offset)) { return false; } off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out.sh_name; char header_name[kMaxSectionNameLen]; ssize_t n_read = - ReadFromOffset(fd, &header_name, kMaxSectionNameLen, name_offset); + file.ReadFromOffset(&header_name, kMaxSectionNameLen, name_offset); if (n_read < 0) { return false; } else if (n_read > kMaxSectionNameLen) { @@ -584,8 +640,10 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, return false; } + char buf[kSmallFileCacheSize]; + CachingFile file(fd, buf, sizeof(buf)); ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { + if (!file.ReadFromOffsetExact(&elf_header, sizeof(elf_header), 0)) { return false; } @@ -597,18 +655,18 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, ElfW(Shdr) shstrtab; off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * elf_header.e_shstrndx; - if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) { + if (!file.ReadFromOffsetExact(&shstrtab, sizeof(shstrtab), shstrtab_offset)) { return false; } for (int i = 0; i < elf_header.e_shnum; ++i) { off_t section_header_offset = static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i; - if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) { + if (!file.ReadFromOffsetExact(out, sizeof(*out), section_header_offset)) { return false; } off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out->sh_name; - ssize_t n_read = ReadFromOffset(fd, &header_name, name_len, name_offset); + ssize_t n_read = file.ReadFromOffset(&header_name, name_len, name_offset); if (n_read < 0) { return false; } else if (static_cast<size_t>(n_read) != name_len) { @@ -683,7 +741,7 @@ static const char *ComputeOffset(const char *base, ptrdiff_t offset) { // To keep stack consumption low, we would like this function to not get // inlined. static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol( - const void *const pc, const int fd, char *out, size_t out_size, + const void *const pc, CachingFile *file, char *out, size_t out_size, ptrdiff_t relocation, const ElfW(Shdr) * strtab, const ElfW(Shdr) * symtab, const ElfW(Shdr) * opd, char *tmp_buf, size_t tmp_buf_size) { if (symtab == nullptr) { @@ -716,7 +774,7 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol( const size_t entries_in_chunk = std::min(num_remaining_symbols, buf_entries); const size_t bytes_in_chunk = entries_in_chunk * sizeof(buf[0]); - const ssize_t len = ReadFromOffset(fd, buf, bytes_in_chunk, offset); + const ssize_t len = file->ReadFromOffset(buf, bytes_in_chunk, offset); SAFE_ASSERT(len >= 0); SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0); const size_t num_symbols_in_buf = static_cast<size_t>(len) / sizeof(buf[0]); @@ -772,12 +830,12 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol( if (found_match) { const off_t off = static_cast<off_t>(strtab->sh_offset) + best_match.st_name; - const ssize_t n_read = ReadFromOffset(fd, out, out_size, off); + const ssize_t n_read = file->ReadFromOffset(out, out_size, off); if (n_read <= 0) { // This should never happen. ABSL_RAW_LOG(WARNING, - "Unable to read from fd %d at offset %lld: n_read = %zd", fd, - static_cast<long long>(off), n_read); + "Unable to read from fd %d at offset %lld: n_read = %zd", + file->fd(), static_cast<long long>(off), n_read); return SYMBOL_NOT_FOUND; } ABSL_RAW_CHECK(static_cast<size_t>(n_read) <= out_size, @@ -827,22 +885,24 @@ FindSymbolResult Symbolizer::GetSymbolFromObjectFile( } } + CachingFile file(obj.fd, file_cache_, sizeof(file_cache_)); + // Consult a regular symbol table, then fall back to the dynamic symbol table. for (const auto symbol_table_type : {SHT_SYMTAB, SHT_DYNSYM}) { - if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum, + if (!GetSectionHeaderByType(&file, obj.elf_header.e_shnum, static_cast<off_t>(obj.elf_header.e_shoff), static_cast<ElfW(Word)>(symbol_table_type), &symtab, tmp_buf, tmp_buf_size)) { continue; } - if (!ReadFromOffsetExact( - obj.fd, &strtab, sizeof(strtab), + if (!file.ReadFromOffsetExact( + &strtab, sizeof(strtab), static_cast<off_t>(obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab)))) { continue; } const FindSymbolResult rc = - FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab, + FindSymbol(pc, &file, out, out_size, relocation, &strtab, &symtab, opd_ptr, tmp_buf, tmp_buf_size); if (rc != SYMBOL_NOT_FOUND) { return rc; @@ -1323,15 +1383,19 @@ static bool MaybeInitializeObjFile(ObjFile *obj) { ABSL_RAW_LOG(WARNING, "%s: open failed: errno=%d", obj->filename, errno); return false; } - obj->elf_type = FileGetElfType(obj->fd); + + char buf[kSmallFileCacheSize]; + CachingFile file(obj->fd, buf, sizeof(buf)); + + obj->elf_type = FileGetElfType(&file); if (obj->elf_type < 0) { ABSL_RAW_LOG(WARNING, "%s: wrong elf type: %d", obj->filename, obj->elf_type); return false; } - if (!ReadFromOffsetExact(obj->fd, &obj->elf_header, sizeof(obj->elf_header), - 0)) { + if (!file.ReadFromOffsetExact(&obj->elf_header, sizeof(obj->elf_header), + 0)) { ABSL_RAW_LOG(WARNING, "%s: failed to read elf header", obj->filename); return false; } @@ -1341,7 +1405,7 @@ static bool MaybeInitializeObjFile(ObjFile *obj) { size_t num_interesting_load_segments = 0; for (int j = 0; j < phnum; j++) { ElfW(Phdr) phdr; - if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) { + if (!file.ReadFromOffsetExact(&phdr, sizeof(phdr), phoff)) { ABSL_RAW_LOG(WARNING, "%s: failed to read program header %d", obj->filename, j); return false; diff --git a/contrib/restricted/abseil-cpp/absl/flags/declare.h b/contrib/restricted/abseil-cpp/absl/flags/declare.h index d1437bb9f6..8d2a856e3b 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/declare.h +++ b/contrib/restricted/abseil-cpp/absl/flags/declare.h @@ -40,13 +40,8 @@ class Flag; // Flag // // Forward declaration of the `absl::Flag` type for use in defining the macro. -#if defined(_MSC_VER) && !defined(__clang__) -template <typename T> -class Flag; -#else template <typename T> using Flag = flags_internal::Flag<T>; -#endif ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/flags/flag.h b/contrib/restricted/abseil-cpp/absl/flags/flag.h index b7f94be7c5..06ea6932f9 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/flag.h +++ b/contrib/restricted/abseil-cpp/absl/flags/flag.h @@ -71,12 +71,9 @@ ABSL_NAMESPACE_BEGIN // For type support of Abseil Flags, see the marshalling.h header file, which // discusses supported standard types, optional flags, and additional Abseil // type support. -#if !defined(_MSC_VER) || defined(__clang__) + template <typename T> using Flag = flags_internal::Flag<T>; -#else -#include "absl/flags/internal/flag_msvc.inc" -#endif // GetFlag() // @@ -196,18 +193,12 @@ ABSL_NAMESPACE_END // ----------------------------------------------------------------------------- // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES -#if !defined(_MSC_VER) || defined(__clang__) #define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag #define ABSL_FLAG_IMPL_HELP_ARG(name) \ absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \ FLAGS_help_storage_##name) #define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \ absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0) -#else -#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl() -#define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst -#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen -#endif #if ABSL_FLAGS_STRIP_NAMES #define ABSL_FLAG_IMPL_FLAGNAME(txt) "" diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h index b41f9a69f8..2e6e6b8742 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.h @@ -54,13 +54,8 @@ template <typename T> class Flag; } // namespace flags_internal -#if defined(_MSC_VER) && !defined(__clang__) -template <typename T> -class Flag; -#else template <typename T> using Flag = flags_internal::Flag<T>; -#endif template <typename T> ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag); diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/flag_msvc.inc b/contrib/restricted/abseil-cpp/absl/flags/internal/flag_msvc.inc deleted file mode 100644 index 614d09fd1a..0000000000 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/flag_msvc.inc +++ /dev/null @@ -1,116 +0,0 @@ -// -// Copyright 2021 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. - -// Do not include this file directly. -// Include absl/flags/flag.h instead. - -// MSVC debug builds do not implement initialization with constexpr constructors -// correctly. To work around this we add a level of indirection, so that the -// class `absl::Flag` contains an `internal::Flag*` (instead of being an alias -// to that class) and dynamically allocates an instance when necessary. We also -// forward all calls to internal::Flag methods via trampoline methods. In this -// setup the `absl::Flag` class does not have constructor and virtual methods, -// all the data members are public and thus MSVC is able to initialize it at -// link time. To deal with multiple threads accessing the flag for the first -// time concurrently we use an atomic boolean indicating if flag object is -// initialized. We also employ the double-checked locking pattern where the -// second level of protection is a global Mutex, so if two threads attempt to -// construct the flag concurrently only one wins. -// -// This solution is based on a recommendation here: -// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454 - -namespace flags_internal { -absl::Mutex* GetGlobalConstructionGuard(); -} // namespace flags_internal - -// Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API. -// See https://abseil.io/docs/cpp/guides/flags -template <typename T> -class Flag { - public: - // No constructor and destructor to ensure this is an aggregate type. - // Visual Studio 2015 still requires the constructor for class to be - // constexpr initializable. -#if _MSC_VER <= 1900 - constexpr Flag(const char* name, const char* filename, - const flags_internal::HelpGenFunc help_gen, - const flags_internal::FlagDfltGenFunc default_value_gen) - : name_(name), - filename_(filename), - help_gen_(help_gen), - default_value_gen_(default_value_gen), - inited_(false), - impl_(nullptr) {} -#endif - - flags_internal::Flag<T>& GetImpl() const { - if (!inited_.load(std::memory_order_acquire)) { - absl::MutexLock l(flags_internal::GetGlobalConstructionGuard()); - - if (inited_.load(std::memory_order_acquire)) { - return *impl_; - } - - impl_ = new flags_internal::Flag<T>( - name_, filename_, - {flags_internal::FlagHelpMsg(help_gen_), - flags_internal::FlagHelpKind::kGenFunc}, - {flags_internal::FlagDefaultSrc(default_value_gen_), - flags_internal::FlagDefaultKind::kGenFunc}); - inited_.store(true, std::memory_order_release); - } - - return *impl_; - } - - // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API. - // See https://abseil.io/docs/cpp/guides/flags - bool IsRetired() const { return GetImpl().IsRetired(); } - absl::string_view Name() const { return GetImpl().Name(); } - std::string Help() const { return GetImpl().Help(); } - bool IsModified() const { return GetImpl().IsModified(); } - bool IsSpecifiedOnCommandLine() const { - return GetImpl().IsSpecifiedOnCommandLine(); - } - std::string Filename() const { return GetImpl().Filename(); } - std::string DefaultValue() const { return GetImpl().DefaultValue(); } - std::string CurrentValue() const { return GetImpl().CurrentValue(); } - template <typename U> - inline bool IsOfType() const { - return GetImpl().template IsOfType<U>(); - } - T Get() const { - return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl()); - } - void Set(const T& v) { - flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v); - } - void InvokeCallback() { GetImpl().InvokeCallback(); } - - const CommandLineFlag& Reflect() const { - return flags_internal::FlagImplPeer::InvokeReflect(GetImpl()); - } - - // The data members are logically private, but they need to be public for - // this to be an aggregate type. - const char* name_; - const char* filename_; - const flags_internal::HelpGenFunc help_gen_; - const flags_internal::FlagDfltGenFunc default_value_gen_; - - mutable std::atomic<bool> inited_; - mutable flags_internal::Flag<T>* impl_; -}; diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc b/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc index 13852e1467..8b169bcdc2 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc @@ -27,7 +27,10 @@ #include <utility> #include <vector> +#include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/const_init.h" +#include "absl/base/thread_annotations.h" #include "absl/flags/commandlineflag.h" #include "absl/flags/flag.h" #include "absl/flags/internal/flag.h" @@ -40,6 +43,8 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" +#include "absl/strings/strip.h" +#include "absl/synchronization/mutex.h" // Dummy global variables to prevent anyone else defining these. bool FLAGS_help = false; diff --git a/contrib/restricted/abseil-cpp/absl/flags/marshalling.cc b/contrib/restricted/abseil-cpp/absl/flags/marshalling.cc index dc69754f00..ca4a130572 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/marshalling.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/marshalling.cc @@ -247,6 +247,14 @@ bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst, *err = "no value provided"; return false; } + if (absl::EqualsIgnoreCase(text, "dfatal")) { + *dst = absl::kLogDebugFatal; + return true; + } + if (absl::EqualsIgnoreCase(text, "klogdebugfatal")) { + *dst = absl::kLogDebugFatal; + return true; + } if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1); if (absl::EqualsIgnoreCase(text, "info")) { *dst = absl::LogSeverity::kInfo; @@ -269,7 +277,8 @@ bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst, *dst = static_cast<absl::LogSeverity>(numeric_value); return true; } - *err = "only integers and absl::LogSeverity enumerators are accepted"; + *err = + "only integers, absl::LogSeverity enumerators, and DFATAL are accepted"; return false; } diff --git a/contrib/restricted/abseil-cpp/absl/flags/parse.cc b/contrib/restricted/abseil-cpp/absl/flags/parse.cc index 4cdd9d0ad3..526b61d1d1 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/parse.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/parse.cc @@ -637,7 +637,7 @@ void ReportUnrecognizedFlags( // -------------------------------------------------------------------- bool WasPresentOnCommandLine(absl::string_view flag_name) { - absl::MutexLock l(&specified_flags_guard); + absl::ReaderMutexLock l(&specified_flags_guard); ABSL_INTERNAL_CHECK(specified_flags != nullptr, "ParseCommandLine is not invoked yet"); diff --git a/contrib/restricted/abseil-cpp/absl/flags/reflection.cc b/contrib/restricted/abseil-cpp/absl/flags/reflection.cc index dbce4032ab..841921a926 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/reflection.cc +++ b/contrib/restricted/abseil-cpp/absl/flags/reflection.cc @@ -21,6 +21,7 @@ #include <string> #include "absl/base/config.h" +#include "absl/base/no_destructor.h" #include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_map.h" #include "absl/flags/commandlineflag.h" @@ -169,7 +170,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag, const char* filename) { } FlagRegistry& FlagRegistry::GlobalRegistry() { - static FlagRegistry* global_registry = new FlagRegistry; + static absl::NoDestructor<FlagRegistry> global_registry; return *global_registry; } diff --git a/contrib/restricted/abseil-cpp/absl/flags/ya.make b/contrib/restricted/abseil-cpp/absl/flags/ya.make index f0006d104f..7e6fae43d6 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/ya.make +++ b/contrib/restricted/abseil-cpp/absl/flags/ya.make @@ -30,7 +30,6 @@ NO_UTIL() SRCS( commandlineflag.cc - flag.cc internal/commandlineflag.cc internal/flag.cc internal/private_handle_accessor.cc diff --git a/contrib/restricted/abseil-cpp/absl/functional/function_ref.h b/contrib/restricted/abseil-cpp/absl/functional/function_ref.h index 2b9139d374..96cece551b 100644 --- a/contrib/restricted/abseil-cpp/absl/functional/function_ref.h +++ b/contrib/restricted/abseil-cpp/absl/functional/function_ref.h @@ -137,6 +137,14 @@ class FunctionRef<R(Args...)> { absl::functional_internal::Invoker<R, Args...> invoker_; }; +// Allow const qualified function signatures. Since FunctionRef requires +// constness anyway we can just make this a no-op. +template <typename R, typename... Args> +class FunctionRef<R(Args...) const> : public FunctionRef<R(Args...)> { + public: + using FunctionRef<R(Args...)>::FunctionRef; +}; + ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/functional/internal/any_invocable.h b/contrib/restricted/abseil-cpp/absl/functional/internal/any_invocable.h index f096bb02e1..b04436d1d6 100644 --- a/contrib/restricted/abseil-cpp/absl/functional/internal/any_invocable.h +++ b/contrib/restricted/abseil-cpp/absl/functional/internal/any_invocable.h @@ -215,8 +215,8 @@ T& ObjectInLocalStorage(TypeErasedState* const state) { // behavior, which works as intended on Abseil's officially supported // platforms as of Q2 2022. #if !defined(__clang__) && defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wstrict-aliasing" #pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif return *reinterpret_cast<T*>(&state->storage); #if !defined(__clang__) && defined(__GNUC__) @@ -526,10 +526,10 @@ class CoreImpl { // Since this is template-heavy code, we prefer to disable these warnings // locally instead of adding yet another overload of this function. #if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Waddress" #pragma GCC diagnostic ignored "-Wnonnull-compare" -#pragma GCC diagnostic push #endif if (static_cast<RemoveCVRef<QualDecayedTRef>>(f) == nullptr) { #if !defined(__clang__) && defined(__GNUC__) diff --git a/contrib/restricted/abseil-cpp/absl/functional/ya.make b/contrib/restricted/abseil-cpp/absl/functional/ya.make index 3b66e3e400..3f9af85fe6 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(20230802.1) +VERSION(20240116.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240116.0.tar.gz) NO_RUNTIME() diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h index ef3f366471..f4a94f9129 100644 --- a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h +++ b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h @@ -19,6 +19,11 @@ #ifndef ABSL_HASH_INTERNAL_HASH_H_ #define ABSL_HASH_INTERNAL_HASH_H_ +#ifdef __APPLE__ +#include <Availability.h> +#include <TargetConditionals.h> +#endif + #include <algorithm> #include <array> #include <bitset> @@ -56,6 +61,11 @@ #include "absl/types/variant.h" #include "absl/utility/utility.h" +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \ + !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) +#include <filesystem> // NOLINT +#endif + #ifdef ABSL_HAVE_STD_STRING_VIEW #include <string_view> #endif @@ -409,9 +419,23 @@ AbslHashValue(H hash_state, LongDouble value) { return H::combine(std::move(hash_state), category); } +// Without this overload, an array decays to a pointer and we hash that, which +// is not likely to be what the caller intended. +template <typename H, typename T, size_t N> +H AbslHashValue(H hash_state, T (&)[N]) { + static_assert( + sizeof(T) == -1, + "Hashing C arrays is not allowed. For string literals, wrap the literal " + "in absl::string_view(). To hash the array contents, use " + "absl::MakeSpan() or make the array an std::array. To hash the array " + "address, use &array[0]."); + return hash_state; +} + // AbslHashValue() for hashing pointers template <typename H, typename T> -H AbslHashValue(H hash_state, T* ptr) { +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. @@ -564,6 +588,29 @@ 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) + +#define ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE 1 + +// Support std::filesystem::path. The SFINAE is required because some string +// types are implicitly convertible to std::filesystem::path. +template <typename Path, typename H, + typename = absl::enable_if_t< + std::is_same_v<Path, std::filesystem::path>>> +H AbslHashValue(H hash_state, const Path& path) { + // This is implemented by deferring to the standard library to compute the + // hash. The standard library requires that for two paths, `p1 == p2`, then + // `hash_value(p1) == hash_value(p2)`. `AbslHashValue` has the same + // requirement. Since `operator==` does platform specific matching, deferring + // to the standard library is the simplest approach. + return H::combine(std::move(hash_state), std::filesystem::hash_value(path)); +} + +#endif // ABSL_INTERNAL_STD_FILESYSTEM_PATH_HASH_AVAILABLE + // ----------------------------------------------------------------------------- // AbslHashValue for Sequence Containers // ----------------------------------------------------------------------------- @@ -818,7 +865,7 @@ AbslHashValue(H hash_state, const absl::variant<T...>& v) { template <typename H, size_t N> H AbslHashValue(H hash_state, const std::bitset<N>& set) { typename H::AbslInternalPiecewiseCombiner combiner; - for (int i = 0; i < N; i++) { + for (size_t i = 0; i < N; i++) { unsigned char c = static_cast<unsigned char>(set[i]); hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c)); } 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 new file mode 100644 index 0000000000..29096b4857 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/log/absl_vlog_is_on.h @@ -0,0 +1,93 @@ +// Copyright 2022 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: log/absl_vlog_is_on.h +// ----------------------------------------------------------------------------- +// +// This header defines the `ABSL_VLOG_IS_ON()` macro that controls the +// variable-verbosity conditional logging. +// +// It's used by `VLOG` in log.h, or it can also be used directly like this: +// +// if (ABSL_VLOG_IS_ON(2)) { +// foo_server.RecomputeStatisticsExpensive(); +// LOG(INFO) << foo_server.LastStatisticsAsString(); +// } +// +// Each source file has an effective verbosity level that's a non-negative +// integer computed from the `--vmodule` and `--v` flags. +// `ABSL_VLOG_IS_ON(n)` is true, and `VLOG(n)` logs, if that effective verbosity +// level is greater than or equal to `n`. +// +// `--vmodule` takes a comma-delimited list of key=value pairs. Each key is a +// pattern matched against filenames, and the values give the effective severity +// level applied to matching files. '?' and '*' characters in patterns are +// interpreted as single-character and zero-or-more-character wildcards. +// Patterns including a slash character are matched against full pathnames, +// while those without are matched against basenames only. One suffix (i.e. the +// last . and everything after it) is stripped from each filename prior to +// matching, as is the special suffix "-inl". +// +// Files are matched against globs in `--vmodule` in order, and the first match +// determines the verbosity level. +// +// Files which do not match any pattern in `--vmodule` use the value of `--v` as +// their effective verbosity level. The default is 0. +// +// SetVLOGLevel helper function is provided to do limited dynamic control over +// V-logging by appending to `--vmodule`. Because these go at the beginning of +// the list, they take priority over any globs previously added. +// +// Resetting --vmodule will override all previous modifications to `--vmodule`, +// including via SetVLOGLevel. + +#ifndef ABSL_LOG_ABSL_VLOG_IS_ON_H_ +#define ABSL_LOG_ABSL_VLOG_IS_ON_H_ + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/log/internal/vlog_config.h" // IWYU pragma: export +#include "absl/strings/string_view.h" + +// IWYU pragma: private, include "absl/log/log.h" + +// This is expanded at the callsite to allow the compiler to optimize +// always-false cases out of the build. +// An ABSL_MAX_VLOG_VERBOSITY of 2 means that VLOG(3) and above should never +// log. +#ifdef ABSL_MAX_VLOG_VERBOSITY +#define ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(x) \ + ((x) <= ABSL_MAX_VLOG_VERBOSITY)&& +#else +#define ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(x) +#endif + +// Each ABSL_VLOG_IS_ON call site gets its own VLogSite that registers with the +// global linked list of sites to asynchronously update its verbosity level on +// changes to --v or --vmodule. The verbosity can also be set by manually +// calling SetVLOGLevel. +// +// ABSL_VLOG_IS_ON is not async signal safe, but it is guaranteed not to +// allocate new memory. +#define ABSL_VLOG_IS_ON(verbose_level) \ + (ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(verbose_level)[]() \ + ->::absl::log_internal::VLogSite * \ + { \ + ABSL_CONST_INIT static ::absl::log_internal::VLogSite site(__FILE__); \ + return &site; \ + }() \ + ->IsEnabled(verbose_level)) + +#endif // ABSL_LOG_ABSL_VLOG_IS_ON_H_ diff --git a/contrib/restricted/abseil-cpp/absl/log/flags.cc b/contrib/restricted/abseil-cpp/absl/log/flags.cc index 215b7bd580..287b3e96c7 100644 --- a/contrib/restricted/abseil-cpp/absl/log/flags.cc +++ b/contrib/restricted/abseil-cpp/absl/log/flags.cc @@ -28,6 +28,7 @@ #include "absl/flags/marshalling.h" #include "absl/log/globals.h" #include "absl/log/internal/config.h" +#include "absl/log/internal/vlog_config.h" #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" @@ -118,3 +119,25 @@ ABSL_FLAG(bool, log_prefix, true, .OnUpdate([] { absl::log_internal::RawEnableLogPrefix(absl::GetFlag(FLAGS_log_prefix)); }); + +ABSL_FLAG(int, v, 0, + "Show all VLOG(m) messages for m <= this. Overridable by --vmodule.") + .OnUpdate([] { + absl::log_internal::UpdateGlobalVLogLevel(absl::GetFlag(FLAGS_v)); + }); + +ABSL_FLAG( + std::string, vmodule, "", + "per-module log verbosity level." + " Argument is a comma-separated list of <module name>=<log level>." + " <module name> is a glob pattern, matched against the filename base" + " (that is, name ignoring .cc/.h./-inl.h)." + " A pattern without slashes matches just the file name portion, otherwise" + " the whole file path below the workspace root" + " (still without .cc/.h./-inl.h) is matched." + " ? and * in the glob pattern match any single or sequence of characters" + " respectively including slashes." + " <log level> overrides any value given by --v.") + .OnUpdate([] { + absl::log_internal::UpdateVModule(absl::GetFlag(FLAGS_vmodule)); + }); diff --git a/contrib/restricted/abseil-cpp/absl/log/globals.h b/contrib/restricted/abseil-cpp/absl/log/globals.h index bc3864c110..b36e47e6d1 100644 --- a/contrib/restricted/abseil-cpp/absl/log/globals.h +++ b/contrib/restricted/abseil-cpp/absl/log/globals.h @@ -24,6 +24,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/log_severity.h" +#include "absl/log/internal/vlog_config.h" #include "absl/strings/string_view.h" namespace absl { @@ -153,6 +154,28 @@ ABSL_MUST_USE_RESULT bool ShouldPrependLogPrefix(); void EnableLogPrefix(bool on_off); //------------------------------------------------------------------------------ +// Set Global VLOG Level +//------------------------------------------------------------------------------ +// +// Sets the global `(ABSL_)VLOG(_IS_ON)` level to `log_level`. This level is +// applied to any sites whose filename doesn't match any `module_pattern`. +// Returns the prior value. +inline int SetGlobalVLogLevel(int log_level) { + return absl::log_internal::UpdateGlobalVLogLevel(log_level); +} + +//------------------------------------------------------------------------------ +// Set VLOG Level +//------------------------------------------------------------------------------ +// +// Sets `(ABSL_)VLOG(_IS_ON)` level for `module_pattern` to `log_level`. This +// allows programmatic control of what is normally set by the --vmodule flag. +// Returns the level that previously applied to `module_pattern`. +inline int SetVLogLevel(absl::string_view module_pattern, int log_level) { + return absl::log_internal::PrependVModule(module_pattern, log_level); +} + +//------------------------------------------------------------------------------ // Configure Android Native Log Tag //------------------------------------------------------------------------------ // diff --git a/contrib/restricted/abseil-cpp/absl/log/initialize.cc b/contrib/restricted/abseil-cpp/absl/log/initialize.cc index a3f6d6c142..ef5d31469a 100644 --- a/contrib/restricted/abseil-cpp/absl/log/initialize.cc +++ b/contrib/restricted/abseil-cpp/absl/log/initialize.cc @@ -21,14 +21,18 @@ namespace absl { ABSL_NAMESPACE_BEGIN -void InitializeLog() { +namespace { +void InitializeLogImpl(absl::TimeZone time_zone) { // This comes first since it is used by RAW_LOG. - absl::log_internal::SetTimeZone(absl::LocalTimeZone()); + absl::log_internal::SetTimeZone(time_zone); // Note that initialization is complete, so logs can now be sent to their // proper destinations rather than stderr. log_internal::SetInitialized(); } +} // namespace + +void InitializeLog() { InitializeLogImpl(absl::LocalTimeZone()); } ABSL_NAMESPACE_END } // namespace absl 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 20b01b5e84..11f0f4078b 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h @@ -65,6 +65,7 @@ ::absl::log_internal::GetReferenceableValue(val2), \ 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) \ @@ -74,6 +75,7 @@ ::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() #define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2, \ s2_text) \ @@ -82,6 +84,7 @@ (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) \ .InternalStream() #define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2, \ @@ -91,6 +94,7 @@ (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) \ .InternalStream() // This one is tricky: @@ -113,6 +117,10 @@ // * As usual, no braces so we can stream into the expansion with `operator<<`. // * Also as usual, it must expand to a single (partial) statement with no // ambiguous-else problems. +// * When stripped by `ABSL_MIN_LOG_LEVEL`, we must discard the `<expr> is OK` +// 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; \ @@ -126,22 +134,24 @@ 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) \ .InternalStream() -#define ABSL_LOG_INTERNAL_QCHECK_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_QCHECK(*absl_log_internal_check_ok_goo.second) \ +#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) \ .InternalStream() namespace absl { @@ -152,8 +162,8 @@ template <typename T> class StatusOr; namespace status_internal { -std::string* MakeCheckFailString(const absl::Status* status, - const char* prefix); +ABSL_ATTRIBUTE_PURE_FUNCTION std::string* MakeCheckFailString( + const absl::Status* status, const char* prefix); } // namespace status_internal namespace log_internal { @@ -314,6 +324,20 @@ ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*); ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*); #undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN +// `ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT` skips formatting the Check_OP result +// string iff `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`, instead returning an empty +// string. +#ifdef ABSL_MIN_LOG_LEVEL +#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \ + ((::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) +#endif + // Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family. The // `(int, int)` override works around the issue that the compiler will not // instantiate the template version of the function on values of unnamed enum @@ -326,7 +350,8 @@ ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*); using U2 = CheckOpStreamType<T2>; \ return ABSL_PREDICT_TRUE(v1 op v2) \ ? nullptr \ - : MakeCheckOpString<U1, U2>(v1, v2, exprtext); \ + : ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, \ + exprtext); \ } \ inline constexpr ::std::string* name##Impl(int v1, int v2, \ const char* exprtext) { \ @@ -339,6 +364,7 @@ ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=) ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <) ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=) 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, diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/conditions.h b/contrib/restricted/abseil-cpp/absl/log/internal/conditions.h index f576d6500b..645f3c23ea 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/conditions.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/conditions.h @@ -57,7 +57,7 @@ // (dangling else, missing switch case) and preserving noreturn semantics (e.g. // on `LOG(FATAL)`) without requiring braces. // -// The `switch` ensures that this expansion is the begnning of a statement (as +// The `switch` ensures that this expansion is the beginning of a statement (as // opposed to an expression) and prevents shenanigans like // `AFunction(LOG(INFO))` and `decltype(LOG(INFO))`. The apparently-redundant // `default` case makes the condition more amenable to Clang dataflow analysis. @@ -68,7 +68,7 @@ !(condition) ? (void)0 : ::absl::log_internal::Voidify()&& // `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like -// `ABSL_LOG_INTERNAL_CONDITION` but adds to that a series of variable +// `ABSL_LOG_INTERNAL_STATELESS_CONDITION` but adds to that a series of variable // declarations, including a local static object which stores the state needed // to implement the stateful macros like `LOG_EVERY_N`. // @@ -137,21 +137,30 @@ ? true \ : (::absl::log_internal::ExitQuietly(), false)) \ : false)) - -#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ - for (int log_internal_severity_loop = 1; log_internal_severity_loop; \ - log_internal_severity_loop = 0) \ - for (const absl::LogSeverity log_internal_severity = \ - ::absl::NormalizeLogSeverity(severity); \ - log_internal_severity_loop; log_internal_severity_loop = 0) \ +#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \ + ABSL_LOG_INTERNAL_##type##_CONDITION( \ + (ABSL_ASSUME(absl::kLogDebugFatal == absl::LogSeverity::kError || \ + absl::kLogDebugFatal == absl::LogSeverity::kFatal), \ + (condition) && \ + (::absl::kLogDebugFatal >= \ + static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \ + (::absl::kLogDebugFatal == ::absl::LogSeverity::kFatal && \ + (::absl::log_internal::AbortQuietly(), false))))) + +#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ + for (int absl_log_internal_severity_loop = 1; \ + absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ + for (const absl::LogSeverity absl_log_internal_severity = \ + ::absl::NormalizeLogSeverity(severity); \ + absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL -#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \ - ABSL_LOG_INTERNAL_##type##_CONDITION( \ - (condition) && \ - (log_internal_severity >= \ - static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \ - (log_internal_severity == ::absl::LogSeverity::kFatal && \ - (::absl::log_internal::AbortQuietly(), false)))) +#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \ + ABSL_LOG_INTERNAL_##type##_CONDITION(( \ + (condition) && \ + (absl_log_internal_severity >= \ + static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \ + (absl_log_internal_severity == ::absl::LogSeverity::kFatal && \ + (::absl::log_internal::AbortQuietly(), false))))) #else // ndef ABSL_MIN_LOG_LEVEL #define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \ ABSL_LOG_INTERNAL_##type##_CONDITION(condition) @@ -163,12 +172,14 @@ ABSL_LOG_INTERNAL_##type##_CONDITION(condition) #define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \ ABSL_LOG_INTERNAL_##type##_CONDITION(condition) -#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ - for (int log_internal_severity_loop = 1; log_internal_severity_loop; \ - log_internal_severity_loop = 0) \ - for (const absl::LogSeverity log_internal_severity = \ - ::absl::NormalizeLogSeverity(severity); \ - log_internal_severity_loop; log_internal_severity_loop = 0) \ +#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \ + ABSL_LOG_INTERNAL_##type##_CONDITION(condition) +#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ + for (int absl_log_internal_severity_loop = 1; \ + absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ + for (const absl::LogSeverity absl_log_internal_severity = \ + ::absl::NormalizeLogSeverity(severity); \ + absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL #define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \ ABSL_LOG_INTERNAL_##type##_CONDITION(condition) diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/flags.h b/contrib/restricted/abseil-cpp/absl/log/internal/flags.h index 0c5e81edee..c4539785ad 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/flags.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/flags.h @@ -33,7 +33,7 @@ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Log messages at this severity or above are sent to stderr in *addition* to -// logfiles. Defaults to `ERROR`. See log_severity.h for numeric values of +// `LogSink`s. Defaults to `ERROR`. See log_severity.h for numeric values of // severity levels. ABSL_DECLARE_FLAG(int, stderrthreshold); @@ -50,4 +50,10 @@ ABSL_DECLARE_FLAG(std::string, log_backtrace_at); // each message logged. Defaults to true. ABSL_DECLARE_FLAG(bool, log_prefix); +// Global log verbosity level. Default is 0. +ABSL_DECLARE_FLAG(int, v); + +// Per-module log verbosity level. By default is empty and is unused. +ABSL_DECLARE_FLAG(std::string, vmodule); + #endif // ABSL_LOG_INTERNAL_FLAGS_H_ diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/fnmatch.cc b/contrib/restricted/abseil-cpp/absl/log/internal/fnmatch.cc new file mode 100644 index 0000000000..26e1e57fe4 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/log/internal/fnmatch.cc @@ -0,0 +1,73 @@ +// Copyright 2023 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/log/internal/fnmatch.h" + +#include <cstddef> + +#include "absl/base/config.h" +#include "absl/strings/string_view.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { +bool FNMatch(absl::string_view pattern, absl::string_view str) { + bool in_wildcard_match = false; + while (true) { + if (pattern.empty()) { + // `pattern` is exhausted; succeed if all of `str` was consumed matching + // it. + return in_wildcard_match || str.empty(); + } + if (str.empty()) { + // `str` is exhausted; succeed if `pattern` is empty or all '*'s. + return pattern.find_first_not_of('*') == pattern.npos; + } + switch (pattern.front()) { + case '*': + pattern.remove_prefix(1); + in_wildcard_match = true; + break; + case '?': + pattern.remove_prefix(1); + str.remove_prefix(1); + break; + default: + if (in_wildcard_match) { + absl::string_view fixed_portion = pattern; + const size_t end = fixed_portion.find_first_of("*?"); + if (end != fixed_portion.npos) { + fixed_portion = fixed_portion.substr(0, end); + } + const size_t match = str.find(fixed_portion); + if (match == str.npos) { + return false; + } + pattern.remove_prefix(fixed_portion.size()); + str.remove_prefix(match + fixed_portion.size()); + in_wildcard_match = false; + } else { + if (pattern.front() != str.front()) { + return false; + } + pattern.remove_prefix(1); + str.remove_prefix(1); + } + break; + } + } +} +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/flags/flag.cc b/contrib/restricted/abseil-cpp/absl/log/internal/fnmatch.h index 531df1287a..4ea147cc6f 100644 --- a/contrib/restricted/abseil-cpp/absl/flags/flag.cc +++ b/contrib/restricted/abseil-cpp/absl/log/internal/fnmatch.h @@ -1,11 +1,10 @@ -// -// Copyright 2019 The Abseil Authors. +// Copyright 2023 The Abseil Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// https://www.apache.org/licenses/LICENSE-2.0 +// 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, @@ -13,26 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "absl/flags/flag.h" +#ifndef ABSL_LOG_INTERNAL_FNMATCH_H_ +#define ABSL_LOG_INTERNAL_FNMATCH_H_ #include "absl/base/config.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN - -// This global mutex protects on-demand construction of flag objects in MSVC -// builds. -#if defined(_MSC_VER) && !defined(__clang__) - -namespace flags_internal { - -ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit); - -absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; } - -} // namespace flags_internal - -#endif - +namespace log_internal { +// Like POSIX `fnmatch`, but: +// * accepts `string_view` +// * does not allocate any dynamic memory +// * only supports * and ? wildcards and not bracket expressions [...] +// * wildcards may match / +// * no backslash-escaping +bool FNMatch(absl::string_view pattern, absl::string_view str); +} // namespace log_internal ABSL_NAMESPACE_END } // namespace absl + +#endif // ABSL_LOG_INTERNAL_FNMATCH_H_ diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h b/contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h index 9326780dc6..99de6dbb24 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h @@ -15,6 +15,7 @@ #ifndef ABSL_LOG_INTERNAL_LOG_IMPL_H_ #define ABSL_LOG_INTERNAL_LOG_IMPL_H_ +#include "absl/log/absl_vlog_is_on.h" #include "absl/log/internal/conditions.h" #include "absl/log/internal/log_message.h" #include "absl/log/internal/strip.h" @@ -41,6 +42,35 @@ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() #endif +// The `switch` ensures that this expansion is the begnning of a statement (as +// opposed to an expression). The use of both `case 0` and `default` is to +// suppress a compiler warning. +#define ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ + _INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + .WithVerbosity(absl_logging_internal_verbose_level) + +#ifndef NDEBUG +#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ + _INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + .WithVerbosity(absl_logging_internal_verbose_level) +#else +#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ + _INFO, false && ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + .WithVerbosity(absl_logging_internal_verbose_level) +#endif + #define ABSL_LOG_INTERNAL_LOG_IF_IMPL(severity, condition) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() @@ -134,6 +164,42 @@ (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() #endif // def NDEBUG +#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (EveryN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_logging_internal_verbose_level) + +#define ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (FirstN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_logging_internal_verbose_level) + +#define ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (EveryPow2) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_logging_internal_verbose_level) + +#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n_seconds) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream() \ + .WithVerbosity(absl_logging_internal_verbose_level) + #define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(severity, condition, n) \ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() 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 46937728cb..4ecb8a1498 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h @@ -40,7 +40,7 @@ #include "absl/log/internal/nullguard.h" #include "absl/log/log_entry.h" #include "absl/log/log_sink.h" -#include "absl/strings/internal/has_absl_stringify.h" +#include "absl/strings/has_absl_stringify.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" @@ -170,15 +170,15 @@ class LogMessage { // Types that support `AbslStringify()` are serialized that way. template <typename T, - typename std::enable_if< - strings_internal::HasAbslStringify<T>::value, int>::type = 0> + typename std::enable_if<absl::HasAbslStringify<T>::value, + int>::type = 0> LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE; // Types that don't support `AbslStringify()` but do support streaming into a // `std::ostream&` are serialized that way. template <typename T, - typename std::enable_if< - !strings_internal::HasAbslStringify<T>::value, int>::type = 0> + typename std::enable_if<!absl::HasAbslStringify<T>::value, + int>::type = 0> LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE; // Note: We explicitly do not support `operator<<` for non-const references @@ -283,8 +283,7 @@ class StringifySink final { // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` template <typename T, - typename std::enable_if<strings_internal::HasAbslStringify<T>::value, - int>::type> + typename std::enable_if<absl::HasAbslStringify<T>::value, int>::type> LogMessage& LogMessage::operator<<(const T& v) { StringifySink sink(*this); // Replace with public API. @@ -294,8 +293,7 @@ LogMessage& LogMessage::operator<<(const T& v) { // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` template <typename T, - typename std::enable_if<!strings_internal::HasAbslStringify<T>::value, - int>::type> + typename std::enable_if<!absl::HasAbslStringify<T>::value, int>::type> LogMessage& LogMessage::operator<<(const T& v) { OstreamView view(*data_); view.stream() << log_internal::NullGuard<T>().Guard(v); diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc b/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc index b7cbe36455..3d5c69952c 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc +++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc @@ -35,6 +35,7 @@ #include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/log_severity.h" +#include "absl/base/no_destructor.h" #include "absl/base/thread_annotations.h" #include "absl/cleanup/cleanup.h" #include "absl/log/globals.h" @@ -168,17 +169,16 @@ class GlobalLogSinkSet final { #if defined(__myriad2__) || defined(__Fuchsia__) // myriad2 and Fuchsia do not log to stderr by default. #else - static StderrLogSink* stderr_log_sink = new StderrLogSink; - AddLogSink(stderr_log_sink); + static absl::NoDestructor<StderrLogSink> stderr_log_sink; + AddLogSink(stderr_log_sink.get()); #endif #ifdef __ANDROID__ - static AndroidLogSink* android_log_sink = new AndroidLogSink; - AddLogSink(android_log_sink); + static absl::NoDestructor<AndroidLogSink> android_log_sink; + AddLogSink(android_log_sink.get()); #endif #if defined(_WIN32) - static WindowsDebuggerLogSink* debugger_log_sink = - new WindowsDebuggerLogSink; - AddLogSink(debugger_log_sink); + static absl::NoDestructor<WindowsDebuggerLogSink> debugger_log_sink; + AddLogSink(debugger_log_sink.get()); #endif // !defined(_WIN32) } @@ -268,7 +268,7 @@ class GlobalLogSinkSet final { // Returns reference to the global LogSinks set. GlobalLogSinkSet& GlobalSinks() { - static GlobalLogSinkSet* global_sinks = new GlobalLogSinkSet; + static absl::NoDestructor<GlobalLogSinkSet> global_sinks; return *global_sinks; } diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/strip.h b/contrib/restricted/abseil-cpp/absl/log/internal/strip.h index adc86ffdfa..f8d2786939 100644 --- a/contrib/restricted/abseil-cpp/absl/log/internal/strip.h +++ b/contrib/restricted/abseil-cpp/absl/log/internal/strip.h @@ -37,7 +37,7 @@ #define ABSL_LOGGING_INTERNAL_LOG_DFATAL \ ::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal) #define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \ - ::absl::log_internal::NullStreamMaybeFatal(log_internal_severity) + ::absl::log_internal::NullStreamMaybeFatal(absl_log_internal_severity) #define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOGGING_INTERNAL_LOG_FATAL #define ABSL_LOG_INTERNAL_QCHECK(failure_message) \ ABSL_LOGGING_INTERNAL_LOG_QFATAL @@ -57,8 +57,9 @@ ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__) #define ABSL_LOGGING_INTERNAL_LOG_DFATAL \ ::absl::log_internal::LogMessage(__FILE__, __LINE__, ::absl::kLogDebugFatal) -#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \ - ::absl::log_internal::LogMessage(__FILE__, __LINE__, log_internal_severity) +#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \ + ::absl::log_internal::LogMessage(__FILE__, __LINE__, \ + absl_log_internal_severity) // These special cases dispatch to special-case constructors that allow us to // avoid an extra function call and shrink non-LTO binaries by a percent or so. #define ABSL_LOG_INTERNAL_CHECK(failure_message) \ diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.cc b/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.cc new file mode 100644 index 0000000000..b578850041 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.cc @@ -0,0 +1,340 @@ +// Copyright 2022 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/log/internal/vlog_config.h" + +#include <stddef.h> + +#include <algorithm> +#include <atomic> +#include <functional> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/const_init.h" +#include "absl/base/internal/spinlock.h" +#include "absl/base/no_destructor.h" +#include "absl/base/optimization.h" +#include "absl/base/thread_annotations.h" +#include "absl/log/internal/fnmatch.h" +#include "absl/memory/memory.h" +#include "absl/strings/numbers.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "absl/strings/strip.h" +#include "absl/synchronization/mutex.h" +#include "absl/types/optional.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { + +namespace { +bool ModuleIsPath(absl::string_view module_pattern) { +#ifdef _WIN32 + return module_pattern.find_first_of("/\\") != module_pattern.npos; +#else + return module_pattern.find('/') != module_pattern.npos; +#endif +} +} // namespace + +bool VLogSite::SlowIsEnabled(int stale_v, int level) { + if (ABSL_PREDICT_TRUE(stale_v != kUninitialized)) { + // Because of the prerequisites to this function, we know that stale_v is + // either uninitialized or >= level. If it's not uninitialized, that means + // it must be >= level, thus we should log. + return true; + } + stale_v = log_internal::RegisterAndInitialize(this); + return ABSL_PREDICT_FALSE(stale_v >= level); +} + +bool VLogSite::SlowIsEnabled0(int stale_v) { return SlowIsEnabled(stale_v, 0); } +bool VLogSite::SlowIsEnabled1(int stale_v) { return SlowIsEnabled(stale_v, 1); } +bool VLogSite::SlowIsEnabled2(int stale_v) { return SlowIsEnabled(stale_v, 2); } +bool VLogSite::SlowIsEnabled3(int stale_v) { return SlowIsEnabled(stale_v, 3); } +bool VLogSite::SlowIsEnabled4(int stale_v) { return SlowIsEnabled(stale_v, 4); } +bool VLogSite::SlowIsEnabled5(int stale_v) { return SlowIsEnabled(stale_v, 5); } + +namespace { +struct VModuleInfo final { + std::string module_pattern; + bool module_is_path; // i.e. it contains a path separator. + int vlog_level; + + // Allocates memory. + VModuleInfo(absl::string_view module_pattern_arg, bool module_is_path_arg, + int vlog_level_arg) + : module_pattern(std::string(module_pattern_arg)), + module_is_path(module_is_path_arg), + vlog_level(vlog_level_arg) {} +}; + +// `mutex` guards all of the data structures that aren't lock-free. +// To avoid problems with the heap checker which calls into `VLOG`, `mutex` must +// be a `SpinLock` that prevents fiber scheduling instead of a `Mutex`. +ABSL_CONST_INIT absl::base_internal::SpinLock mutex( + absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY); + +// `GetUpdateSitesMutex()` serializes updates to all of the sites (i.e. those in +// `site_list_head`) themselves. +absl::Mutex* GetUpdateSitesMutex() { + // Chromium requires no global destructors, so we can't use the + // absl::kConstInit idiom since absl::Mutex as a non-trivial destructor. + static absl::NoDestructor<absl::Mutex> update_sites_mutex ABSL_ACQUIRED_AFTER( + mutex); + return update_sites_mutex.get(); +} + +ABSL_CONST_INIT int global_v ABSL_GUARDED_BY(mutex) = 0; +// `site_list_head` is the head of a singly-linked list. Traversal, insertion, +// and reads are atomic, so no locks are required, but updates to existing +// elements are guarded by `GetUpdateSitesMutex()`. +ABSL_CONST_INIT std::atomic<VLogSite*> site_list_head{nullptr}; +ABSL_CONST_INIT std::vector<VModuleInfo>* vmodule_info ABSL_GUARDED_BY(mutex) + ABSL_PT_GUARDED_BY(mutex){nullptr}; + +// Only used for lisp. +ABSL_CONST_INIT std::vector<std::function<void()>>* update_callbacks + ABSL_GUARDED_BY(GetUpdateSitesMutex()) + ABSL_PT_GUARDED_BY(GetUpdateSitesMutex()){nullptr}; + +// Allocates memory. +std::vector<VModuleInfo>& get_vmodule_info() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) { + if (!vmodule_info) vmodule_info = new std::vector<VModuleInfo>; + return *vmodule_info; +} + +// Does not allocate or take locks. +int VLogLevel(absl::string_view file, const std::vector<VModuleInfo>* infos, + int current_global_v) { + // `infos` is null during a call to `VLOG` prior to setting `vmodule` (e.g. by + // parsing flags). We can't allocate in `VLOG`, so we treat null as empty + // here and press on. + if (!infos || infos->empty()) return current_global_v; + // Get basename for file + absl::string_view basename = file; + { + const size_t sep = basename.rfind('/'); + if (sep != basename.npos) { + basename.remove_prefix(sep + 1); +#ifdef _WIN32 + } else { + const size_t sep = basename.rfind('\\'); + if (sep != basename.npos) basename.remove_prefix(sep + 1); +#endif + } + } + + absl::string_view stem = file, stem_basename = basename; + { + const size_t sep = stem_basename.find('.'); + if (sep != stem_basename.npos) { + stem.remove_suffix(stem_basename.size() - sep); + stem_basename.remove_suffix(stem_basename.size() - sep); + } + if (absl::ConsumeSuffix(&stem_basename, "-inl")) { + stem.remove_suffix(absl::string_view("-inl").size()); + } + } + for (const auto& info : *infos) { + if (info.module_is_path) { + // If there are any slashes in the pattern, try to match the full + // name. + if (FNMatch(info.module_pattern, stem)) { + return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level; + } + } else if (FNMatch(info.module_pattern, stem_basename)) { + return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level; + } + } + + return current_global_v; +} + +// Allocates memory. +int AppendVModuleLocked(absl::string_view module_pattern, int log_level) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) { + for (const auto& info : get_vmodule_info()) { + if (FNMatch(info.module_pattern, module_pattern)) { + // This is a memory optimization to avoid storing patterns that will never + // match due to exit early semantics. Primarily optimized for our own unit + // tests. + return info.vlog_level; + } + } + bool module_is_path = ModuleIsPath(module_pattern); + get_vmodule_info().emplace_back(std::string(module_pattern), module_is_path, + log_level); + return global_v; +} + +// Allocates memory. +int PrependVModuleLocked(absl::string_view module_pattern, int log_level) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) { + absl::optional<int> old_log_level; + for (const auto& info : get_vmodule_info()) { + if (FNMatch(info.module_pattern, module_pattern)) { + old_log_level = info.vlog_level; + break; + } + } + bool module_is_path = ModuleIsPath(module_pattern); + auto iter = get_vmodule_info().emplace(get_vmodule_info().cbegin(), + std::string(module_pattern), + module_is_path, log_level); + + // This is a memory optimization to avoid storing patterns that will never + // match due to exit early semantics. Primarily optimized for our own unit + // tests. + get_vmodule_info().erase( + std::remove_if(++iter, get_vmodule_info().end(), + [module_pattern](const VModuleInfo& info) { + return FNMatch(info.module_pattern, module_pattern); + }), + get_vmodule_info().cend()); + return old_log_level.value_or(global_v); +} +} // namespace + +int VLogLevel(absl::string_view file) ABSL_LOCKS_EXCLUDED(mutex) { + absl::base_internal::SpinLockHolder l(&mutex); + return VLogLevel(file, vmodule_info, global_v); +} + +int RegisterAndInitialize(VLogSite* v) ABSL_LOCKS_EXCLUDED(mutex) { + // std::memory_order_seq_cst is overkill in this function, but given that this + // path is intended to be slow, it's not worth the brain power to relax that. + VLogSite* h = site_list_head.load(std::memory_order_seq_cst); + + VLogSite* old = nullptr; + if (v->next_.compare_exchange_strong(old, h, std::memory_order_seq_cst, + std::memory_order_seq_cst)) { + // Multiple threads may attempt to register this site concurrently. + // By successfully setting `v->next` this thread commits to being *the* + // thread that installs `v` in the list. + while (!site_list_head.compare_exchange_weak( + h, v, std::memory_order_seq_cst, std::memory_order_seq_cst)) { + v->next_.store(h, std::memory_order_seq_cst); + } + } + + int old_v = VLogSite::kUninitialized; + int new_v = VLogLevel(v->file_); + // No loop, if someone else set this, we should respect their evaluation of + // `VLogLevel`. This may mean we return a stale `v`, but `v` itself will + // always arrive at the freshest value. Otherwise, we could be writing a + // stale value and clobbering the fresher one. + if (v->v_.compare_exchange_strong(old_v, new_v, std::memory_order_seq_cst, + std::memory_order_seq_cst)) { + return new_v; + } + return old_v; +} + +void UpdateVLogSites() ABSL_UNLOCK_FUNCTION(mutex) + ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) { + std::vector<VModuleInfo> infos = get_vmodule_info(); + int current_global_v = global_v; + // We need to grab `GetUpdateSitesMutex()` before we release `mutex` to ensure + // that updates are not interleaved (resulting in an inconsistent final state) + // and to ensure that the final state in the sites matches the final state of + // `vmodule_info`. We unlock `mutex` to ensure that uninitialized sites don't + // have to wait on all updates in order to acquire `mutex` and initialize + // themselves. + absl::MutexLock ul(GetUpdateSitesMutex()); + mutex.Unlock(); + VLogSite* n = site_list_head.load(std::memory_order_seq_cst); + // Because sites are added to the list in the order they are executed, there + // tend to be clusters of entries with the same file. + const char* last_file = nullptr; + int last_file_level = 0; + while (n != nullptr) { + if (n->file_ != last_file) { + last_file = n->file_; + last_file_level = VLogLevel(n->file_, &infos, current_global_v); + } + n->v_.store(last_file_level, std::memory_order_seq_cst); + n = n->next_.load(std::memory_order_seq_cst); + } + if (update_callbacks) { + for (auto& cb : *update_callbacks) { + cb(); + } + } +} + +void UpdateVModule(absl::string_view vmodule) + ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { + std::vector<std::pair<absl::string_view, int>> glob_levels; + for (absl::string_view glob_level : absl::StrSplit(vmodule, ',')) { + const size_t eq = glob_level.rfind('='); + if (eq == glob_level.npos) continue; + const absl::string_view glob = glob_level.substr(0, eq); + int level; + if (!absl::SimpleAtoi(glob_level.substr(eq + 1), &level)) continue; + glob_levels.emplace_back(glob, level); + } + mutex.Lock(); // Unlocked by UpdateVLogSites(). + get_vmodule_info().clear(); + for (const auto& it : glob_levels) { + const absl::string_view glob = it.first; + const int level = it.second; + AppendVModuleLocked(glob, level); + } + UpdateVLogSites(); +} + +int UpdateGlobalVLogLevel(int v) + ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { + mutex.Lock(); // Unlocked by UpdateVLogSites(). + const int old_global_v = global_v; + if (v == global_v) { + mutex.Unlock(); + return old_global_v; + } + global_v = v; + UpdateVLogSites(); + return old_global_v; +} + +int PrependVModule(absl::string_view module_pattern, int log_level) + ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { + mutex.Lock(); // Unlocked by UpdateVLogSites(). + int old_v = PrependVModuleLocked(module_pattern, log_level); + UpdateVLogSites(); + return old_v; +} + +void OnVLogVerbosityUpdate(std::function<void()> cb) + ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) { + absl::MutexLock ul(GetUpdateSitesMutex()); + if (!update_callbacks) + update_callbacks = new std::vector<std::function<void()>>; + update_callbacks->push_back(std::move(cb)); +} + +VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v) { + return site_list_head.exchange(v, std::memory_order_seq_cst); +} + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.h b/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.h new file mode 100644 index 0000000000..b6e322c468 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/log/internal/vlog_config.h @@ -0,0 +1,163 @@ +// Copyright 2022 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// vlog_config.h +// ----------------------------------------------------------------------------- +// +// This header file defines `VLogSite`, a public primitive that represents +// a callsite for the `VLOG` family of macros and related libraries. +// It also declares and defines multiple internal utilities used to implement +// `VLOG`, such as `VLogSiteManager`. + +#ifndef ABSL_LOG_INTERNAL_VLOG_CONFIG_H_ +#define ABSL_LOG_INTERNAL_VLOG_CONFIG_H_ + +// IWYU pragma: private, include "absl/log/log.h" + +#include <atomic> +#include <cstdint> +#include <functional> +#include <limits> +#include <type_traits> + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/optimization.h" +#include "absl/base/thread_annotations.h" +#include "absl/strings/string_view.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { + +class SyntheticBinary; +class VLogSite; + +int RegisterAndInitialize(VLogSite* v); +void UpdateVLogSites(); +constexpr int kUseFlag = (std::numeric_limits<int16_t>::min)(); + +// Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call. +// +// Libraries that provide `VLOG`-like functionality should use this to +// efficiently handle --vmodule. +// +// VLogSite objects must not be destroyed until the program exits. Doing so will +// probably yield nasty segfaults in VLogSiteManager::UpdateLogSites(). The +// recommendation is to make all such objects function-local statics. +class VLogSite final { + public: + // `f` must not be destroyed until the program exits. + explicit constexpr VLogSite(const char* f) + : file_(f), v_(kUninitialized), next_(nullptr) {} + VLogSite(const VLogSite&) = delete; + VLogSite& operator=(const VLogSite&) = delete; + + // Inlining the function yields a ~3x performance improvement at the cost of a + // 1.5x code size increase at the call site. + // Takes locks but does not allocate memory. + ABSL_ATTRIBUTE_ALWAYS_INLINE + bool IsEnabled(int level) { + int stale_v = v_.load(std::memory_order_relaxed); + if (ABSL_PREDICT_TRUE(level > stale_v)) { + return false; + } + + // We put everything other than the fast path, i.e. vlogging is initialized + // but not on, behind an out-of-line function to reduce code size. + // "level" is almost always a call-site constant, so we can save a bit + // of code space by special-casing for a few common levels. +#if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__) + if (__builtin_constant_p(level)) { + if (level == 0) return SlowIsEnabled0(stale_v); + if (level == 1) return SlowIsEnabled1(stale_v); + if (level == 2) return SlowIsEnabled2(stale_v); + if (level == 3) return SlowIsEnabled3(stale_v); + if (level == 4) return SlowIsEnabled4(stale_v); + if (level == 5) return SlowIsEnabled5(stale_v); + } +#endif + return SlowIsEnabled(stale_v, level); + } + + private: + friend int log_internal::RegisterAndInitialize(VLogSite* v); + friend void log_internal::UpdateVLogSites(); + friend class log_internal::SyntheticBinary; + static constexpr int kUninitialized = (std::numeric_limits<int>::max)(); + + // SlowIsEnabled performs slower checks to determine whether a log site is + // enabled. Because it is expected to be called somewhat rarely + // (comparatively), it is not inlined to save on code size. + // + // Prerequisites to calling SlowIsEnabled: + // 1) stale_v is uninitialized OR + // 2) stale_v is initialized and >= level (meaning we must log). + // Takes locks but does not allocate memory. + ABSL_ATTRIBUTE_NOINLINE + bool SlowIsEnabled(int stale_v, int level); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled0(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled1(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled2(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled3(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled4(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v); + + // This object is too size-sensitive to use absl::string_view. + const char* const file_; + std::atomic<int> v_; + std::atomic<VLogSite*> next_; +}; +static_assert(std::is_trivially_destructible<VLogSite>::value, + "VLogSite must be trivially destructible"); + +// Returns the current verbose log level of `file`. +// Does not allocate memory. +int VLogLevel(absl::string_view file); + +// Registers a site `v` to get updated as `vmodule` and `v` change. Also +// initializes the site based on their current values, and returns that result. +// Does not allocate memory. +int RegisterAndInitialize(VLogSite* v); + +// Allocates memory. +void UpdateVLogSites(); + +// Completely overwrites the saved value of `vmodule`. +// Allocates memory. +void UpdateVModule(absl::string_view vmodule); + +// Updates the global verbosity level to `v` and returns the prior value. +// Allocates memory. +int UpdateGlobalVLogLevel(int v); + +// Atomically prepends `module_pattern=log_level` to the start of vmodule. +// Returns the prior value for `module_pattern` if there was an exact match and +// `global_v` otherwise. +// Allocates memory. +int PrependVModule(absl::string_view module_pattern, int log_level); + +// Registers `on_update` to be called whenever `v` or `vmodule` change. +// Allocates memory. +void OnVLogVerbosityUpdate(std::function<void()> cb); + +// Does not allocate memory. +VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v); + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_LOG_INTERNAL_VLOG_CONFIG_H_ diff --git a/contrib/restricted/abseil-cpp/absl/log/log.h b/contrib/restricted/abseil-cpp/absl/log/log.h index 602b5acf07..b721b087cc 100644 --- a/contrib/restricted/abseil-cpp/absl/log/log.h +++ b/contrib/restricted/abseil-cpp/absl/log/log.h @@ -32,6 +32,8 @@ // * The `QFATAL` pseudo-severity level is equivalent to `FATAL` but triggers // quieter termination messages, e.g. without a full stack trace, and skips // running registered error handlers. +// * The `DFATAL` pseudo-severity level is defined as `FATAL` in debug mode and +// as `ERROR` otherwise. // Some preprocessor shenanigans are used to ensure that e.g. `LOG(INFO)` has // the same meaning even if a local symbol or preprocessor macro named `INFO` is // defined. To specify a severity level using an expression instead of a @@ -51,6 +53,14 @@ // * .NoPrefix() // Omits the prefix from this line. The prefix includes metadata about the // logged data such as source code location and timestamp. +// * .WithVerbosity(int verbose_level) +// Sets the verbosity field of the logged message as if it was logged by +// `VLOG(verbose_level)`. Unlike `VLOG`, this method does not affect +// evaluation of the statement when the specified `verbose_level` has been +// disabled. The only effect is on `LogSink` implementations which make use +// of the `absl::LogSink::verbosity()` value. The value +// `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message +// not verbose. // * .WithTimestamp(absl::Time timestamp) // Uses the specified timestamp instead of one collected at the time of // execution. @@ -188,6 +198,7 @@ #define ABSL_LOG_LOG_H_ #include "absl/log/internal/log_impl.h" +#include "absl/log/vlog_is_on.h" // IWYU pragma: export // LOG() // @@ -211,11 +222,32 @@ // terminate the program if `NDEBUG` is defined. #define DLOG(severity) ABSL_LOG_INTERNAL_DLOG_IMPL(_##severity) +// `VLOG` uses numeric levels to provide verbose logging that can configured at +// runtime, including at a per-module level. `VLOG` statements are logged at +// `INFO` severity if they are logged at all; the numeric levels are on a +// different scale than the proper severity levels. Positive levels are +// disabled by default. Negative levels should not be used. +// Example: +// +// VLOG(1) << "I print when you run the program with --v=1 or higher"; +// VLOG(2) << "I print when you run the program with --v=2 or higher"; +// +// See vlog_is_on.h for further documentation, including the usage of the +// --vmodule flag to log at different levels in different source files. +#define VLOG(severity) ABSL_LOG_INTERNAL_VLOG_IMPL(severity) + +// `DVLOG` behaves like `VLOG` in debug mode (i.e. `#ifndef NDEBUG`). +// Otherwise, it compiles away and does nothing. +#define DVLOG(severity) ABSL_LOG_INTERNAL_DVLOG_IMPL(severity) + // `LOG_IF` and friends add a second argument which specifies a condition. If // the condition is false, nothing is logged. // Example: // // LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; +// +// There is no `VLOG_IF` because the order of evaluation of the arguments is +// ambiguous and the alternate spelling with an `if`-statement is trivial. #define LOG_IF(severity, condition) \ ABSL_LOG_INTERNAL_LOG_IF_IMPL(_##severity, condition) #define PLOG_IF(severity, condition) \ @@ -283,6 +315,15 @@ #define DLOG_EVERY_N_SEC(severity, n_seconds) \ ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds) +#define VLOG_EVERY_N(severity, n) \ + ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(severity, n) +#define VLOG_FIRST_N(severity, n) \ + ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(severity, n) +#define VLOG_EVERY_POW_2(severity) \ + ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(severity) +#define VLOG_EVERY_N_SEC(severity, n_seconds) \ + ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(severity, n_seconds) + // `LOG_IF_EVERY_N` and friends behave as the corresponding `LOG_EVERY_N` // but neither increment a counter nor log a message if condition is false (as // `LOG_IF`). diff --git a/contrib/restricted/abseil-cpp/absl/log/log_entry.cc b/contrib/restricted/abseil-cpp/absl/log/log_entry.cc index 19c3b3f1be..fe58a576b5 100644 --- a/contrib/restricted/abseil-cpp/absl/log/log_entry.cc +++ b/contrib/restricted/abseil-cpp/absl/log/log_entry.cc @@ -25,5 +25,17 @@ constexpr int LogEntry::kNoVerbosityLevel; constexpr int LogEntry::kNoVerboseLevel; #endif +// https://github.com/abseil/abseil-cpp/issues/1465 +// CMake builds on Apple platforms error when libraries are empty. +// Our CMake configuration can avoid this error on header-only libraries, +// but since this library is conditionally empty, including a single +// variable is an easy workaround. +#ifdef __APPLE__ +namespace log_internal { +extern const char kAvoidEmptyLogEntryLibraryWarning; +const char kAvoidEmptyLogEntryLibraryWarning = 0; +} // namespace log_internal +#endif // __APPLE__ + ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/log/log_entry.h b/contrib/restricted/abseil-cpp/absl/log/log_entry.h index 9e4ae8eb76..7a55dfe29e 100644 --- a/contrib/restricted/abseil-cpp/absl/log/log_entry.h +++ b/contrib/restricted/abseil-cpp/absl/log/log_entry.h @@ -96,7 +96,8 @@ class LogEntry final { // LogEntry::verbosity() // // Returns this entry's verbosity, or `kNoVerbosityLevel` for a non-verbose - // entry. Verbosity control is not available outside of Google yet. + // entry. Taken from the argument to `VLOG` or from + // `LOG(...).WithVerbosity(...)`. int verbosity() const { return verbose_level_; } // LogEntry::timestamp() diff --git a/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h b/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h new file mode 100644 index 0000000000..7898651380 --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h @@ -0,0 +1,72 @@ +// Copyright 2022 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: log/vlog_is_on.h +// ----------------------------------------------------------------------------- +// +// This header defines the `VLOG_IS_ON()` macro that controls the +// variable-verbosity conditional logging. +// +// It's used by `VLOG` in log.h, or it can also be used directly like this: +// +// if (VLOG_IS_ON(2)) { +// foo_server.RecomputeStatisticsExpensive(); +// LOG(INFO) << foo_server.LastStatisticsAsString(); +// } +// +// Each source file has an effective verbosity level that's a non-negative +// integer computed from the `--vmodule` and `--v` flags. +// `VLOG_IS_ON(n)` is true, and `VLOG(n)` logs, if that effective verbosity +// level is greater than or equal to `n`. +// +// `--vmodule` takes a comma-delimited list of key=value pairs. Each key is a +// pattern matched against filenames, and the values give the effective severity +// level applied to matching files. '?' and '*' characters in patterns are +// interpreted as single-character and zero-or-more-character wildcards. +// Patterns including a slash character are matched against full pathnames, +// while those without are matched against basenames only. One suffix (i.e. the +// last . and everything after it) is stripped from each filename prior to +// matching, as is the special suffix "-inl". +// +// Files are matched against globs in `--vmodule` in order, and the first match +// determines the verbosity level. +// +// Files which do not match any pattern in `--vmodule` use the value of `--v` as +// their effective verbosity level. The default is 0. +// +// SetVLOGLevel helper function is provided to do limited dynamic control over +// V-logging by appending to `--vmodule`. Because these go at the beginning of +// the list, they take priority over any globs previously added. +// +// Resetting --vmodule will override all previous modifications to `--vmodule`, +// including via SetVLOGLevel. + +#ifndef ABSL_LOG_VLOG_IS_ON_H_ +#define ABSL_LOG_VLOG_IS_ON_H_ + +#include "absl/log/absl_vlog_is_on.h" // IWYU pragma: export + +// IWYU pragma: private, include "absl/log/log.h" + +// Each VLOG_IS_ON call site gets its own VLogSite that registers with the +// global linked list of sites to asynchronously update its verbosity level on +// changes to --v or --vmodule. The verbosity can also be set by manually +// calling SetVLOGLevel. +// +// VLOG_IS_ON is not async signal safe, but it is guaranteed not to allocate +// new memory. +#define VLOG_IS_ON(verbose_level) ABSL_VLOG_IS_ON(verbose_level) + +#endif // ABSL_LOG_VLOG_IS_ON_H_ diff --git a/contrib/restricted/abseil-cpp/absl/log/ya.make b/contrib/restricted/abseil-cpp/absl/log/ya.make index cb73fdb2b2..f35baf8a56 100644 --- a/contrib/restricted/abseil-cpp/absl/log/ya.make +++ b/contrib/restricted/abseil-cpp/absl/log/ya.make @@ -35,12 +35,14 @@ SRCS( initialize.cc internal/check_op.cc internal/conditions.cc + internal/fnmatch.cc internal/globals.cc internal/log_format.cc internal/log_message.cc internal/log_sink_set.cc internal/nullguard.cc internal/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 2d3aab1c79..4f191bfa0b 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(20230802.1) +VERSION(20240116.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240116.0.tar.gz) PEERDIR( contrib/restricted/abseil-cpp/absl/meta diff --git a/contrib/restricted/abseil-cpp/absl/meta/ya.make b/contrib/restricted/abseil-cpp/absl/meta/ya.make index 39b472c0fa..8a0016666e 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(20230802.1) +VERSION(20240116.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240116.0.tar.gz) PEERDIR( contrib/restricted/abseil-cpp/absl/base diff --git a/contrib/restricted/abseil-cpp/absl/numeric/bits.h b/contrib/restricted/abseil-cpp/absl/numeric/bits.h index 5ed36f5296..c76454c8fb 100644 --- a/contrib/restricted/abseil-cpp/absl/numeric/bits.h +++ b/contrib/restricted/abseil-cpp/absl/numeric/bits.h @@ -49,9 +49,19 @@ namespace absl { ABSL_NAMESPACE_BEGIN -#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) -// rotating +// https://github.com/llvm/llvm-project/issues/64544 +// libc++ had the wrong signature for std::rotl and std::rotr +// prior to libc++ 18.0. +// +#if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) && \ + (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 180000) +using std::rotl; +using std::rotr; + +#else + +// Rotating functions template <class T> ABSL_MUST_USE_RESULT constexpr typename std::enable_if<std::is_unsigned<T>::value, T>::type @@ -66,6 +76,22 @@ ABSL_MUST_USE_RESULT constexpr return numeric_internal::RotateRight(x, s); } +#endif + +// https://github.com/llvm/llvm-project/issues/64544 +// libc++ had the wrong signature for std::rotl and std::rotr +// prior to libc++ 18.0. +// +#if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) + +using std::countl_one; +using std::countl_zero; +using std::countr_one; +using std::countr_zero; +using std::popcount; + +#else + // Counting functions // // While these functions are typically constexpr, on some platforms, they may @@ -107,19 +133,18 @@ ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline popcount(T x) noexcept { return numeric_internal::Popcount(x); } -#else // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L - -using std::countl_one; -using std::countl_zero; -using std::countr_one; -using std::countr_zero; -using std::popcount; -using std::rotl; -using std::rotr; #endif -#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) +#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) + +using std::bit_ceil; +using std::bit_floor; +using std::bit_width; +using std::has_single_bit; + +#else + // Returns: true if x is an integral power of two; false otherwise. template <class T> constexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type @@ -162,12 +187,6 @@ ABSL_INTERNAL_CONSTEXPR_CLZ inline return has_single_bit(x) ? T{1} << (bit_width(x) - 1) : numeric_internal::BitCeilNonPowerOf2(x); } -#else // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L - -using std::bit_ceil; -using std::bit_floor; -using std::bit_width; -using std::has_single_bit; #endif diff --git a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.cc b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.cc new file mode 100644 index 0000000000..a91567549e --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.cc @@ -0,0 +1,248 @@ +// Copyright 2023 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/status/internal/status_internal.h" + +#include <atomic> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstring> +#include <memory> +#include <string> +#include <utility> + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/base/nullability.h" +#include "absl/debugging/stacktrace.h" +#include "absl/debugging/symbolize.h" +#include "absl/memory/memory.h" +#include "absl/status/status.h" +#include "absl/status/status_payload_printer.h" +#include "absl/strings/cord.h" +#include "absl/strings/escaping.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace status_internal { + +void StatusRep::Unref() const { + // Fast path: if ref==1, there is no need for a RefCountDec (since + // this is the only reference and therefore no other thread is + // allowed to be mucking with r). + if (ref_.load(std::memory_order_acquire) == 1 || + ref_.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) { + delete this; + } +} + +static absl::optional<size_t> FindPayloadIndexByUrl( + const Payloads* payloads, absl::string_view type_url) { + if (payloads == nullptr) return absl::nullopt; + + for (size_t i = 0; i < payloads->size(); ++i) { + if ((*payloads)[i].type_url == type_url) return i; + } + + return absl::nullopt; +} + +absl::optional<absl::Cord> StatusRep::GetPayload( + absl::string_view type_url) const { + absl::optional<size_t> index = + status_internal::FindPayloadIndexByUrl(payloads_.get(), type_url); + if (index.has_value()) return (*payloads_)[index.value()].payload; + + return absl::nullopt; +} + +void StatusRep::SetPayload(absl::string_view type_url, absl::Cord payload) { + if (payloads_ == nullptr) { + payloads_ = absl::make_unique<status_internal::Payloads>(); + } + + absl::optional<size_t> index = + status_internal::FindPayloadIndexByUrl(payloads_.get(), type_url); + if (index.has_value()) { + (*payloads_)[index.value()].payload = std::move(payload); + return; + } + + payloads_->push_back({std::string(type_url), std::move(payload)}); +} + +StatusRep::EraseResult StatusRep::ErasePayload(absl::string_view type_url) { + absl::optional<size_t> index = + status_internal::FindPayloadIndexByUrl(payloads_.get(), type_url); + if (!index.has_value()) return {false, Status::PointerToRep(this)}; + payloads_->erase(payloads_->begin() + index.value()); + if (payloads_->empty() && message_.empty()) { + // Special case: If this can be represented inlined, it MUST be inlined + // (== depends on this behavior). + EraseResult result = {true, Status::CodeToInlinedRep(code_)}; + Unref(); + return result; + } + return {true, Status::PointerToRep(this)}; +} + +void StatusRep::ForEachPayload( + absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) + const { + if (auto* payloads = payloads_.get()) { + bool in_reverse = + payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6; + + for (size_t index = 0; index < payloads->size(); ++index) { + const auto& elem = + (*payloads)[in_reverse ? payloads->size() - 1 - index : index]; + +#ifdef NDEBUG + visitor(elem.type_url, elem.payload); +#else + // In debug mode invalidate the type url to prevent users from relying on + // this string lifetime. + + // NOLINTNEXTLINE intentional extra conversion to force temporary. + visitor(std::string(elem.type_url), elem.payload); +#endif // NDEBUG + } + } +} + +std::string StatusRep::ToString(StatusToStringMode mode) const { + std::string text; + absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message()); + + const bool with_payload = (mode & StatusToStringMode::kWithPayload) == + StatusToStringMode::kWithPayload; + + if (with_payload) { + status_internal::StatusPayloadPrinter printer = + status_internal::GetStatusPayloadPrinter(); + this->ForEachPayload([&](absl::string_view type_url, + const absl::Cord& payload) { + absl::optional<std::string> result; + if (printer) result = printer(type_url, payload); + absl::StrAppend( + &text, " [", type_url, "='", + result.has_value() ? *result : absl::CHexEscape(std::string(payload)), + "']"); + }); + } + + return text; +} + +bool StatusRep::operator==(const StatusRep& other) const { + assert(this != &other); + if (code_ != other.code_) return false; + if (message_ != other.message_) return false; + const status_internal::Payloads* this_payloads = payloads_.get(); + const status_internal::Payloads* other_payloads = other.payloads_.get(); + + const status_internal::Payloads no_payloads; + const status_internal::Payloads* larger_payloads = + this_payloads ? this_payloads : &no_payloads; + const status_internal::Payloads* smaller_payloads = + other_payloads ? other_payloads : &no_payloads; + if (larger_payloads->size() < smaller_payloads->size()) { + std::swap(larger_payloads, smaller_payloads); + } + if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false; + // Payloads can be ordered differently, so we can't just compare payload + // vectors. + for (const auto& payload : *larger_payloads) { + + bool found = false; + for (const auto& other_payload : *smaller_payloads) { + if (payload.type_url == other_payload.type_url) { + if (payload.payload != other_payload.payload) { + return false; + } + found = true; + break; + } + } + if (!found) return false; + } + return true; +} + +absl::Nonnull<StatusRep*> StatusRep::CloneAndUnref() const { + // Optimization: no need to create a clone if we already have a refcount of 1. + if (ref_.load(std::memory_order_acquire) == 1) { + // All StatusRep instances are heap allocated and mutable, therefore this + // const_cast will never cast away const from a stack instance. + // + // CloneAndUnref is the only method that doesn't involve an external cast to + // get a mutable StatusRep* from the uintptr_t rep stored in Status. + return const_cast<StatusRep*>(this); + } + std::unique_ptr<status_internal::Payloads> payloads; + if (payloads_) { + payloads = absl::make_unique<status_internal::Payloads>(*payloads_); + } + auto* new_rep = new StatusRep(code_, message_, std::move(payloads)); + Unref(); + return new_rep; +} + +// Convert canonical code to a value known to this binary. +absl::StatusCode MapToLocalCode(int value) { + absl::StatusCode code = static_cast<absl::StatusCode>(value); + switch (code) { + case absl::StatusCode::kOk: + case absl::StatusCode::kCancelled: + case absl::StatusCode::kUnknown: + case absl::StatusCode::kInvalidArgument: + case absl::StatusCode::kDeadlineExceeded: + case absl::StatusCode::kNotFound: + case absl::StatusCode::kAlreadyExists: + case absl::StatusCode::kPermissionDenied: + case absl::StatusCode::kResourceExhausted: + case absl::StatusCode::kFailedPrecondition: + case absl::StatusCode::kAborted: + case absl::StatusCode::kOutOfRange: + case absl::StatusCode::kUnimplemented: + case absl::StatusCode::kInternal: + case absl::StatusCode::kUnavailable: + case absl::StatusCode::kDataLoss: + case absl::StatusCode::kUnauthenticated: + return code; + default: + return absl::StatusCode::kUnknown; + } +} + +absl::Nonnull<std::string*> MakeCheckFailString( + absl::Nonnull<const absl::Status*> status, + absl::Nonnull<const char*> prefix) { + return new std::string( + absl::StrCat(prefix, " (", + status->ToString(StatusToStringMode::kWithEverything), ")")); +} + +} // namespace status_internal + +ABSL_NAMESPACE_END +} // namespace absl 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 6198e726b3..c9f4383272 100644 --- a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h +++ b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h @@ -14,13 +14,19 @@ #ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_ #define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_ +#include <atomic> +#include <cstdint> #include <memory> #include <string> #include <utility> #include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/container/inlined_vector.h" #include "absl/strings/cord.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" #ifndef SWIG // Disabled for SWIG as it doesn't parse attributes correctly. @@ -32,9 +38,9 @@ ABSL_NAMESPACE_BEGIN // TODO(b/176172494): ABSL_MUST_USE_RESULT should expand to the more strict // [[nodiscard]]. For now, just use [[nodiscard]] directly when it is available. #if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) -class [[nodiscard]] Status; +class [[nodiscard]] ABSL_ATTRIBUTE_TRIVIAL_ABI Status; #else -class ABSL_MUST_USE_RESULT Status; +class ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_TRIVIAL_ABI Status; #endif ABSL_NAMESPACE_END } // namespace absl @@ -44,6 +50,7 @@ namespace absl { ABSL_NAMESPACE_BEGIN enum class StatusCode : int; +enum class StatusToStringMode : int; namespace status_internal { @@ -56,22 +63,54 @@ struct Payload { using Payloads = absl::InlinedVector<Payload, 1>; // Reference-counted representation of Status data. -struct StatusRep { +class StatusRep { + public: StatusRep(absl::StatusCode code_arg, absl::string_view message_arg, std::unique_ptr<status_internal::Payloads> payloads_arg) - : ref(int32_t{1}), - code(code_arg), - message(message_arg), - payloads(std::move(payloads_arg)) {} - - std::atomic<int32_t> ref; - absl::StatusCode code; + : ref_(int32_t{1}), + code_(code_arg), + message_(message_arg), + payloads_(std::move(payloads_arg)) {} + + absl::StatusCode code() const { return code_; } + const std::string& message() const { return message_; } + + // Ref and unref are const to allow access through a const pointer, and are + // used during copying operations. + void Ref() const { ref_.fetch_add(1, std::memory_order_relaxed); } + void Unref() const; + + // Payload methods correspond to the same methods in absl::Status. + absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const; + void SetPayload(absl::string_view type_url, absl::Cord payload); + struct EraseResult { + bool erased; + uintptr_t new_rep; + }; + EraseResult ErasePayload(absl::string_view type_url); + void ForEachPayload( + absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) + const; + + std::string ToString(StatusToStringMode mode) const; + + bool operator==(const StatusRep& other) const; + bool operator!=(const StatusRep& other) const { return !(*this == other); } + + // Returns an equivalent heap allocated StatusRep with refcount 1. + // + // `this` is not safe to be used after calling as it may have been deleted. + absl::Nonnull<StatusRep*> CloneAndUnref() const; + + private: + mutable std::atomic<int32_t> ref_; + absl::StatusCode code_; // As an internal implementation detail, we guarantee that if status.message() // is non-empty, then the resulting string_view is null terminated. // This is required to implement 'StatusMessageAsCStr(...)' - std::string message; - std::unique_ptr<status_internal::Payloads> payloads; + std::string message_; + std::unique_ptr<status_internal::Payloads> payloads_; }; absl::StatusCode MapToLocalCode(int value); @@ -80,8 +119,10 @@ absl::StatusCode MapToLocalCode(int value); // suitable for output as an error message in assertion/`CHECK()` failures. // // This is an internal implementation detail for Abseil logging. -std::string* MakeCheckFailString(const absl::Status* status, - const char* prefix); +ABSL_ATTRIBUTE_PURE_FUNCTION +absl::Nonnull<std::string*> MakeCheckFailString( + absl::Nonnull<const absl::Status*> status, + absl::Nonnull<const char*> prefix); } // namespace status_internal diff --git a/contrib/restricted/abseil-cpp/absl/status/internal/statusor_internal.h b/contrib/restricted/abseil-cpp/absl/status/internal/statusor_internal.h index 49cead7a7f..5be94903b7 100644 --- a/contrib/restricted/abseil-cpp/absl/status/internal/statusor_internal.h +++ b/contrib/restricted/abseil-cpp/absl/status/internal/statusor_internal.h @@ -14,12 +14,15 @@ #ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_ #define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_ +#include <cstdint> #include <type_traits> #include <utility> #include "absl/base/attributes.h" +#include "absl/base/nullability.h" #include "absl/meta/type_traits.h" #include "absl/status/status.h" +#include "absl/strings/string_view.h" #include "absl/utility/utility.h" namespace absl { @@ -123,7 +126,7 @@ using IsForwardingAssignmentValid = absl::disjunction< class Helper { public: // Move type-agnostic error handling to the .cc. - static void HandleInvalidStatusCtorArg(Status*); + static void HandleInvalidStatusCtorArg(absl::Nonnull<Status*>); ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status); }; @@ -131,7 +134,8 @@ class Helper { // the constructor. // This abstraction is here mostly for the gcc performance fix. template <typename T, typename... Args> -ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) { +ABSL_ATTRIBUTE_NONNULL(1) +void PlacementNew(absl::Nonnull<void*> p, Args&&... args) { new (p) T(std::forward<Args>(args)...); } @@ -377,6 +381,53 @@ struct MoveAssignBase<T, false> { ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status); +// Used to introduce jitter into the output of printing functions for +// `StatusOr` (i.e. `AbslStringify` and `operator<<`). +class StringifyRandom { + enum BracesType { + kBareParens = 0, + kSpaceParens, + kBareBrackets, + kSpaceBrackets, + }; + + // Returns a random `BracesType` determined once per binary load. + static BracesType RandomBraces() { + static const BracesType kRandomBraces = static_cast<BracesType>( + (reinterpret_cast<uintptr_t>(&kRandomBraces) >> 4) % 4); + return kRandomBraces; + } + + public: + static inline absl::string_view OpenBrackets() { + switch (RandomBraces()) { + case kBareParens: + return "("; + case kSpaceParens: + return "( "; + case kBareBrackets: + return "["; + case kSpaceBrackets: + return "[ "; + } + return "("; + } + + static inline absl::string_view CloseBrackets() { + switch (RandomBraces()) { + case kBareParens: + return ")"; + case kSpaceParens: + return " )"; + case kBareBrackets: + return "]"; + case kSpaceBrackets: + return " ]"; + } + return ")"; + } +}; + } // namespace internal_statusor ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/status/status.cc b/contrib/restricted/abseil-cpp/absl/status/status.cc index 26e68294ac..4dd5ae06ce 100644 --- a/contrib/restricted/abseil-cpp/absl/status/status.cc +++ b/contrib/restricted/abseil-cpp/absl/status/status.cc @@ -15,23 +15,37 @@ #include <errno.h> -#include <cassert> -#include <utility> - +#include <atomic> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <memory> +#include <ostream> +#include <string> + +#include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/strerror.h" #include "absl/base/macros.h" +#include "absl/base/no_destructor.h" +#include "absl/base/nullability.h" #include "absl/debugging/stacktrace.h" #include "absl/debugging/symbolize.h" -#include "absl/status/status_payload_printer.h" -#include "absl/strings/escaping.h" +#include "absl/status/internal/status_internal.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" namespace absl { ABSL_NAMESPACE_BEGIN +static_assert( + alignof(status_internal::StatusRep) >= 4, + "absl::Status assumes it can use the bottom 2 bits of a StatusRep*."); + std::string StatusCodeToString(StatusCode code) { switch (code) { case StatusCode::kOk: @@ -77,146 +91,18 @@ std::ostream& operator<<(std::ostream& os, StatusCode code) { return os << StatusCodeToString(code); } -namespace status_internal { - -static absl::optional<size_t> FindPayloadIndexByUrl( - const Payloads* payloads, absl::string_view type_url) { - if (payloads == nullptr) return absl::nullopt; - - for (size_t i = 0; i < payloads->size(); ++i) { - if ((*payloads)[i].type_url == type_url) return i; - } - - return absl::nullopt; -} - -// Convert canonical code to a value known to this binary. -absl::StatusCode MapToLocalCode(int value) { - absl::StatusCode code = static_cast<absl::StatusCode>(value); - switch (code) { - case absl::StatusCode::kOk: - case absl::StatusCode::kCancelled: - case absl::StatusCode::kUnknown: - case absl::StatusCode::kInvalidArgument: - case absl::StatusCode::kDeadlineExceeded: - case absl::StatusCode::kNotFound: - case absl::StatusCode::kAlreadyExists: - case absl::StatusCode::kPermissionDenied: - case absl::StatusCode::kResourceExhausted: - case absl::StatusCode::kFailedPrecondition: - case absl::StatusCode::kAborted: - case absl::StatusCode::kOutOfRange: - case absl::StatusCode::kUnimplemented: - case absl::StatusCode::kInternal: - case absl::StatusCode::kUnavailable: - case absl::StatusCode::kDataLoss: - case absl::StatusCode::kUnauthenticated: - return code; - default: - return absl::StatusCode::kUnknown; - } -} -} // namespace status_internal - -absl::optional<absl::Cord> Status::GetPayload( - absl::string_view type_url) const { - const auto* payloads = GetPayloads(); - absl::optional<size_t> index = - status_internal::FindPayloadIndexByUrl(payloads, type_url); - if (index.has_value()) return (*payloads)[index.value()].payload; - - return absl::nullopt; -} - -void Status::SetPayload(absl::string_view type_url, absl::Cord payload) { - if (ok()) return; - - PrepareToModify(); - - status_internal::StatusRep* rep = RepToPointer(rep_); - if (!rep->payloads) { - rep->payloads = absl::make_unique<status_internal::Payloads>(); - } - - absl::optional<size_t> index = - status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url); - if (index.has_value()) { - (*rep->payloads)[index.value()].payload = std::move(payload); - return; - } - - rep->payloads->push_back({std::string(type_url), std::move(payload)}); -} - -bool Status::ErasePayload(absl::string_view type_url) { - absl::optional<size_t> index = - status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url); - if (index.has_value()) { - PrepareToModify(); - GetPayloads()->erase(GetPayloads()->begin() + index.value()); - if (GetPayloads()->empty() && message().empty()) { - // Special case: If this can be represented inlined, it MUST be - // inlined (EqualsSlow depends on this behavior). - StatusCode c = static_cast<StatusCode>(raw_code()); - Unref(rep_); - rep_ = CodeToInlinedRep(c); - } - return true; - } - - return false; -} - -void Status::ForEachPayload( - absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) - const { - if (auto* payloads = GetPayloads()) { - bool in_reverse = - payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6; - - for (size_t index = 0; index < payloads->size(); ++index) { - const auto& elem = - (*payloads)[in_reverse ? payloads->size() - 1 - index : index]; - -#ifdef NDEBUG - visitor(elem.type_url, elem.payload); -#else - // In debug mode invalidate the type url to prevent users from relying on - // this string lifetime. - - // NOLINTNEXTLINE intentional extra conversion to force temporary. - visitor(std::string(elem.type_url), elem.payload); -#endif // NDEBUG - } - } -} - -const std::string* Status::EmptyString() { - static union EmptyString { - std::string str; - ~EmptyString() {} - } empty = {{}}; - return &empty.str; +absl::Nonnull<const std::string*> Status::EmptyString() { + static const absl::NoDestructor<std::string> kEmpty; + return kEmpty.get(); } #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL constexpr const char Status::kMovedFromString[]; #endif -const std::string* Status::MovedFromString() { - static std::string* moved_from_string = new std::string(kMovedFromString); - return moved_from_string; -} - -void Status::UnrefNonInlined(uintptr_t rep) { - status_internal::StatusRep* r = RepToPointer(rep); - // Fast path: if ref==1, there is no need for a RefCountDec (since - // this is the only reference and therefore no other thread is - // allowed to be mucking with r). - if (r->ref.load(std::memory_order_acquire) == 1 || - r->ref.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) { - delete r; - } +absl::Nonnull<const std::string*> Status::MovedFromString() { + static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString); + return kMovedFrom.get(); } Status::Status(absl::StatusCode code, absl::string_view msg) @@ -226,97 +112,20 @@ Status::Status(absl::StatusCode code, absl::string_view msg) } } -int Status::raw_code() const { - if (IsInlined(rep_)) { - return static_cast<int>(InlinedRepToCode(rep_)); +absl::Nonnull<status_internal::StatusRep*> Status::PrepareToModify( + uintptr_t rep) { + if (IsInlined(rep)) { + return new status_internal::StatusRep(InlinedRepToCode(rep), + absl::string_view(), nullptr); } - status_internal::StatusRep* rep = RepToPointer(rep_); - return static_cast<int>(rep->code); + return RepToPointer(rep)->CloneAndUnref(); } -absl::StatusCode Status::code() const { - return status_internal::MapToLocalCode(raw_code()); -} - -void Status::PrepareToModify() { - ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status."); - if (IsInlined(rep_)) { - rep_ = PointerToRep(new status_internal::StatusRep( - static_cast<absl::StatusCode>(raw_code()), absl::string_view(), - nullptr)); - return; +std::string Status::ToStringSlow(uintptr_t rep, StatusToStringMode mode) { + if (IsInlined(rep)) { + return absl::StrCat(absl::StatusCodeToString(InlinedRepToCode(rep)), ": "); } - - uintptr_t rep_i = rep_; - status_internal::StatusRep* rep = RepToPointer(rep_); - if (rep->ref.load(std::memory_order_acquire) != 1) { - std::unique_ptr<status_internal::Payloads> payloads; - if (rep->payloads) { - payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads); - } - status_internal::StatusRep* const new_rep = new status_internal::StatusRep( - rep->code, message(), std::move(payloads)); - rep_ = PointerToRep(new_rep); - UnrefNonInlined(rep_i); - } -} - -bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) { - if (IsInlined(a.rep_) != IsInlined(b.rep_)) return false; - if (a.message() != b.message()) return false; - if (a.raw_code() != b.raw_code()) return false; - if (a.GetPayloads() == b.GetPayloads()) return true; - - const status_internal::Payloads no_payloads; - const status_internal::Payloads* larger_payloads = - a.GetPayloads() ? a.GetPayloads() : &no_payloads; - const status_internal::Payloads* smaller_payloads = - b.GetPayloads() ? b.GetPayloads() : &no_payloads; - if (larger_payloads->size() < smaller_payloads->size()) { - std::swap(larger_payloads, smaller_payloads); - } - if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false; - // Payloads can be ordered differently, so we can't just compare payload - // vectors. - for (const auto& payload : *larger_payloads) { - - bool found = false; - for (const auto& other_payload : *smaller_payloads) { - if (payload.type_url == other_payload.type_url) { - if (payload.payload != other_payload.payload) { - return false; - } - found = true; - break; - } - } - if (!found) return false; - } - return true; -} - -std::string Status::ToStringSlow(StatusToStringMode mode) const { - std::string text; - absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message()); - - const bool with_payload = (mode & StatusToStringMode::kWithPayload) == - StatusToStringMode::kWithPayload; - - if (with_payload) { - status_internal::StatusPayloadPrinter printer = - status_internal::GetStatusPayloadPrinter(); - this->ForEachPayload([&](absl::string_view type_url, - const absl::Cord& payload) { - absl::optional<std::string> result; - if (printer) result = printer(type_url, payload); - absl::StrAppend( - &text, " [", type_url, "='", - result.has_value() ? *result : absl::CHexEscape(std::string(payload)), - "']"); - }); - } - - return text; + return RepToPointer(rep)->ToString(mode); } std::ostream& operator<<(std::ostream& os, const Status& x) { @@ -605,18 +414,7 @@ Status ErrnoToStatus(int error_number, absl::string_view message) { MessageForErrnoToStatus(error_number, message)); } -namespace status_internal { - -std::string* MakeCheckFailString(const absl::Status* status, - const char* prefix) { - return new std::string( - absl::StrCat(prefix, " (", - status->ToString(StatusToStringMode::kWithEverything), ")")); -} - -} // namespace status_internal - -const char* StatusMessageAsCStr(const Status& status) { +absl::Nonnull<const char*> StatusMessageAsCStr(const Status& status) { // As an internal implementation detail, we guarantee that if status.message() // is non-empty, then the resulting string_view is null terminated. auto sv_message = status.message(); diff --git a/contrib/restricted/abseil-cpp/absl/status/status.h b/contrib/restricted/abseil-cpp/absl/status/status.h index 595064c0f1..9ce16db961 100644 --- a/contrib/restricted/abseil-cpp/absl/status/status.h +++ b/contrib/restricted/abseil-cpp/absl/status/status.h @@ -51,10 +51,17 @@ #ifndef ABSL_STATUS_STATUS_H_ #define ABSL_STATUS_STATUS_H_ +#include <cassert> +#include <cstdint> #include <ostream> #include <string> #include <utility> +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/base/nullability.h" +#include "absl/base/optimization.h" #include "absl/functional/function_ref.h" #include "absl/status/internal/status_internal.h" #include "absl/strings/cord.h" @@ -421,7 +428,7 @@ inline StatusToStringMode& operator^=(StatusToStringMode& lhs, // Returned Status objects may not be ignored. status_internal.h has a forward // declaration of the form // class ABSL_MUST_USE_RESULT Status; -class Status final { +class ABSL_ATTRIBUTE_TRIVIAL_ABI Status final { public: // Constructors @@ -516,6 +523,12 @@ class Status final { std::string ToString( StatusToStringMode mode = StatusToStringMode::kDefault) const; + // Support `absl::StrCat`, `absl::StrFormat`, etc. + template <typename Sink> + friend void AbslStringify(Sink& sink, const Status& status) { + sink.Append(status.ToString(StatusToStringMode::kWithEverything)); + } + // Status::IgnoreError() // // Ignores any errors. This method does nothing except potentially suppress @@ -602,56 +615,57 @@ class Status final { // code, and an empty error message. explicit Status(absl::StatusCode code); - static void UnrefNonInlined(uintptr_t rep); + // Underlying constructor for status from a rep_. + explicit Status(uintptr_t rep) : rep_(rep) {} + static void Ref(uintptr_t rep); static void Unref(uintptr_t rep); // REQUIRES: !ok() - // Ensures rep_ is not shared with any other Status. - void PrepareToModify(); - - const status_internal::Payloads* GetPayloads() const; - status_internal::Payloads* GetPayloads(); - - static bool EqualsSlow(const absl::Status& a, const absl::Status& b); + // Ensures rep is not inlined or shared with any other Status. + static absl::Nonnull<status_internal::StatusRep*> PrepareToModify( + uintptr_t rep); // MSVC 14.0 limitation requires the const. static constexpr const char kMovedFromString[] = "Status accessed after move."; - static const std::string* EmptyString(); - static const std::string* MovedFromString(); + static absl::Nonnull<const std::string*> EmptyString(); + static absl::Nonnull<const std::string*> MovedFromString(); // Returns whether rep contains an inlined representation. // See rep_ for details. - static bool IsInlined(uintptr_t rep); + static constexpr bool IsInlined(uintptr_t rep); // Indicates whether this Status was the rhs of a move operation. See rep_ // for details. - static bool IsMovedFrom(uintptr_t rep); - static uintptr_t MovedFromRep(); + static constexpr bool IsMovedFrom(uintptr_t rep); + static constexpr uintptr_t MovedFromRep(); // Convert between error::Code and the inlined uintptr_t representation used // by rep_. See rep_ for details. - static uintptr_t CodeToInlinedRep(absl::StatusCode code); - static absl::StatusCode InlinedRepToCode(uintptr_t rep); + static constexpr uintptr_t CodeToInlinedRep(absl::StatusCode code); + static constexpr absl::StatusCode InlinedRepToCode(uintptr_t rep); // 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 status_internal::StatusRep* RepToPointer(uintptr_t r); + static absl::Nonnull<const status_internal::StatusRep*> RepToPointer( + uintptr_t r); - std::string ToStringSlow(StatusToStringMode mode) const; + static std::string ToStringSlow(uintptr_t rep, StatusToStringMode mode); // Status supports two different representations. - // - When the low bit is off it is an inlined representation. + // - When the low bit is set it is an inlined representation. // It uses the canonical error space, no message or payload. // The error code is (rep_ >> 2). // The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom(). - // - When the low bit is on it is an external representation. + // - When the low bit is off it is an external representation. // In this case all the data comes from a heap allocated Rep object. - // (rep_ - 1) is a status_internal::StatusRep* pointer to that structure. + // rep_ is a status_internal::StatusRep* pointer to that structure. uintptr_t rep_; + + friend class status_internal::StatusRep; }; // OkStatus() @@ -755,11 +769,11 @@ Status ErrnoToStatus(int error_number, absl::string_view message); // Implementation details follow //------------------------------------------------------------------------------ -inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {} +inline Status::Status() : Status(absl::StatusCode::kOk) {} -inline Status::Status(absl::StatusCode code) : rep_(CodeToInlinedRep(code)) {} +inline Status::Status(absl::StatusCode code) : Status(CodeToInlinedRep(code)) {} -inline Status::Status(const Status& x) : rep_(x.rep_) { Ref(rep_); } +inline Status::Status(const Status& x) : Status(x.rep_) { Ref(rep_); } inline Status& Status::operator=(const Status& x) { uintptr_t old_rep = rep_; @@ -771,7 +785,7 @@ inline Status& Status::operator=(const Status& x) { return *this; } -inline Status::Status(Status&& x) noexcept : rep_(x.rep_) { +inline Status::Status(Status&& x) noexcept : Status(x.rep_) { x.rep_ = MovedFromRep(); } @@ -803,15 +817,27 @@ inline bool Status::ok() const { return rep_ == CodeToInlinedRep(absl::StatusCode::kOk); } +inline absl::StatusCode Status::code() const { + return status_internal::MapToLocalCode(raw_code()); +} + +inline int Status::raw_code() const { + if (IsInlined(rep_)) return static_cast<int>(InlinedRepToCode(rep_)); + return static_cast<int>(RepToPointer(rep_)->code()); +} + inline absl::string_view Status::message() const { return !IsInlined(rep_) - ? RepToPointer(rep_)->message + ? RepToPointer(rep_)->message() : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString) : absl::string_view()); } inline bool operator==(const Status& lhs, const Status& rhs) { - return lhs.rep_ == rhs.rep_ || Status::EqualsSlow(lhs, rhs); + if (lhs.rep_ == rhs.rep_) return true; + if (Status::IsInlined(lhs.rep_)) return false; + if (Status::IsInlined(rhs.rep_)) return false; + return *Status::RepToPointer(lhs.rep_) == *Status::RepToPointer(rhs.rep_); } inline bool operator!=(const Status& lhs, const Status& rhs) { @@ -819,7 +845,7 @@ inline bool operator!=(const Status& lhs, const Status& rhs) { } inline std::string Status::ToString(StatusToStringMode mode) const { - return ok() ? "OK" : ToStringSlow(mode); + return ok() ? "OK" : ToStringSlow(rep_, mode); } inline void Status::IgnoreError() const { @@ -831,52 +857,68 @@ inline void swap(absl::Status& a, absl::Status& b) { swap(a.rep_, b.rep_); } -inline const status_internal::Payloads* Status::GetPayloads() const { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); +inline absl::optional<absl::Cord> Status::GetPayload( + absl::string_view type_url) const { + if (IsInlined(rep_)) return absl::nullopt; + return RepToPointer(rep_)->GetPayload(type_url); } -inline status_internal::Payloads* Status::GetPayloads() { - return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get(); +inline void Status::SetPayload(absl::string_view type_url, absl::Cord payload) { + if (ok()) return; + status_internal::StatusRep* rep = PrepareToModify(rep_); + rep->SetPayload(type_url, std::move(payload)); + rep_ = PointerToRep(rep); } -inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) == 0; } - -inline bool Status::IsMovedFrom(uintptr_t rep) { - return IsInlined(rep) && (rep & 2) != 0; +inline bool Status::ErasePayload(absl::string_view type_url) { + if (IsInlined(rep_)) return false; + status_internal::StatusRep* rep = PrepareToModify(rep_); + auto res = rep->ErasePayload(type_url); + rep_ = res.new_rep; + return res.erased; } -inline uintptr_t Status::MovedFromRep() { - return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; +inline void Status::ForEachPayload( + absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor) + const { + if (IsInlined(rep_)) return; + RepToPointer(rep_)->ForEachPayload(visitor); } -inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { - return static_cast<uintptr_t>(code) << 2; +constexpr bool Status::IsInlined(uintptr_t rep) { return (rep & 1) != 0; } + +constexpr bool Status::IsMovedFrom(uintptr_t rep) { return (rep & 2) != 0; } + +constexpr uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) { + return (static_cast<uintptr_t>(code) << 2) + 1; } -inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { - assert(IsInlined(rep)); +constexpr absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) { + ABSL_ASSERT(IsInlined(rep)); return static_cast<absl::StatusCode>(rep >> 2); } -inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) { +constexpr uintptr_t Status::MovedFromRep() { + return CodeToInlinedRep(absl::StatusCode::kInternal) | 2; +} + +inline absl::Nonnull<const status_internal::StatusRep*> Status::RepToPointer( + uintptr_t rep) { assert(!IsInlined(rep)); - return reinterpret_cast<status_internal::StatusRep*>(rep - 1); + return reinterpret_cast<const status_internal::StatusRep*>(rep); } -inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) { - return reinterpret_cast<uintptr_t>(rep) + 1; +inline uintptr_t Status::PointerToRep( + absl::Nonnull<status_internal::StatusRep*> rep) { + return reinterpret_cast<uintptr_t>(rep); } inline void Status::Ref(uintptr_t rep) { - if (!IsInlined(rep)) { - RepToPointer(rep)->ref.fetch_add(1, std::memory_order_relaxed); - } + if (!IsInlined(rep)) RepToPointer(rep)->Ref(); } inline void Status::Unref(uintptr_t rep) { - if (!IsInlined(rep)) { - UnrefNonInlined(rep); - } + if (!IsInlined(rep)) RepToPointer(rep)->Unref(); } inline Status OkStatus() { return Status(); } @@ -892,7 +934,7 @@ inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); } // If the status's message is empty, the empty string is returned. // // StatusMessageAsCStr exists for C support. Use `status.message()` in C++. -const char* StatusMessageAsCStr( +absl::Nonnull<const char*> StatusMessageAsCStr( const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND); ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.cc b/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.cc index a47aea11c2..98401e9072 100644 --- a/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.cc +++ b/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.cc @@ -13,9 +13,7 @@ // limitations under the License. #include "absl/status/status_payload_printer.h" -#include <atomic> - -#include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/internal/atomic_hook.h" namespace absl { diff --git a/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.h b/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.h index 5e0937f67d..f22255e1c6 100644 --- a/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.h +++ b/contrib/restricted/abseil-cpp/absl/status/status_payload_printer.h @@ -16,6 +16,7 @@ #include <string> +#include "absl/base/nullability.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" @@ -34,8 +35,8 @@ namespace status_internal { // NOTE: This is an internal API and the design is subject to change in the // future in a non-backward-compatible way. Since it's only meant for debugging // purpose, you should not rely on it in any critical logic. -using StatusPayloadPrinter = absl::optional<std::string> (*)(absl::string_view, - const absl::Cord&); +using StatusPayloadPrinter = absl::Nullable<absl::optional<std::string> (*)( + absl::string_view, const absl::Cord&)>; // Sets the global payload printer. Only one printer should be set per process. // If multiple printers are set, it's undefined which one will be used. diff --git a/contrib/restricted/abseil-cpp/absl/status/statusor.cc b/contrib/restricted/abseil-cpp/absl/status/statusor.cc index 96642b340f..7e6b334c74 100644 --- a/contrib/restricted/abseil-cpp/absl/status/statusor.cc +++ b/contrib/restricted/abseil-cpp/absl/status/statusor.cc @@ -17,7 +17,10 @@ #include <utility> #include "absl/base/call_once.h" +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" +#include "absl/base/nullability.h" +#include "absl/status/internal/statusor_internal.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" @@ -52,7 +55,7 @@ BadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) { BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other) : status_(std::move(other.status_)) {} -const char* BadStatusOrAccess::what() const noexcept { +absl::Nonnull<const char*> BadStatusOrAccess::what() const noexcept { InitWhat(); return what_.c_str(); } @@ -67,7 +70,7 @@ void BadStatusOrAccess::InitWhat() const { namespace internal_statusor { -void Helper::HandleInvalidStatusCtorArg(absl::Status* status) { +void Helper::HandleInvalidStatusCtorArg(absl::Nonnull<absl::Status*> status) { const char* kMessage = "An OK status is not a valid constructor argument to StatusOr<T>"; #ifdef NDEBUG diff --git a/contrib/restricted/abseil-cpp/absl/status/statusor.h b/contrib/restricted/abseil-cpp/absl/status/statusor.h index 54c7ce023f..cd35e5b436 100644 --- a/contrib/restricted/abseil-cpp/absl/status/statusor.h +++ b/contrib/restricted/abseil-cpp/absl/status/statusor.h @@ -39,15 +39,20 @@ #include <exception> #include <initializer_list> #include <new> +#include <ostream> #include <string> #include <type_traits> #include <utility> #include "absl/base/attributes.h" +#include "absl/base/nullability.h" #include "absl/base/call_once.h" #include "absl/meta/type_traits.h" #include "absl/status/internal/statusor_internal.h" #include "absl/status/status.h" +#include "absl/strings/has_absl_stringify.h" +#include "absl/strings/has_ostream_operator.h" +#include "absl/strings/str_format.h" #include "absl/types/variant.h" #include "absl/utility/utility.h" @@ -88,7 +93,7 @@ class BadStatusOrAccess : public std::exception { // // The pointer of this string is guaranteed to be valid until any non-const // function is invoked on the exception object. - const char* what() const noexcept override; + absl::Nonnull<const char*> what() const noexcept override; // BadStatusOrAccess::status() // @@ -650,6 +655,41 @@ bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) { return !(lhs == rhs); } +// Prints the `value` or the status in brackets to `os`. +// +// Requires `T` supports `operator<<`. Do not rely on the output format which +// may change without notice. +template <typename T, typename std::enable_if< + absl::HasOstreamOperator<T>::value, int>::type = 0> +std::ostream& operator<<(std::ostream& os, const StatusOr<T>& status_or) { + if (status_or.ok()) { + os << status_or.value(); + } else { + os << internal_statusor::StringifyRandom::OpenBrackets() + << status_or.status() + << internal_statusor::StringifyRandom::CloseBrackets(); + } + return os; +} + +// As above, but supports `StrCat`, `StrFormat`, etc. +// +// Requires `T` has `AbslStringify`. Do not rely on the output format which +// may change without notice. +template < + typename Sink, typename T, + typename std::enable_if<absl::HasAbslStringify<T>::value, int>::type = 0> +void AbslStringify(Sink& sink, const StatusOr<T>& status_or) { + if (status_or.ok()) { + absl::Format(&sink, "%v", status_or.value()); + } else { + absl::Format(&sink, "%s%v%s", + internal_statusor::StringifyRandom::OpenBrackets(), + status_or.status(), + internal_statusor::StringifyRandom::CloseBrackets()); + } +} + //------------------------------------------------------------------------------ // Implementation details for StatusOr<T> //------------------------------------------------------------------------------ @@ -750,13 +790,13 @@ T&& StatusOr<T>::operator*() && { } template <typename T> -const T* StatusOr<T>::operator->() const { +absl::Nonnull<const T*> StatusOr<T>::operator->() const { this->EnsureOk(); return &this->data_; } template <typename T> -T* StatusOr<T>::operator->() { +absl::Nonnull<T*> StatusOr<T>::operator->() { this->EnsureOk(); return &this->data_; } diff --git a/contrib/restricted/abseil-cpp/absl/status/ya.make b/contrib/restricted/abseil-cpp/absl/status/ya.make index f4a990c542..48ab349f07 100644 --- a/contrib/restricted/abseil-cpp/absl/status/ya.make +++ b/contrib/restricted/abseil-cpp/absl/status/ya.make @@ -26,6 +26,7 @@ NO_COMPILER_WARNINGS() NO_UTIL() SRCS( + internal/status_internal.cc status.cc status_payload_printer.cc ) diff --git a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc index 16c9689961..5460b2c6dc 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc @@ -15,8 +15,13 @@ #include "absl/strings/ascii.h" #include <climits> +#include <cstdint> #include <cstring> #include <string> +#include <type_traits> + +#include "absl/base/config.h" +#include "absl/base/nullability.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -157,8 +162,74 @@ ABSL_DLL const char kToUpper[256] = { }; // clang-format on +template <class T> +static constexpr T BroadcastByte(unsigned char value) { + static_assert(std::is_integral<T>::value && sizeof(T) <= sizeof(uint64_t) && + std::is_unsigned<T>::value, + "only unsigned integers up to 64-bit allowed"); + T result = value; + constexpr size_t result_bit_width = sizeof(result) * CHAR_BIT; + result |= result << ((CHAR_BIT << 0) & (result_bit_width - 1)); + result |= result << ((CHAR_BIT << 1) & (result_bit_width - 1)); + result |= result << ((CHAR_BIT << 2) & (result_bit_width - 1)); + return result; +} + +// Returns whether `c` is in the a-z/A-Z range (w.r.t. `ToUpper`). +// Implemented by: +// 1. Pushing the a-z/A-Z range to [SCHAR_MIN, SCHAR_MIN + 26). +// 2. Comparing to SCHAR_MIN + 26. +template <bool ToUpper> +constexpr bool AsciiInAZRange(unsigned char c) { + constexpr unsigned char sub = (ToUpper ? 'a' : 'A') - SCHAR_MIN; + constexpr signed char threshold = SCHAR_MIN + 26; // 26 = alphabet size. + // Using unsigned arithmetic as overflows/underflows are well defined. + unsigned char u = c - sub; + // Using signed cmp, as SIMD unsigned cmp isn't available in many platforms. + return static_cast<signed char>(u) < threshold; +} + template <bool ToUpper> -constexpr void AsciiStrCaseFold(char* p, char* end) { +static constexpr char* PartialAsciiStrCaseFold(absl::Nonnull<char*> p, + absl::Nonnull<char*> end) { + using vec_t = size_t; + const size_t n = static_cast<size_t>(end - p); + + // SWAR algorithm: http://0x80.pl/notesen/2016-01-06-swar-swap-case.html + constexpr char ch_a = ToUpper ? 'a' : 'A', ch_z = ToUpper ? 'z' : 'Z'; + char* const swar_end = p + (n / sizeof(vec_t)) * sizeof(vec_t); + while (p < swar_end) { + vec_t v = vec_t(); + + // memcpy the vector, but constexpr + for (size_t i = 0; i < sizeof(vec_t); ++i) { + v |= static_cast<vec_t>(static_cast<unsigned char>(p[i])) + << (i * CHAR_BIT); + } + + constexpr unsigned int msb = 1u << (CHAR_BIT - 1); + const vec_t v_msb = v & BroadcastByte<vec_t>(msb); + const vec_t v_nonascii_mask = (v_msb << 1) - (v_msb >> (CHAR_BIT - 1)); + const vec_t v_nonascii = v & v_nonascii_mask; + const vec_t v_ascii = v & ~v_nonascii_mask; + const vec_t a = v_ascii + BroadcastByte<vec_t>(msb - ch_a - 0), + z = v_ascii + BroadcastByte<vec_t>(msb - ch_z - 1); + v = v_nonascii | (v_ascii ^ ((a ^ z) & BroadcastByte<vec_t>(msb)) >> 2); + + // memcpy the vector, but constexpr + for (size_t i = 0; i < sizeof(vec_t); ++i) { + p[i] = static_cast<char>(v >> (i * CHAR_BIT)); + } + + p += sizeof(v); + } + + return p; +} + +template <bool ToUpper> +static constexpr void AsciiStrCaseFold(absl::Nonnull<char*> p, + absl::Nonnull<char*> end) { // 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 @@ -166,16 +237,17 @@ constexpr void AsciiStrCaseFold(char* p, char* end) { // have the same single bit difference. constexpr unsigned char kAsciiCaseBitFlip = 'a' ^ 'A'; - constexpr char ch_a = ToUpper ? 'a' : 'A'; - constexpr char ch_z = ToUpper ? 'z' : 'Z'; - for (; p < end; ++p) { + using vec_t = size_t; + // TODO(b/316380338): When FDO becomes able to vectorize these, + // revert this manual optimization and just leave the naive loop. + if (static_cast<size_t>(end - p) >= sizeof(vec_t)) { + p = ascii_internal::PartialAsciiStrCaseFold<ToUpper>(p, end); + } + while (p < end) { unsigned char v = static_cast<unsigned char>(*p); - // We use & instead of && to ensure this always stays branchless - // We use static_cast<int> to suppress -Wbitwise-instead-of-logical - bool is_in_range = static_cast<bool>(static_cast<int>(ch_a <= v) & - static_cast<int>(v <= ch_z)); - v ^= is_in_range ? kAsciiCaseBitFlip : 0; + v ^= AsciiInAZRange<ToUpper>(v) ? kAsciiCaseBitFlip : 0; *p = static_cast<char>(v); + ++p; } } @@ -205,17 +277,17 @@ static_assert(ValidateAsciiCasefold() == 0, "error in case conversion"); } // namespace ascii_internal -void AsciiStrToLower(std::string* s) { +void AsciiStrToLower(absl::Nonnull<std::string*> s) { char* p = &(*s)[0]; // Guaranteed to be valid for empty strings return ascii_internal::AsciiStrCaseFold<false>(p, p + s->size()); } -void AsciiStrToUpper(std::string* s) { +void AsciiStrToUpper(absl::Nonnull<std::string*> s) { char* p = &(*s)[0]; // Guaranteed to be valid for empty strings return ascii_internal::AsciiStrCaseFold<true>(p, p + s->size()); } -void RemoveExtraAsciiWhitespace(std::string* str) { +void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str) { auto stripped = StripAsciiWhitespace(*str); if (stripped.empty()) { diff --git a/contrib/restricted/abseil-cpp/absl/strings/ascii.h b/contrib/restricted/abseil-cpp/absl/strings/ascii.h index 42eadaea6c..c238f4de82 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/ascii.h +++ b/contrib/restricted/abseil-cpp/absl/strings/ascii.h @@ -53,10 +53,12 @@ #define ABSL_STRINGS_ASCII_H_ #include <algorithm> +#include <cstddef> #include <string> #include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/strings/string_view.h" namespace absl { @@ -165,7 +167,7 @@ inline char ascii_tolower(unsigned char c) { } // Converts the characters in `s` to lowercase, changing the contents of `s`. -void AsciiStrToLower(std::string* s); +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) { @@ -183,7 +185,7 @@ inline char ascii_toupper(unsigned char c) { } // Converts the characters in `s` to uppercase, changing the contents of `s`. -void AsciiStrToUpper(std::string* s); +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) { @@ -201,7 +203,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripLeadingAsciiWhitespace( } // Strips in place whitespace from the beginning of the given string. -inline void StripLeadingAsciiWhitespace(std::string* str) { +inline void StripLeadingAsciiWhitespace(absl::Nonnull<std::string*> str) { auto it = std::find_if_not(str->begin(), str->end(), absl::ascii_isspace); str->erase(str->begin(), it); } @@ -215,7 +217,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripTrailingAsciiWhitespace( } // Strips in place whitespace from the end of the given string -inline void StripTrailingAsciiWhitespace(std::string* str) { +inline void StripTrailingAsciiWhitespace(absl::Nonnull<std::string*> str) { auto it = std::find_if_not(str->rbegin(), str->rend(), absl::ascii_isspace); str->erase(static_cast<size_t>(str->rend() - it)); } @@ -228,13 +230,13 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripAsciiWhitespace( } // Strips in place whitespace from both ends of the given string -inline void StripAsciiWhitespace(std::string* str) { +inline void StripAsciiWhitespace(absl::Nonnull<std::string*> str) { StripTrailingAsciiWhitespace(str); StripLeadingAsciiWhitespace(str); } // Removes leading, trailing, and consecutive internal whitespace. -void RemoveExtraAsciiWhitespace(std::string*); +void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str); ABSL_NAMESPACE_END } // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc index 778a1c75a5..0c9227f849 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc @@ -16,12 +16,14 @@ #include <algorithm> #include <cassert> -#include <cmath> -#include <cstring> +#include <cstddef> +#include <cstdint> #include <limits> +#include <system_error> // NOLINT(build/c++11) #include "absl/base/casts.h" #include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/numeric/bits.h" #include "absl/numeric/int128.h" #include "absl/strings/internal/charconv_bigint.h" @@ -118,7 +120,7 @@ struct FloatTraits<double> { // Parsing a smaller N will produce something finite. static constexpr int kEiselLemireMaxExclusiveExp10 = 309; - static double MakeNan(const char* tagp) { + static double MakeNan(absl::Nonnull<const char*> tagp) { #if ABSL_HAVE_BUILTIN(__builtin_nan) // Use __builtin_nan() if available since it has a fix for // https://bugs.llvm.org/show_bug.cgi?id=37778 @@ -191,7 +193,7 @@ struct FloatTraits<float> { static constexpr int kEiselLemireMinInclusiveExp10 = -46 - 18; static constexpr int kEiselLemireMaxExclusiveExp10 = 39; - static float MakeNan(const char* tagp) { + static float MakeNan(absl::Nonnull<const char*> tagp) { #if ABSL_HAVE_BUILTIN(__builtin_nanf) // Use __builtin_nanf() if available since it has a fix for // https://bugs.llvm.org/show_bug.cgi?id=37778 @@ -343,7 +345,7 @@ int NormalizedShiftSize(int mantissa_width, int binary_exponent) { // `value` must be wider than the requested bit width. // // Returns the number of bits shifted. -int TruncateToBitWidth(int bit_width, uint128* value) { +int TruncateToBitWidth(int bit_width, absl::Nonnull<uint128*> value) { const int current_bit_width = BitWidth(*value); const int shift = current_bit_width - bit_width; *value >>= shift; @@ -355,7 +357,7 @@ int TruncateToBitWidth(int bit_width, uint128* value) { // the appropriate double, and returns true. template <typename FloatType> bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative, - FloatType* value) { + 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 @@ -404,7 +406,8 @@ bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative, // number is stored in *value. template <typename FloatType> void EncodeResult(const CalculatedFloat& calculated, bool negative, - absl::from_chars_result* result, FloatType* value) { + absl::Nonnull<absl::from_chars_result*> result, + absl::Nonnull<FloatType*> value) { if (calculated.exponent == kOverflow) { result->ec = std::errc::result_out_of_range; *value = negative ? -std::numeric_limits<FloatType>::max() @@ -450,7 +453,7 @@ void EncodeResult(const CalculatedFloat& calculated, bool negative, // Zero and negative values of `shift` are accepted, in which case the word is // shifted left, as necessary. uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact, - bool* output_exact) { + absl::Nonnull<bool*> output_exact) { if (shift <= 0) { *output_exact = input_exact; return static_cast<uint64_t>(value << -shift); @@ -684,7 +687,8 @@ CalculatedFloat CalculateFromParsedDecimal( // this function returns false) is both fast and correct. template <typename FloatType> bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative, - FloatType* value, std::errc* ec) { + absl::Nonnull<FloatType*> value, + absl::Nonnull<std::errc*> ec) { uint64_t man = input.mantissa; int exp10 = input.exponent; if (exp10 < FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10) { @@ -857,7 +861,8 @@ bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative, } template <typename FloatType> -from_chars_result FromCharsImpl(const char* first, const char* last, +from_chars_result FromCharsImpl(absl::Nonnull<const char*> first, + absl::Nonnull<const char*> last, FloatType& value, chars_format fmt_flags) { from_chars_result result; result.ptr = first; // overwritten on successful parse @@ -943,12 +948,14 @@ from_chars_result FromCharsImpl(const char* first, const char* last, } } // namespace -from_chars_result from_chars(const char* first, const char* last, double& value, +from_chars_result from_chars(absl::Nonnull<const char*> first, + absl::Nonnull<const char*> last, double& value, chars_format fmt) { return FromCharsImpl(first, last, value, fmt); } -from_chars_result from_chars(const char* first, const char* last, float& value, +from_chars_result from_chars(absl::Nonnull<const char*> first, + absl::Nonnull<const char*> last, float& value, chars_format fmt) { return FromCharsImpl(first, last, value, fmt); } diff --git a/contrib/restricted/abseil-cpp/absl/strings/charconv.h b/contrib/restricted/abseil-cpp/absl/strings/charconv.h index 111c7120de..be250902ad 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/charconv.h +++ b/contrib/restricted/abseil-cpp/absl/strings/charconv.h @@ -18,6 +18,7 @@ #include <system_error> // NOLINT(build/c++11) #include "absl/base/config.h" +#include "absl/base/nullability.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -44,7 +45,7 @@ enum class chars_format { // characters that were successfully parsed. If none was found, `ptr` is set // to the `first` argument to from_chars. struct from_chars_result { - const char* ptr; + absl::Nonnull<const char*> ptr; std::errc ec; }; @@ -76,11 +77,13 @@ struct from_chars_result { // format that strtod() accepts, except that a "0x" prefix is NOT matched. // (In particular, in `hex` mode, the input "0xff" results in the largest // matching pattern "0".) -absl::from_chars_result from_chars(const char* first, const char* last, +absl::from_chars_result from_chars(absl::Nonnull<const char*> first, + absl::Nonnull<const char*> last, double& value, // NOLINT chars_format fmt = chars_format::general); -absl::from_chars_result from_chars(const char* first, const char* last, +absl::from_chars_result from_chars(absl::Nonnull<const char*> first, + absl::Nonnull<const char*> last, float& value, // NOLINT chars_format fmt = chars_format::general); diff --git a/contrib/restricted/abseil-cpp/absl/strings/charset.h b/contrib/restricted/abseil-cpp/absl/strings/charset.h new file mode 100644 index 0000000000..ff4e81a41f --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/strings/charset.h @@ -0,0 +1,164 @@ +// Copyright 2022 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: charset.h +// ----------------------------------------------------------------------------- +// +// This file contains absl::CharSet, a fast, bit-vector set of 8-bit unsigned +// characters. +// +// Instances can be initialized as constexpr constants. For example: +// +// constexpr absl::CharSet kJustX = absl::CharSet::Char('x'); +// constexpr absl::CharSet kMySymbols = absl::CharSet("$@!"); +// constexpr absl::CharSet kLetters = absl::CharSet::Range('a', 'z'); +// +// Multiple instances can be combined that still forms a constexpr expression. +// For example: +// +// constexpr absl::CharSet kLettersAndNumbers = +// absl::CharSet::Range('a', 'z') | absl::CharSet::Range('0', '9'); +// +// Several pre-defined character classes are available that mirror the methods +// from <cctype>. For example: +// +// constexpr absl::CharSet kLettersAndWhitespace = +// absl::CharSet::AsciiAlphabet() | absl::CharSet::AsciiWhitespace(); +// +// To check membership, use the .contains method, e.g. +// +// absl::CharSet hex_letters("abcdef"); +// hex_letters.contains('a'); // true +// hex_letters.contains('g'); // false + +#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/strings/string_view.h" + +namespace absl { + +class CharSet { + public: + constexpr CharSet() : m_() {} + + // Initializes with a given string_view. + constexpr explicit CharSet(absl::string_view str) : m_() { + for (char c : str) { + SetChar(static_cast<unsigned char>(c)); + } + } + + constexpr bool contains(char c) const { + return ((m_[static_cast<unsigned char>(c) / 64] >> + (static_cast<unsigned char>(c) % 64)) & + 0x1) == 0x1; + } + + constexpr bool empty() const { + for (uint64_t c : m_) { + if (c != 0) return false; + } + return true; + } + + // Containing only a single specified char. + static constexpr CharSet Char(char x) { + return CharSet(CharMaskForWord(x, 0), CharMaskForWord(x, 1), + CharMaskForWord(x, 2), CharMaskForWord(x, 3)); + } + + // Containing all the chars in the closed interval [lo,hi]. + static constexpr CharSet Range(char lo, char hi) { + return CharSet(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1), + RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3)); + } + + friend constexpr CharSet operator&(const CharSet& a, const CharSet& b) { + return CharSet(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2], + a.m_[3] & b.m_[3]); + } + + friend constexpr CharSet operator|(const CharSet& a, const CharSet& b) { + return CharSet(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2], + a.m_[3] | b.m_[3]); + } + + friend constexpr CharSet operator~(const CharSet& a) { + return CharSet(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]); + } + + // Mirrors the char-classifying predicates in <cctype>. + static constexpr CharSet AsciiUppercase() { return CharSet::Range('A', 'Z'); } + static constexpr CharSet AsciiLowercase() { return CharSet::Range('a', 'z'); } + static constexpr CharSet AsciiDigits() { return CharSet::Range('0', '9'); } + static constexpr CharSet AsciiAlphabet() { + return AsciiLowercase() | AsciiUppercase(); + } + static constexpr CharSet AsciiAlphanumerics() { + return AsciiDigits() | AsciiAlphabet(); + } + static constexpr CharSet AsciiHexDigits() { + return AsciiDigits() | CharSet::Range('A', 'F') | CharSet::Range('a', 'f'); + } + static constexpr CharSet AsciiPrintable() { + return CharSet::Range(0x20, 0x7e); + } + static constexpr CharSet AsciiWhitespace() { return CharSet("\t\n\v\f\r "); } + static constexpr CharSet AsciiPunctuation() { + return AsciiPrintable() & ~AsciiWhitespace() & ~AsciiAlphanumerics(); + } + + private: + constexpr CharSet(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3) + : m_{b0, b1, b2, b3} {} + + static constexpr uint64_t RangeForWord(char lo, char hi, uint64_t word) { + return OpenRangeFromZeroForWord(static_cast<unsigned char>(hi) + 1, word) & + ~OpenRangeFromZeroForWord(static_cast<unsigned char>(lo), word); + } + + // All the chars in the specified word of the range [0, upper). + static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper, + uint64_t word) { + return (upper <= 64 * word) ? 0 + : (upper >= 64 * (word + 1)) + ? ~static_cast<uint64_t>(0) + : (~static_cast<uint64_t>(0) >> (64 - upper % 64)); + } + + static constexpr uint64_t CharMaskForWord(char x, uint64_t word) { + return (static_cast<unsigned char>(x) / 64 == word) + ? (static_cast<uint64_t>(1) + << (static_cast<unsigned char>(x) % 64)) + : 0; + } + + constexpr void SetChar(unsigned char c) { + m_[c / 64] |= static_cast<uint64_t>(1) << (c % 64); + } + + uint64_t m_[4]; +}; + +} // namespace absl + +#endif // ABSL_STRINGS_CHARSET_H_ diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord.cc b/contrib/restricted/abseil-cpp/absl/strings/cord.cc index 14976aef58..f67326fdef 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/cord.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/cord.cc @@ -15,27 +15,33 @@ #include "absl/strings/cord.h" #include <algorithm> -#include <atomic> +#include <cassert> #include <cstddef> +#include <cstdint> #include <cstdio> #include <cstdlib> +#include <cstring> #include <iomanip> #include <ios> #include <iostream> #include <limits> +#include <memory> #include <ostream> #include <sstream> -#include <type_traits> -#include <unordered_set> -#include <vector> +#include <string> +#include <utility> -#include "absl/base/casts.h" +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/internal/endian.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/container/fixed_array.h" +#include "absl/base/optimization.h" +#include "absl/base/nullability.h" #include "absl/container/inlined_vector.h" +#include "absl/crc/crc32c.h" #include "absl/crc/internal/crc_cord_state.h" +#include "absl/functional/function_ref.h" #include "absl/strings/cord_buffer.h" #include "absl/strings/escaping.h" #include "absl/strings/internal/cord_data_edge.h" @@ -43,13 +49,14 @@ #include "absl/strings/internal/cord_rep_btree.h" #include "absl/strings/internal/cord_rep_crc.h" #include "absl/strings/internal/cord_rep_flat.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/match.h" #include "absl/strings/str_cat.h" -#include "absl/strings/str_join.h" #include "absl/strings/string_view.h" +#include "absl/strings/strip.h" +#include "absl/types/optional.h" +#include "absl/types/span.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -68,29 +75,21 @@ using ::absl::cord_internal::kMinFlatLength; using ::absl::cord_internal::kInlinedVectorSize; using ::absl::cord_internal::kMaxBytesToCopy; -static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, - int indent = 0); -static bool VerifyNode(CordRep* root, CordRep* start_node, - bool full_validation); - -static inline CordRep* VerifyTree(CordRep* node) { - // Verification is expensive, so only do it in debug mode. - // Even in debug mode we normally do only light validation. - // If you are debugging Cord itself, you should define the - // macro EXTRA_CORD_VALIDATION, e.g. by adding - // --copt=-DEXTRA_CORD_VALIDATION to the blaze line. -#ifdef EXTRA_CORD_VALIDATION - assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/true)); -#else // EXTRA_CORD_VALIDATION - assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/false)); -#endif // EXTRA_CORD_VALIDATION - static_cast<void>(&VerifyNode); +static void DumpNode(absl::Nonnull<CordRep*> rep, bool include_data, + absl::Nonnull<std::ostream*> os, int indent = 0); +static bool VerifyNode(absl::Nonnull<CordRep*> root, + absl::Nonnull<CordRep*> start_node); +static inline absl::Nullable<CordRep*> VerifyTree( + absl::Nullable<CordRep*> node) { + assert(node == nullptr || VerifyNode(node, node)); + static_cast<void>(&VerifyNode); return node; } -static CordRepFlat* CreateFlat(const char* data, size_t length, - size_t alloc_hint) { +static absl::Nonnull<CordRepFlat*> CreateFlat(absl::Nonnull<const char*> data, + size_t length, + size_t alloc_hint) { CordRepFlat* flat = CordRepFlat::New(length + alloc_hint); flat->length = length; memcpy(flat->Data(), data, length); @@ -99,7 +98,8 @@ static CordRepFlat* CreateFlat(const char* data, size_t length, // Creates a new flat or Btree out of the specified array. // The returned node has a refcount of 1. -static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) { +static absl::Nonnull<CordRep*> NewBtree(absl::Nonnull<const char*> data, + size_t length, size_t alloc_hint) { if (length <= kMaxFlatLength) { return CreateFlat(data, length, alloc_hint); } @@ -112,14 +112,16 @@ static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) { // Create a new tree out of the specified array. // The returned node has a refcount of 1. -static CordRep* NewTree(const char* data, size_t length, size_t alloc_hint) { +static absl::Nullable<CordRep*> NewTree(absl::Nullable<const char*> data, + size_t length, size_t alloc_hint) { if (length == 0) return nullptr; return NewBtree(data, length, alloc_hint); } namespace cord_internal { -void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) { +void InitializeCordRepExternal(absl::string_view data, + absl::Nonnull<CordRepExternal*> rep) { assert(!data.empty()); rep->length = data.size(); rep->tag = EXTERNAL; @@ -133,7 +135,7 @@ void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) { // and not wasteful, we move the string into an external cord rep, preserving // the already allocated string contents. // Requires the provided string length to be larger than `kMaxInline`. -static CordRep* CordRepFromString(std::string&& src) { +static absl::Nonnull<CordRep*> CordRepFromString(std::string&& src) { assert(src.length() > cord_internal::kMaxInline); if ( // String is short: copy data to avoid external block overhead. @@ -165,12 +167,13 @@ static CordRep* CordRepFromString(std::string&& src) { constexpr unsigned char Cord::InlineRep::kMaxInline; #endif -inline void Cord::InlineRep::set_data(const char* data, size_t n) { +inline void Cord::InlineRep::set_data(absl::Nonnull<const char*> data, + size_t n) { static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15"); data_.set_inline_data(data, n); } -inline char* Cord::InlineRep::set_data(size_t n) { +inline absl::Nonnull<char*> Cord::InlineRep::set_data(size_t n) { assert(n <= kMaxInline); ResetToEmpty(); set_inline_size(n); @@ -194,13 +197,13 @@ inline void Cord::InlineRep::remove_prefix(size_t n) { // Returns `rep` converted into a CordRepBtree. // Directly returns `rep` if `rep` is already a CordRepBtree. -static CordRepBtree* ForceBtree(CordRep* rep) { +static absl::Nonnull<CordRepBtree*> ForceBtree(CordRep* rep) { return rep->IsBtree() ? rep->btree() : CordRepBtree::Create(cord_internal::RemoveCrcNode(rep)); } -void Cord::InlineRep::AppendTreeToInlined(CordRep* tree, +void Cord::InlineRep::AppendTreeToInlined(absl::Nonnull<CordRep*> tree, MethodIdentifier method) { assert(!is_tree()); if (!data_.is_empty()) { @@ -210,14 +213,16 @@ void Cord::InlineRep::AppendTreeToInlined(CordRep* tree, EmplaceTree(tree, method); } -void Cord::InlineRep::AppendTreeToTree(CordRep* tree, MethodIdentifier method) { +void Cord::InlineRep::AppendTreeToTree(absl::Nonnull<CordRep*> tree, + MethodIdentifier method) { assert(is_tree()); const CordzUpdateScope scope(data_.cordz_info(), method); tree = CordRepBtree::Append(ForceBtree(data_.as_tree()), tree); SetTree(tree, scope); } -void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) { +void Cord::InlineRep::AppendTree(absl::Nonnull<CordRep*> tree, + MethodIdentifier method) { assert(tree != nullptr); assert(tree->length != 0); assert(!tree->IsCrc()); @@ -228,7 +233,7 @@ void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) { } } -void Cord::InlineRep::PrependTreeToInlined(CordRep* tree, +void Cord::InlineRep::PrependTreeToInlined(absl::Nonnull<CordRep*> tree, MethodIdentifier method) { assert(!is_tree()); if (!data_.is_empty()) { @@ -238,7 +243,7 @@ void Cord::InlineRep::PrependTreeToInlined(CordRep* tree, EmplaceTree(tree, method); } -void Cord::InlineRep::PrependTreeToTree(CordRep* tree, +void Cord::InlineRep::PrependTreeToTree(absl::Nonnull<CordRep*> tree, MethodIdentifier method) { assert(is_tree()); const CordzUpdateScope scope(data_.cordz_info(), method); @@ -246,7 +251,8 @@ void Cord::InlineRep::PrependTreeToTree(CordRep* tree, SetTree(tree, scope); } -void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) { +void Cord::InlineRep::PrependTree(absl::Nonnull<CordRep*> tree, + MethodIdentifier method) { assert(tree != nullptr); assert(tree->length != 0); assert(!tree->IsCrc()); @@ -261,8 +267,9 @@ void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) { // suitable leaf is found, the function will update the length field for all // nodes to account for the size increase. The append region address will be // written to region and the actual size increase will be written to size. -static inline bool PrepareAppendRegion(CordRep* root, char** region, - size_t* size, size_t max_length) { +static inline bool PrepareAppendRegion( + absl::Nonnull<CordRep*> root, absl::Nonnull<absl::Nullable<char*>*> region, + absl::Nonnull<size_t*> size, size_t max_length) { if (root->IsBtree() && root->refcount.IsOne()) { Span<char> span = root->btree()->GetAppendBuffer(max_length); if (!span.empty()) { @@ -465,11 +472,11 @@ void Cord::InlineRep::AppendArray(absl::string_view src, CommitTree(root, rep, scope, method); } -inline CordRep* Cord::TakeRep() const& { +inline absl::Nonnull<CordRep*> Cord::TakeRep() const& { return CordRep::Ref(contents_.tree()); } -inline CordRep* Cord::TakeRep() && { +inline absl::Nonnull<CordRep*> Cord::TakeRep() && { CordRep* rep = contents_.tree(); contents_.clear(); return rep; @@ -527,7 +534,7 @@ inline void Cord::AppendImpl(C&& src) { contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord); } -static CordRep::ExtractResult ExtractAppendBuffer(CordRep* rep, +static CordRep::ExtractResult ExtractAppendBuffer(absl::Nonnull<CordRep*> rep, size_t min_capacity) { switch (rep->tag) { case cord_internal::BTREE: @@ -573,13 +580,9 @@ CordBuffer Cord::GetAppendBufferSlowPath(size_t block_size, size_t capacity, return CreateAppendBuffer(contents_.data_, block_size, capacity); } -void Cord::Append(const Cord& src) { - AppendImpl(src); -} +void Cord::Append(const Cord& src) { AppendImpl(src); } -void Cord::Append(Cord&& src) { - AppendImpl(std::move(src)); -} +void Cord::Append(Cord&& src) { AppendImpl(std::move(src)); } template <typename T, Cord::EnableIfString<T>> void Cord::Append(T&& src) { @@ -778,8 +781,9 @@ int ClampResult(int memcmp_res) { return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0); } -int CompareChunks(absl::string_view* lhs, absl::string_view* rhs, - size_t* size_to_compare) { +int CompareChunks(absl::Nonnull<absl::string_view*> lhs, + absl::Nonnull<absl::string_view*> rhs, + absl::Nonnull<size_t*> size_to_compare) { size_t compared_size = std::min(lhs->size(), rhs->size()); assert(*size_to_compare >= compared_size); *size_to_compare -= compared_size; @@ -877,7 +881,8 @@ void Cord::SetExpectedChecksum(uint32_t crc) { SetCrcCordState(std::move(state)); } -const crc_internal::CrcCordState* Cord::MaybeGetCrcCordState() const { +absl::Nullable<const crc_internal::CrcCordState*> Cord::MaybeGetCrcCordState() + const { if (!contents_.is_tree() || !contents_.tree()->IsCrc()) { return nullptr; } @@ -894,7 +899,8 @@ absl::optional<uint32_t> Cord::ExpectedChecksum() const { inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size, size_t size_to_compare) const { - auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) { + auto advance = [](absl::Nonnull<Cord::ChunkIterator*> it, + absl::Nonnull<absl::string_view*> chunk) { if (!chunk->empty()) return true; ++*it; if (it->bytes_remaining_ == 0) return false; @@ -924,7 +930,8 @@ inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size, inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size, size_t size_to_compare) const { - auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) { + auto advance = [](absl::Nonnull<Cord::ChunkIterator*> it, + absl::Nonnull<absl::string_view*> chunk) { if (!chunk->empty()) return true; ++*it; if (it->bytes_remaining_ == 0) return false; @@ -1046,7 +1053,7 @@ Cord::operator std::string() const { return s; } -void CopyCordToString(const Cord& src, std::string* dst) { +void CopyCordToString(const Cord& src, absl::Nonnull<std::string*> dst) { if (!src.contents_.is_tree()) { src.contents_.CopyTo(dst); } else { @@ -1055,7 +1062,7 @@ void CopyCordToString(const Cord& src, std::string* dst) { } } -void Cord::CopyToArraySlowPath(char* dst) const { +void Cord::CopyToArraySlowPath(absl::Nonnull<char*> dst) const { assert(contents_.is_tree()); absl::string_view fragment; if (GetFlatAux(contents_.tree(), &fragment)) { @@ -1165,6 +1172,194 @@ char Cord::operator[](size_t i) const { } } +namespace { + +// Tests whether the sequence of chunks beginning at `position` starts with +// `needle`. +// +// REQUIRES: remaining `absl::Cord` starting at `position` is greater than or +// equal to `needle.size()`. +bool IsSubstringInCordAt(absl::Cord::CharIterator position, + absl::string_view needle) { + auto haystack_chunk = absl::Cord::ChunkRemaining(position); + while (true) { + // Precondition is that `absl::Cord::ChunkRemaining(position)` is not + // empty. This assert will trigger if that is not true. + assert(!haystack_chunk.empty()); + auto min_length = std::min(haystack_chunk.size(), needle.size()); + if (!absl::ConsumePrefix(&needle, haystack_chunk.substr(0, min_length))) { + return false; + } + if (needle.empty()) { + return true; + } + absl::Cord::Advance(&position, min_length); + haystack_chunk = absl::Cord::ChunkRemaining(position); + } +} + +} // namespace + +// A few options how this could be implemented: +// (a) Flatten the Cord and find, i.e. +// haystack.Flatten().find(needle) +// For large 'haystack' (where Cord makes sense to be used), this copies +// the whole 'haystack' and can be slow. +// (b) Use std::search, i.e. +// std::search(haystack.char_begin(), haystack.char_end(), +// needle.begin(), needle.end()) +// This avoids the copy, but compares one byte at a time, and branches a +// lot every time it has to advance. It is also not possible to use +// std::search as is, because CharIterator is only an input iterator, not a +// forward iterator. +// (c) Use string_view::find in each fragment, and specifically handle fragment +// boundaries. +// +// This currently implements option (b). +absl::Cord::CharIterator absl::Cord::FindImpl(CharIterator it, + absl::string_view needle) const { + // Ensure preconditions are met by callers first. + + // Needle must not be empty. + assert(!needle.empty()); + // Haystack must be at least as large as needle. + assert(it.chunk_iterator_.bytes_remaining_ >= needle.size()); + + // Cord is a sequence of chunks. To find `needle` we go chunk by chunk looking + // for the first char of needle, up until we have advanced `N` defined as + // `haystack.size() - needle.size()`. If we find the first char of needle at + // `P` and `P` is less than `N`, we then call `IsSubstringInCordAt` to + // see if this is the needle. If not, we advance to `P + 1` and try again. + while (it.chunk_iterator_.bytes_remaining_ >= needle.size()) { + auto haystack_chunk = Cord::ChunkRemaining(it); + assert(!haystack_chunk.empty()); + // Look for the first char of `needle` in the current chunk. + auto idx = haystack_chunk.find(needle.front()); + if (idx == absl::string_view::npos) { + // No potential match in this chunk, advance past it. + Cord::Advance(&it, haystack_chunk.size()); + continue; + } + // We found the start of a potential match in the chunk. Advance the + // iterator and haystack chunk to the match the position. + Cord::Advance(&it, idx); + // Check if there is enough haystack remaining to actually have a match. + if (it.chunk_iterator_.bytes_remaining_ < needle.size()) { + break; + } + // Check if this is `needle`. + if (IsSubstringInCordAt(it, needle)) { + return it; + } + // No match, increment the iterator for the next attempt. + Cord::Advance(&it, 1); + } + // If we got here, we did not find `needle`. + return char_end(); +} + +absl::Cord::CharIterator absl::Cord::Find(absl::string_view needle) const { + if (needle.empty()) { + return char_begin(); + } + if (needle.size() > size()) { + return char_end(); + } + if (needle.size() == size()) { + return *this == needle ? char_begin() : char_end(); + } + return FindImpl(char_begin(), needle); +} + +namespace { + +// Tests whether the sequence of chunks beginning at `haystack` starts with the +// sequence of chunks beginning at `needle_begin` and extending to `needle_end`. +// +// REQUIRES: remaining `absl::Cord` starting at `position` is greater than or +// equal to `needle_end - needle_begin` and `advance`. +bool IsSubcordInCordAt(absl::Cord::CharIterator haystack, + absl::Cord::CharIterator needle_begin, + absl::Cord::CharIterator needle_end) { + while (needle_begin != needle_end) { + auto haystack_chunk = absl::Cord::ChunkRemaining(haystack); + assert(!haystack_chunk.empty()); + auto needle_chunk = absl::Cord::ChunkRemaining(needle_begin); + auto min_length = std::min(haystack_chunk.size(), needle_chunk.size()); + if (haystack_chunk.substr(0, min_length) != + needle_chunk.substr(0, min_length)) { + return false; + } + absl::Cord::Advance(&haystack, min_length); + absl::Cord::Advance(&needle_begin, min_length); + } + return true; +} + +// Tests whether the sequence of chunks beginning at `position` starts with the +// cord `needle`. +// +// REQUIRES: remaining `absl::Cord` starting at `position` is greater than or +// equal to `needle.size()`. +bool IsSubcordInCordAt(absl::Cord::CharIterator position, + const absl::Cord& needle) { + return IsSubcordInCordAt(position, needle.char_begin(), needle.char_end()); +} + +} // namespace + +absl::Cord::CharIterator absl::Cord::Find(const absl::Cord& needle) const { + if (needle.empty()) { + return char_begin(); + } + const auto needle_size = needle.size(); + if (needle_size > size()) { + return char_end(); + } + if (needle_size == size()) { + return *this == needle ? char_begin() : char_end(); + } + const auto needle_chunk = Cord::ChunkRemaining(needle.char_begin()); + auto haystack_it = char_begin(); + while (true) { + haystack_it = FindImpl(haystack_it, needle_chunk); + if (haystack_it == char_end() || + haystack_it.chunk_iterator_.bytes_remaining_ < needle_size) { + break; + } + // We found the first chunk of `needle` at `haystack_it` but not the entire + // subcord. Advance past the first chunk and check for the remainder. + auto haystack_advanced_it = haystack_it; + auto needle_it = needle.char_begin(); + Cord::Advance(&haystack_advanced_it, needle_chunk.size()); + Cord::Advance(&needle_it, needle_chunk.size()); + if (IsSubcordInCordAt(haystack_advanced_it, needle_it, needle.char_end())) { + return haystack_it; + } + Cord::Advance(&haystack_it, 1); + if (haystack_it.chunk_iterator_.bytes_remaining_ < needle_size) { + break; + } + if (haystack_it.chunk_iterator_.bytes_remaining_ == needle_size) { + // Special case, if there is exactly `needle_size` bytes remaining, the + // subcord is either at `haystack_it` or not at all. + if (IsSubcordInCordAt(haystack_it, needle)) { + return haystack_it; + } + break; + } + } + return char_end(); +} + +bool Cord::Contains(absl::string_view rhs) const { + return rhs.empty() || Find(rhs) != char_end(); +} + +bool Cord::Contains(const absl::Cord& rhs) const { + return rhs.empty() || Find(rhs) != char_end(); +} + absl::string_view Cord::FlattenSlowPath() { assert(contents_.is_tree()); size_t total_size = size(); @@ -1193,7 +1388,8 @@ absl::string_view Cord::FlattenSlowPath() { return absl::string_view(new_buffer, total_size); } -/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) { +/* static */ bool Cord::GetFlatAux(absl::Nonnull<CordRep*> rep, + absl::Nonnull<absl::string_view*> fragment) { assert(rep != nullptr); if (rep->length == 0) { *fragment = absl::string_view(); @@ -1227,7 +1423,7 @@ absl::string_view Cord::FlattenSlowPath() { } /* static */ void Cord::ForEachChunkAux( - absl::cord_internal::CordRep* rep, + absl::Nonnull<absl::cord_internal::CordRep*> rep, absl::FunctionRef<void(absl::string_view)> callback) { assert(rep != nullptr); if (rep->length == 0) return; @@ -1252,8 +1448,8 @@ absl::string_view Cord::FlattenSlowPath() { } } -static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, - int indent) { +static void DumpNode(absl::Nonnull<CordRep*> rep, bool include_data, + absl::Nonnull<std::ostream*> os, int indent) { const int kIndentStep = 1; absl::InlinedVector<CordRep*, kInlinedVectorSize> stack; absl::InlinedVector<int, kInlinedVectorSize> indents; @@ -1289,7 +1485,7 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, *os << absl::CEscape(std::string(rep->flat()->Data(), rep->length)); *os << "]\n"; } else { - CordRepBtree::Dump(rep, /*label=*/ "", include_data, *os); + CordRepBtree::Dump(rep, /*label=*/"", include_data, *os); } } if (leaf) { @@ -1303,16 +1499,17 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, ABSL_INTERNAL_CHECK(indents.empty(), ""); } -static std::string ReportError(CordRep* root, CordRep* node) { +static std::string ReportError(absl::Nonnull<CordRep*> root, + absl::Nonnull<CordRep*> node) { std::ostringstream buf; buf << "Error at node " << node << " in:"; DumpNode(root, true, &buf); return buf.str(); } -static bool VerifyNode(CordRep* root, CordRep* start_node, - bool /* full_validation */) { - absl::InlinedVector<CordRep*, 2> worklist; +static bool VerifyNode(absl::Nonnull<CordRep*> root, + absl::Nonnull<CordRep*> start_node) { + absl::InlinedVector<absl::Nonnull<CordRep*>, 2> worklist; worklist.push_back(start_node); do { CordRep* node = worklist.back(); diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord.h b/contrib/restricted/abseil-cpp/absl/strings/cord.h index 457ccf0609..b3e556b6b4 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/cord.h +++ b/contrib/restricted/abseil-cpp/absl/strings/cord.h @@ -74,6 +74,7 @@ #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/port.h" #include "absl/container/inlined_vector.h" #include "absl/crc/internal/crc_cord_state.h" @@ -86,7 +87,6 @@ #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/cord_rep_ring.h" #include "absl/strings/internal/cordz_functions.h" #include "absl/strings/internal/cordz_info.h" #include "absl/strings/internal/cordz_statistics.h" @@ -103,7 +103,7 @@ class Cord; class CordTestPeer; template <typename Releaser> Cord MakeCordFromExternal(absl::string_view, Releaser&&); -void CopyCordToString(const Cord& src, std::string* dst); +void CopyCordToString(const Cord& src, absl::Nonnull<std::string*> dst); // Cord memory accounting modes enum class CordMemoryAccounting { @@ -120,8 +120,8 @@ enum class CordMemoryAccounting { // // For example: // absl::Cord cord; - // cord.append(some_other_cord); - // cord.append(some_other_cord); + // cord.Append(some_other_cord); + // cord.Append(some_other_cord); // // Counts `some_other_cord` twice: // cord.EstimatedMemoryUsage(kTotal); // // Counts `some_other_cord` once: @@ -362,7 +362,7 @@ class Cord { // Cord::empty() // - // Determines whether the given Cord is empty, returning `true` is so. + // Determines whether the given Cord is empty, returning `true` if so. bool empty() const; // Cord::EstimatedMemoryUsage() @@ -396,6 +396,12 @@ class Cord { bool EndsWith(absl::string_view rhs) const; bool EndsWith(const Cord& rhs) const; + // Cord::Contains() + // + // Determines whether the Cord contains the passed string data `rhs`. + bool Contains(absl::string_view rhs) const; + bool Contains(const Cord& rhs) const; + // Cord::operator std::string() // // Converts a Cord into a `std::string()`. This operator is marked explicit to @@ -411,7 +417,8 @@ class Cord { // guarantee that pointers previously returned by `dst->data()` remain valid // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new // object, prefer to simply use the conversion operator to `std::string`. - friend void CopyCordToString(const Cord& src, std::string* dst); + friend void CopyCordToString(const Cord& src, + absl::Nonnull<std::string*> dst); class CharIterator; @@ -448,7 +455,7 @@ class Cord { using iterator_category = std::input_iterator_tag; using value_type = absl::string_view; using difference_type = ptrdiff_t; - using pointer = const value_type*; + using pointer = absl::Nonnull<const value_type*>; using reference = value_type; ChunkIterator() = default; @@ -468,14 +475,14 @@ class Cord { using CordRepBtree = absl::cord_internal::CordRepBtree; using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader; - // Constructs a `begin()` iterator from `tree`. `tree` must not be null. - explicit ChunkIterator(cord_internal::CordRep* tree); + // Constructs a `begin()` iterator from `tree`. + explicit ChunkIterator(absl::Nonnull<cord_internal::CordRep*> tree); // Constructs a `begin()` iterator from `cord`. - explicit ChunkIterator(const Cord* cord); + explicit ChunkIterator(absl::Nonnull<const Cord*> cord); // Initializes this instance from a tree. Invoked by constructors. - void InitTree(cord_internal::CordRep* tree); + void InitTree(absl::Nonnull<cord_internal::CordRep*> tree); // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than // `current_chunk_.size()`. @@ -493,7 +500,7 @@ class Cord { // The current leaf, or `nullptr` if the iterator points to short data. // If the current chunk is a substring node, current_leaf_ points to the // underlying flat or external node. - absl::cord_internal::CordRep* current_leaf_ = nullptr; + absl::Nullable<absl::cord_internal::CordRep*> current_leaf_ = nullptr; // The number of bytes left in the `Cord` over which we are iterating. size_t bytes_remaining_ = 0; @@ -515,7 +522,7 @@ class Cord { // absl::string_view s) { // return std::find(c.chunk_begin(), c.chunk_end(), s); // } - ChunkIterator chunk_begin() const; + ChunkIterator chunk_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND; // Cord::chunk_end() // @@ -524,7 +531,7 @@ class Cord { // Generally, prefer using `Cord::Chunks()` within a range-based for loop for // iterating over the chunks of a Cord. This method may be useful for getting // a `ChunkIterator` where range-based for-loops may not be available. - ChunkIterator chunk_end() const; + ChunkIterator chunk_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND; //---------------------------------------------------------------------------- // Cord::ChunkRange @@ -550,13 +557,13 @@ class Cord { using iterator = ChunkIterator; using const_iterator = ChunkIterator; - explicit ChunkRange(const Cord* cord) : cord_(cord) {} + explicit ChunkRange(absl::Nonnull<const Cord*> cord) : cord_(cord) {} ChunkIterator begin() const; ChunkIterator end() const; private: - const Cord* cord_; + absl::Nonnull<const Cord*> cord_; }; // Cord::Chunks() @@ -578,7 +585,7 @@ class Cord { // // The temporary Cord returned by CordFactory has been destroyed! // } // } - ChunkRange Chunks() const; + ChunkRange Chunks() const ABSL_ATTRIBUTE_LIFETIME_BOUND; //---------------------------------------------------------------------------- // Cord::CharIterator @@ -609,7 +616,7 @@ class Cord { using iterator_category = std::input_iterator_tag; using value_type = char; using difference_type = ptrdiff_t; - using pointer = const char*; + using pointer = absl::Nonnull<const char*>; using reference = const char&; CharIterator() = default; @@ -624,7 +631,8 @@ class Cord { friend Cord; private: - explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {} + explicit CharIterator(absl::Nonnull<const Cord*> cord) + : chunk_iterator_(cord) {} ChunkIterator chunk_iterator_; }; @@ -635,14 +643,14 @@ class Cord { // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the // number of bytes within the Cord; otherwise, behavior is undefined. It is // valid to pass `char_end()` and `0`. - static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes); + static Cord AdvanceAndRead(absl::Nonnull<CharIterator*> it, size_t n_bytes); // Cord::Advance() // // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than // or equal to the number of bytes remaining within the Cord; otherwise, // behavior is undefined. It is valid to pass `char_end()` and `0`. - static void Advance(CharIterator* it, size_t n_bytes); + static void Advance(absl::Nonnull<CharIterator*> it, size_t n_bytes); // Cord::ChunkRemaining() // @@ -658,7 +666,7 @@ class Cord { // Generally, prefer using `Cord::Chars()` within a range-based for loop for // iterating over the chunks of a Cord. This method may be useful for getting // a `CharIterator` where range-based for-loops may not be available. - CharIterator char_begin() const; + CharIterator char_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND; // Cord::char_end() // @@ -667,7 +675,7 @@ class Cord { // Generally, prefer using `Cord::Chars()` within a range-based for loop for // iterating over the chunks of a Cord. This method may be useful for getting // a `CharIterator` where range-based for-loops are not useful. - CharIterator char_end() const; + CharIterator char_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND; // Cord::CharRange // @@ -691,13 +699,13 @@ class Cord { using iterator = CharIterator; using const_iterator = CharIterator; - explicit CharRange(const Cord* cord) : cord_(cord) {} + explicit CharRange(absl::Nonnull<const Cord*> cord) : cord_(cord) {} CharIterator begin() const; CharIterator end() const; private: - const Cord* cord_; + absl::Nonnull<const Cord*> cord_; }; // Cord::Chars() @@ -719,7 +727,7 @@ class Cord { // // The temporary Cord returned by CordFactory has been destroyed! // } // } - CharRange Chars() const; + CharRange Chars() const ABSL_ATTRIBUTE_LIFETIME_BOUND; // Cord::operator[] // @@ -737,20 +745,38 @@ class Cord { // // If this cord's representation is a single flat array, returns a // string_view referencing that array. Otherwise returns nullopt. - absl::optional<absl::string_view> TryFlat() const; + absl::optional<absl::string_view> TryFlat() const + ABSL_ATTRIBUTE_LIFETIME_BOUND; // Cord::Flatten() // // Flattens the cord into a single array and returns a view of the data. // // If the cord was already flat, the contents are not modified. - absl::string_view Flatten(); + absl::string_view Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND; + + // Cord::Find() + // + // Returns an iterator to the first occurrance of the substring `needle`. + // + // If the substring `needle` does not occur, `Cord::char_end()` is returned. + CharIterator Find(absl::string_view needle) const; + CharIterator Find(const absl::Cord& needle) const; // Supports absl::Cord as a sink object for absl::Format(). - friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) { + friend void AbslFormatFlush(absl::Nonnull<absl::Cord*> cord, + absl::string_view part) { cord->Append(part); } + // Support automatic stringification with absl::StrCat and absl::StrFormat. + template <typename Sink> + friend void AbslStringify(Sink& sink, const absl::Cord& cord) { + for (absl::string_view chunk : cord.Chunks()) { + sink.Append(chunk); + } + } + // Cord::SetExpectedChecksum() // // Stores a checksum value with this non-empty cord instance, for later @@ -809,7 +835,8 @@ class Cord { friend bool operator==(const Cord& lhs, const Cord& rhs); friend bool operator==(const Cord& lhs, absl::string_view rhs); - friend const CordzInfo* GetCordzInfoForTesting(const Cord& cord); + friend absl::Nullable<const CordzInfo*> GetCordzInfoForTesting( + const Cord& cord); // Calls the provided function once for each cord chunk, in order. Unlike // Chunks(), this API will not allocate memory. @@ -836,20 +863,22 @@ class Cord { InlineRep& operator=(const InlineRep& src); InlineRep& operator=(InlineRep&& src) noexcept; - explicit constexpr InlineRep(absl::string_view sv, CordRep* rep); + explicit constexpr InlineRep(absl::string_view sv, + absl::Nullable<CordRep*> rep); - void Swap(InlineRep* rhs); - bool empty() const; + void Swap(absl::Nonnull<InlineRep*> rhs); size_t size() const; - const char* data() const; // Returns nullptr if holding pointer - void set_data(const char* data, size_t n); // Discards pointer, if any - char* set_data(size_t n); // Write data to the result + // Returns nullptr if holding pointer + absl::Nullable<const char*> data() const; + // Discards pointer, if any + void set_data(absl::Nonnull<const char*> data, size_t n); + absl::Nonnull<char*> set_data(size_t n); // Write data to the result // Returns nullptr if holding bytes - absl::cord_internal::CordRep* tree() const; - absl::cord_internal::CordRep* as_tree() const; - const char* as_chars() const; + absl::Nullable<absl::cord_internal::CordRep*> tree() const; + absl::Nonnull<absl::cord_internal::CordRep*> as_tree() const; + absl::Nonnull<const char*> as_chars() const; // Returns non-null iff was holding a pointer - absl::cord_internal::CordRep* clear(); + absl::Nullable<absl::cord_internal::CordRep*> clear(); // Converts to pointer if necessary. void reduce_size(size_t n); // REQUIRES: holding data void remove_prefix(size_t n); // REQUIRES: holding data @@ -858,46 +887,52 @@ class Cord { // Creates a CordRepFlat instance from the current inlined data with `extra' // bytes of desired additional capacity. - CordRepFlat* MakeFlatWithExtraCapacity(size_t extra); + absl::Nonnull<CordRepFlat*> MakeFlatWithExtraCapacity(size_t extra); // Sets the tree value for this instance. `rep` must not be null. // Requires the current instance to hold a tree, and a lock to be held on // any CordzInfo referenced by this instance. The latter is enforced through // the CordzUpdateScope argument. If the current instance is sampled, then // the CordzInfo instance is updated to reference the new `rep` value. - void SetTree(CordRep* rep, const CordzUpdateScope& scope); + void SetTree(absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope); // Identical to SetTree(), except that `rep` is allowed to be null, in // which case the current instance is reset to an empty value. - void SetTreeOrEmpty(CordRep* rep, const CordzUpdateScope& scope); + void SetTreeOrEmpty(absl::Nullable<CordRep*> rep, + const CordzUpdateScope& scope); // Sets the tree value for this instance, and randomly samples this cord. // This function disregards existing contents in `data_`, and should be // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined' // value to a non-inlined (tree / ring) value. - void EmplaceTree(CordRep* rep, MethodIdentifier method); + void EmplaceTree(absl::Nonnull<CordRep*> rep, MethodIdentifier method); // Identical to EmplaceTree, except that it copies the parent stack from // the provided `parent` data if the parent is sampled. - void EmplaceTree(CordRep* rep, const InlineData& parent, + void EmplaceTree(absl::Nonnull<CordRep*> rep, const InlineData& parent, MethodIdentifier method); // Commits the change of a newly created, or updated `rep` root value into // this cord. `old_rep` indicates the old (inlined or tree) value of the // cord, and determines if the commit invokes SetTree() or EmplaceTree(). - void CommitTree(const CordRep* old_rep, CordRep* rep, - const CordzUpdateScope& scope, MethodIdentifier method); - - void AppendTreeToInlined(CordRep* tree, MethodIdentifier method); - void AppendTreeToTree(CordRep* tree, MethodIdentifier method); - void AppendTree(CordRep* tree, MethodIdentifier method); - void PrependTreeToInlined(CordRep* tree, MethodIdentifier method); - void PrependTreeToTree(CordRep* tree, MethodIdentifier method); - void PrependTree(CordRep* tree, MethodIdentifier method); + void CommitTree(absl::Nullable<const CordRep*> old_rep, + absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope, + MethodIdentifier method); + + void AppendTreeToInlined(absl::Nonnull<CordRep*> tree, + MethodIdentifier method); + void AppendTreeToTree(absl::Nonnull<CordRep*> tree, + MethodIdentifier method); + void AppendTree(absl::Nonnull<CordRep*> tree, MethodIdentifier method); + void PrependTreeToInlined(absl::Nonnull<CordRep*> tree, + MethodIdentifier method); + void PrependTreeToTree(absl::Nonnull<CordRep*> tree, + MethodIdentifier method); + void PrependTree(absl::Nonnull<CordRep*> tree, MethodIdentifier method); bool IsSame(const InlineRep& other) const { return data_ == other.data_; } - void CopyTo(std::string* dst) const { + 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. @@ -909,7 +944,7 @@ class Cord { } // Copies the inline contents into `dst`. Assumes the cord is not empty. - void CopyToArray(char* dst) const; + void CopyToArray(absl::Nonnull<char*> dst) const; bool is_tree() const { return data_.is_tree(); } @@ -922,12 +957,12 @@ class Cord { } // Returns the profiled CordzInfo, or nullptr if not sampled. - absl::cord_internal::CordzInfo* cordz_info() const { + absl::Nullable<absl::cord_internal::CordzInfo*> cordz_info() const { return data_.cordz_info(); } - // Sets the profiled CordzInfo. `cordz_info` must not be null. - void set_cordz_info(cord_internal::CordzInfo* cordz_info) { + // Sets the profiled CordzInfo. + void set_cordz_info(absl::Nonnull<cord_internal::CordzInfo*> cordz_info) { assert(cordz_info != nullptr); data_.set_cordz_info(cordz_info); } @@ -959,19 +994,19 @@ class Cord { InlineRep contents_; // Helper for GetFlat() and TryFlat(). - static bool GetFlatAux(absl::cord_internal::CordRep* rep, - absl::string_view* fragment); + static bool GetFlatAux(absl::Nonnull<absl::cord_internal::CordRep*> rep, + absl::Nonnull<absl::string_view*> fragment); // Helper for ForEachChunk(). static void ForEachChunkAux( - absl::cord_internal::CordRep* rep, + absl::Nonnull<absl::cord_internal::CordRep*> rep, absl::FunctionRef<void(absl::string_view)> callback); // The destructor for non-empty Cords. void DestroyCordSlow(); // Out-of-line implementation of slower parts of logic. - void CopyToArraySlowPath(char* dst) const; + void CopyToArraySlowPath(absl::Nonnull<char*> dst) const; int CompareSlowPath(absl::string_view rhs, size_t compared_size, size_t size_to_compare) const; int CompareSlowPath(const Cord& rhs, size_t compared_size, @@ -988,8 +1023,8 @@ class Cord { // Returns a new reference to contents_.tree(), or steals an existing // reference if called on an rvalue. - absl::cord_internal::CordRep* TakeRep() const&; - absl::cord_internal::CordRep* TakeRep() &&; + absl::Nonnull<absl::cord_internal::CordRep*> TakeRep() const&; + absl::Nonnull<absl::cord_internal::CordRep*> TakeRep() &&; // Helper for Append(). template <typename C> @@ -1026,7 +1061,10 @@ class Cord { friend class CrcCord; void SetCrcCordState(crc_internal::CrcCordState state); - const crc_internal::CrcCordState* MaybeGetCrcCordState() const; + absl::Nullable<const crc_internal::CrcCordState*> MaybeGetCrcCordState() + const; + + CharIterator FindImpl(CharIterator it, absl::string_view needle) const; }; ABSL_NAMESPACE_END @@ -1045,13 +1083,15 @@ namespace cord_internal { // Does non-template-specific `CordRepExternal` initialization. // Requires `data` to be non-empty. -void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep); +void InitializeCordRepExternal(absl::string_view data, + absl::Nonnull<CordRepExternal*> rep); // Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer // to it. Requires `data` to be non-empty. template <typename Releaser> // NOLINTNEXTLINE - suppress clang-tidy raw pointer return. -CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) { +absl::Nonnull<CordRep*> NewExternalRep(absl::string_view data, + Releaser&& releaser) { assert(!data.empty()); using ReleaserType = absl::decay_t<Releaser>; CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>( @@ -1063,7 +1103,7 @@ CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) { // Overload for function reference types that dispatches using a function // pointer because there are no `alignof()` or `sizeof()` a function reference. // NOLINTNEXTLINE - suppress clang-tidy raw pointer return. -inline CordRep* NewExternalRep(absl::string_view data, +inline absl::Nonnull<CordRep*> NewExternalRep(absl::string_view data, void (&releaser)(absl::string_view)) { return NewExternalRep(data, &releaser); } @@ -1086,7 +1126,8 @@ Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) { return cord; } -constexpr Cord::InlineRep::InlineRep(absl::string_view sv, CordRep* rep) +constexpr Cord::InlineRep::InlineRep(absl::string_view sv, + absl::Nullable<CordRep*> rep) : data_(sv, rep) {} inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) @@ -1125,28 +1166,30 @@ inline Cord::InlineRep& Cord::InlineRep::operator=( return *this; } -inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) { +inline void Cord::InlineRep::Swap(absl::Nonnull<Cord::InlineRep*> rhs) { if (rhs == this) { return; } std::swap(data_, rhs->data_); } -inline const char* Cord::InlineRep::data() const { +inline absl::Nullable<const char*> Cord::InlineRep::data() const { return is_tree() ? nullptr : data_.as_chars(); } -inline const char* Cord::InlineRep::as_chars() const { +inline absl::Nonnull<const char*> Cord::InlineRep::as_chars() const { assert(!data_.is_tree()); return data_.as_chars(); } -inline absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const { +inline absl::Nonnull<absl::cord_internal::CordRep*> Cord::InlineRep::as_tree() + const { assert(data_.is_tree()); return data_.as_tree(); } -inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const { +inline absl::Nullable<absl::cord_internal::CordRep*> Cord::InlineRep::tree() + const { if (is_tree()) { return as_tree(); } else { @@ -1154,14 +1197,12 @@ inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const { } } -inline bool Cord::InlineRep::empty() const { return data_.is_empty(); } - inline size_t Cord::InlineRep::size() const { return is_tree() ? as_tree()->length : inline_size(); } -inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity( - size_t extra) { +inline absl::Nonnull<cord_internal::CordRepFlat*> +Cord::InlineRep::MakeFlatWithExtraCapacity(size_t extra) { static_assert(cord_internal::kMinFlatLength >= sizeof(data_), ""); size_t len = data_.inline_size(); auto* result = CordRepFlat::New(len + extra); @@ -1170,20 +1211,21 @@ inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity( return result; } -inline void Cord::InlineRep::EmplaceTree(CordRep* rep, +inline void Cord::InlineRep::EmplaceTree(absl::Nonnull<CordRep*> rep, MethodIdentifier method) { assert(rep); data_.make_tree(rep); CordzInfo::MaybeTrackCord(data_, method); } -inline void Cord::InlineRep::EmplaceTree(CordRep* rep, const InlineData& parent, +inline void Cord::InlineRep::EmplaceTree(absl::Nonnull<CordRep*> rep, + const InlineData& parent, MethodIdentifier method) { data_.make_tree(rep); CordzInfo::MaybeTrackCord(data_, parent, method); } -inline void Cord::InlineRep::SetTree(CordRep* rep, +inline void Cord::InlineRep::SetTree(absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope) { assert(rep); assert(data_.is_tree()); @@ -1191,7 +1233,7 @@ inline void Cord::InlineRep::SetTree(CordRep* rep, scope.SetCordRep(rep); } -inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep, +inline void Cord::InlineRep::SetTreeOrEmpty(absl::Nullable<CordRep*> rep, const CordzUpdateScope& scope) { assert(data_.is_tree()); if (rep) { @@ -1202,7 +1244,8 @@ inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep, scope.SetCordRep(rep); } -inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep, +inline void Cord::InlineRep::CommitTree(absl::Nullable<const CordRep*> old_rep, + absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope, MethodIdentifier method) { if (old_rep) { @@ -1212,7 +1255,7 @@ inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep, } } -inline absl::cord_internal::CordRep* Cord::InlineRep::clear() { +inline absl::Nullable<absl::cord_internal::CordRep*> Cord::InlineRep::clear() { if (is_tree()) { CordzInfo::MaybeUntrackCord(cordz_info()); } @@ -1221,7 +1264,7 @@ inline absl::cord_internal::CordRep* Cord::InlineRep::clear() { return result; } -inline void Cord::InlineRep::CopyToArray(char* dst) const { +inline void Cord::InlineRep::CopyToArray(absl::Nonnull<char*> dst) const { assert(!is_tree()); size_t n = inline_size(); assert(n != 0); @@ -1402,7 +1445,8 @@ inline bool Cord::StartsWith(absl::string_view rhs) const { return EqualsImpl(rhs, rhs_size); } -inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) { +inline void Cord::ChunkIterator::InitTree( + absl::Nonnull<cord_internal::CordRep*> tree) { tree = cord_internal::SkipCrcNode(tree); if (tree->tag == cord_internal::BTREE) { current_chunk_ = btree_reader_.Init(tree->btree()); @@ -1412,12 +1456,13 @@ inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) { } } -inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree) { +inline Cord::ChunkIterator::ChunkIterator( + absl::Nonnull<cord_internal::CordRep*> tree) { bytes_remaining_ = tree->length; InitTree(tree); } -inline Cord::ChunkIterator::ChunkIterator(const Cord* cord) { +inline Cord::ChunkIterator::ChunkIterator(absl::Nonnull<const Cord*> cord) { if (CordRep* tree = cord->contents_.tree()) { bytes_remaining_ = tree->length; if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) { @@ -1557,12 +1602,13 @@ inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const { return chunk_iterator_->data(); } -inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) { +inline Cord Cord::AdvanceAndRead(absl::Nonnull<CharIterator*> it, + size_t n_bytes) { assert(it != nullptr); return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes); } -inline void Cord::Advance(CharIterator* it, size_t n_bytes) { +inline void Cord::Advance(absl::Nonnull<CharIterator*> it, size_t n_bytes) { assert(it != nullptr); it->chunk_iterator_.AdvanceBytes(n_bytes); } @@ -1618,7 +1664,7 @@ inline bool operator>=(const Cord& x, const Cord& y) { // Nonmember Cord-to-absl::string_view relational operators. // // Due to implicit conversions, these also enable comparisons of Cord with -// with std::string, ::string, and const char*. +// std::string and const char*. inline bool operator==(const Cord& lhs, absl::string_view rhs) { size_t lhs_size = lhs.size(); size_t rhs_size = rhs.size(); diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.cc b/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.cc index e859b0db06..19b0fa4436 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.cc @@ -14,23 +14,17 @@ #include "absl/strings/cord_analysis.h" +#include <cassert> #include <cstddef> #include <cstdint> #include <unordered_set> -#include "absl/base/attributes.h" #include "absl/base/config.h" -#include "absl/container/inlined_vector.h" +#include "absl/base/nullability.h" #include "absl/strings/internal/cord_data_edge.h" #include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_rep_btree.h" #include "absl/strings/internal/cord_rep_crc.h" -#include "absl/strings/internal/cord_rep_flat.h" -#include "absl/strings/internal/cord_rep_ring.h" -// -#include "absl/base/macros.h" -#include "absl/base/port.h" -#include "absl/functional/function_ref.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -45,13 +39,15 @@ enum class Mode { kFairShare, kTotal, kTotalMorePrecise }; template <Mode mode> struct CordRepRef { // Instantiates a CordRepRef instance. - explicit CordRepRef(const CordRep* r) : rep(r) {} + explicit CordRepRef(absl::Nonnull<const CordRep*> r) : rep(r) {} // Creates a child reference holding the provided child. // Overloaded to add cumulative reference count for kFairShare. - CordRepRef Child(const CordRep* child) const { return CordRepRef(child); } + CordRepRef Child(absl::Nonnull<const CordRep*> child) const { + return CordRepRef(child); + } - const CordRep* rep; + absl::Nonnull<const CordRep*> rep; }; // RawUsage holds the computed total number of bytes. @@ -70,11 +66,10 @@ template <> struct RawUsage<Mode::kTotalMorePrecise> { size_t total = 0; // TODO(b/289250880): Replace this with a flat_hash_set. - std::unordered_set<const CordRep*> counted; + std::unordered_set<absl::Nonnull<const CordRep*>> counted; void Add(size_t size, CordRepRef<Mode::kTotalMorePrecise> repref) { - if (counted.find(repref.rep) == counted.end()) { - counted.insert(repref.rep); + if (counted.insert(repref.rep).second) { total += size; } } @@ -95,15 +90,15 @@ double MaybeDiv(double d, refcount_t refcount) { template <> struct CordRepRef<Mode::kFairShare> { // Creates a CordRepRef with the provided rep and top (parent) fraction. - explicit CordRepRef(const CordRep* r, double frac = 1.0) + explicit CordRepRef(absl::Nonnull<const CordRep*> r, double frac = 1.0) : rep(r), fraction(MaybeDiv(frac, r->refcount.Get())) {} // Returns a CordRepRef with a fraction of `this->fraction / child.refcount` - CordRepRef Child(const CordRep* child) const { + CordRepRef Child(absl::Nonnull<const CordRep*> child) const { return CordRepRef(child, fraction); } - const CordRep* rep; + absl::Nonnull<const CordRep*> rep; double fraction; }; @@ -138,16 +133,6 @@ void AnalyzeDataEdge(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) { raw_usage.Add(size, rep); } -// Computes the memory size of the provided Ring tree. -template <Mode mode> -void AnalyzeRing(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) { - const CordRepRing* ring = rep.rep->ring(); - raw_usage.Add(CordRepRing::AllocSize(ring->capacity()), rep); - ring->ForEach([&](CordRepRing::index_type pos) { - AnalyzeDataEdge(rep.Child(ring->entry_child(pos)), raw_usage); - }); -} - // Computes the memory size of the provided Btree tree. template <Mode mode> void AnalyzeBtree(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) { @@ -165,7 +150,7 @@ void AnalyzeBtree(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) { } template <Mode mode> -size_t GetEstimatedUsage(const CordRep* rep) { +size_t GetEstimatedUsage(absl::Nonnull<const CordRep*> rep) { // Zero initialized memory usage totals. RawUsage<mode> raw_usage; @@ -175,6 +160,9 @@ size_t GetEstimatedUsage(const CordRep* rep) { // Consume the top level CRC node if present. if (repref.rep->tag == CRC) { raw_usage.Add(sizeof(CordRepCrc), repref); + if (repref.rep->crc()->child == nullptr) { + return static_cast<size_t>(raw_usage.total); + } repref = repref.Child(repref.rep->crc()->child); } @@ -182,8 +170,6 @@ size_t GetEstimatedUsage(const CordRep* rep) { AnalyzeDataEdge(repref, raw_usage); } else if (repref.rep->tag == BTREE) { AnalyzeBtree(repref, raw_usage); - } else if (repref.rep->tag == RING) { - AnalyzeRing(repref, raw_usage); } else { assert(false); } @@ -193,15 +179,15 @@ size_t GetEstimatedUsage(const CordRep* rep) { } // namespace -size_t GetEstimatedMemoryUsage(const CordRep* rep) { +size_t GetEstimatedMemoryUsage(absl::Nonnull<const CordRep*> rep) { return GetEstimatedUsage<Mode::kTotal>(rep); } -size_t GetEstimatedFairShareMemoryUsage(const CordRep* rep) { +size_t GetEstimatedFairShareMemoryUsage(absl::Nonnull<const CordRep*> rep) { return GetEstimatedUsage<Mode::kFairShare>(rep); } -size_t GetMorePreciseMemoryUsage(const CordRep* rep) { +size_t GetMorePreciseMemoryUsage(absl::Nonnull<const CordRep*> rep) { return GetEstimatedUsage<Mode::kTotalMorePrecise>(rep); } diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.h b/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.h index 9b9527a57d..f8ce348984 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.h +++ b/contrib/restricted/abseil-cpp/absl/strings/cord_analysis.h @@ -19,6 +19,7 @@ #include <cstdint> #include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/strings/internal/cord_internal.h" namespace absl { @@ -28,7 +29,7 @@ namespace cord_internal { // Returns the *approximate* number of bytes held in full or in part by this // Cord (which may not remain the same between invocations). Cords that share // memory could each be "charged" independently for the same shared memory. -size_t GetEstimatedMemoryUsage(const CordRep* rep); +size_t GetEstimatedMemoryUsage(absl::Nonnull<const CordRep*> rep); // Returns the *approximate* number of bytes held in full or in part by this // Cord for the distinct memory held by this cord. This is similar to @@ -46,13 +47,13 @@ size_t GetEstimatedMemoryUsage(const CordRep* rep); // // This is more expensive than `GetEstimatedMemoryUsage()` as it requires // deduplicating all memory references. -size_t GetMorePreciseMemoryUsage(const CordRep* rep); +size_t GetMorePreciseMemoryUsage(absl::Nonnull<const CordRep*> rep); // Returns the *approximate* number of bytes held in full or in part by this // CordRep weighted by the sharing ratio of that data. For example, if some data // edge is shared by 4 different Cords, then each cord is attribute 1/4th of // the total memory usage as a 'fair share' of the total memory usage. -size_t GetEstimatedFairShareMemoryUsage(const CordRep* rep); +size_t GetEstimatedFairShareMemoryUsage(absl::Nonnull<const CordRep*> rep); } // namespace cord_internal ABSL_NAMESPACE_END diff --git a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc index 2827fbaa37..1c0eac42d7 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc @@ -16,21 +16,22 @@ #include <algorithm> #include <cassert> +#include <cstddef> #include <cstdint> #include <cstring> -#include <iterator> #include <limits> #include <string> -#include "absl/base/internal/endian.h" +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/unaligned_access.h" -#include "absl/strings/internal/char_map.h" +#include "absl/strings/ascii.h" +#include "absl/strings/charset.h" #include "absl/strings/internal/escaping.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/utf8.h" +#include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" -#include "absl/strings/str_join.h" #include "absl/strings/string_view.h" namespace absl { diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/has_absl_stringify.h b/contrib/restricted/abseil-cpp/absl/strings/has_absl_stringify.h index 55a0850829..274a7865d1 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/has_absl_stringify.h +++ b/contrib/restricted/abseil-cpp/absl/strings/has_absl_stringify.h @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef ABSL_STRINGS_INTERNAL_HAS_ABSL_STRINGIFY_H_ -#define ABSL_STRINGS_INTERNAL_HAS_ABSL_STRINGIFY_H_ -#include <string> +#ifndef ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_ +#define ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_ + #include <type_traits> #include <utility> @@ -38,6 +38,16 @@ class UnimplementedSink { friend void AbslFormatFlush(UnimplementedSink* sink, absl::string_view v); }; +} // namespace strings_internal + +// `HasAbslStringify<T>` detects if type `T` supports the `AbslStringify()` +// customization point (see +// https://abseil.io/docs/cpp/guides/format#abslstringify for the +// documentation). +// +// Note that there are types that can be `StrCat`-ed that do not use the +// `AbslStringify` customization point (for example, `int`). + template <typename T, typename = void> struct HasAbslStringify : std::false_type {}; @@ -47,9 +57,7 @@ struct HasAbslStringify< std::declval<strings_internal::UnimplementedSink&>(), std::declval<const T&>()))>::value>> : std::true_type {}; -} // namespace strings_internal - ABSL_NAMESPACE_END } // namespace absl -#endif // ABSL_STRINGS_INTERNAL_HAS_ABSL_STRINGIFY_H_ +#endif // ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_ diff --git a/contrib/restricted/abseil-cpp/absl/strings/has_ostream_operator.h b/contrib/restricted/abseil-cpp/absl/strings/has_ostream_operator.h new file mode 100644 index 0000000000..156ffc743d --- /dev/null +++ b/contrib/restricted/abseil-cpp/absl/strings/has_ostream_operator.h @@ -0,0 +1,42 @@ +// Copyright 2023 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_ +#define ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_ + +#include <ostream> +#include <type_traits> +#include <utility> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// Detects if type `T` supports streaming to `std::ostream`s with `operator<<`. + +template <typename T, typename = void> +struct HasOstreamOperator : std::false_type {}; + +template <typename T> +struct HasOstreamOperator< + T, std::enable_if_t<std::is_same< + std::ostream&, decltype(std::declval<std::ostream&>() + << std::declval<const T&>())>::value>> + : std::true_type {}; + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_ diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h b/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h deleted file mode 100644 index 70a9034336..0000000000 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Character Map Class -// -// A fast, bit-vector map for 8-bit unsigned characters. -// This class is useful for non-character purposes as well. - -#ifndef ABSL_STRINGS_INTERNAL_CHAR_MAP_H_ -#define ABSL_STRINGS_INTERNAL_CHAR_MAP_H_ - -#include <cstddef> -#include <cstdint> -#include <cstring> - -#include "absl/base/macros.h" -#include "absl/base/port.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace strings_internal { - -class Charmap { - public: - constexpr Charmap() : m_() {} - - // Initializes with a given char*. Note that NUL is not treated as - // a terminator, but rather a char to be flicked. - Charmap(const char* str, int len) : m_() { - while (len--) SetChar(*str++); - } - - // Initializes with a given char*. NUL is treated as a terminator - // and will not be in the charmap. - explicit Charmap(const char* str) : m_() { - while (*str) SetChar(*str++); - } - - constexpr bool contains(unsigned char c) const { - return (m_[c / 64] >> (c % 64)) & 0x1; - } - - // Returns true if and only if a character exists in both maps. - bool IntersectsWith(const Charmap& c) const { - for (size_t i = 0; i < ABSL_ARRAYSIZE(m_); ++i) { - if ((m_[i] & c.m_[i]) != 0) return true; - } - return false; - } - - bool IsZero() const { - for (uint64_t c : m_) { - if (c != 0) return false; - } - return true; - } - - // Containing only a single specified char. - static constexpr Charmap Char(char x) { - return Charmap(CharMaskForWord(x, 0), CharMaskForWord(x, 1), - CharMaskForWord(x, 2), CharMaskForWord(x, 3)); - } - - // Containing all the chars in the C-string 's'. - static constexpr Charmap FromString(const char* s) { - Charmap ret; - while (*s) ret = ret | Char(*s++); - return ret; - } - - // Containing all the chars in the closed interval [lo,hi]. - static constexpr Charmap Range(char lo, char hi) { - return Charmap(RangeForWord(lo, hi, 0), RangeForWord(lo, hi, 1), - RangeForWord(lo, hi, 2), RangeForWord(lo, hi, 3)); - } - - friend constexpr Charmap operator&(const Charmap& a, const Charmap& b) { - return Charmap(a.m_[0] & b.m_[0], a.m_[1] & b.m_[1], a.m_[2] & b.m_[2], - a.m_[3] & b.m_[3]); - } - - friend constexpr Charmap operator|(const Charmap& a, const Charmap& b) { - return Charmap(a.m_[0] | b.m_[0], a.m_[1] | b.m_[1], a.m_[2] | b.m_[2], - a.m_[3] | b.m_[3]); - } - - friend constexpr Charmap operator~(const Charmap& a) { - return Charmap(~a.m_[0], ~a.m_[1], ~a.m_[2], ~a.m_[3]); - } - - private: - constexpr Charmap(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3) - : m_{b0, b1, b2, b3} {} - - static constexpr uint64_t RangeForWord(char lo, char hi, uint64_t word) { - return OpenRangeFromZeroForWord(static_cast<unsigned char>(hi) + 1, word) & - ~OpenRangeFromZeroForWord(static_cast<unsigned char>(lo), word); - } - - // All the chars in the specified word of the range [0, upper). - static constexpr uint64_t OpenRangeFromZeroForWord(uint64_t upper, - uint64_t word) { - return (upper <= 64 * word) - ? 0 - : (upper >= 64 * (word + 1)) - ? ~static_cast<uint64_t>(0) - : (~static_cast<uint64_t>(0) >> (64 - upper % 64)); - } - - static constexpr uint64_t CharMaskForWord(char x, uint64_t word) { - const auto unsigned_x = static_cast<unsigned char>(x); - return (unsigned_x / 64 == word) - ? (static_cast<uint64_t>(1) << (unsigned_x % 64)) - : 0; - } - - void SetChar(char c) { - const auto unsigned_c = static_cast<unsigned char>(c); - m_[unsigned_c / 64] |= static_cast<uint64_t>(1) << (unsigned_c % 64); - } - - uint64_t m_[4]; -}; - -// Mirror the char-classifying predicates in <cctype> -constexpr Charmap UpperCharmap() { return Charmap::Range('A', 'Z'); } -constexpr Charmap LowerCharmap() { return Charmap::Range('a', 'z'); } -constexpr Charmap DigitCharmap() { return Charmap::Range('0', '9'); } -constexpr Charmap AlphaCharmap() { return LowerCharmap() | UpperCharmap(); } -constexpr Charmap AlnumCharmap() { return DigitCharmap() | AlphaCharmap(); } -constexpr Charmap XDigitCharmap() { - return DigitCharmap() | Charmap::Range('A', 'F') | Charmap::Range('a', 'f'); -} -constexpr Charmap PrintCharmap() { return Charmap::Range(0x20, 0x7e); } -constexpr Charmap SpaceCharmap() { return Charmap::FromString("\t\n\v\f\r "); } -constexpr Charmap CntrlCharmap() { - return Charmap::Range(0, 0x7f) & ~PrintCharmap(); -} -constexpr Charmap BlankCharmap() { return Charmap::FromString("\t "); } -constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); } -constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); } - -} // namespace strings_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_ diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.cc index b7874385de..57d9d385b3 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.cc @@ -22,15 +22,12 @@ #include "absl/strings/internal/cord_rep_btree.h" #include "absl/strings/internal/cord_rep_crc.h" #include "absl/strings/internal/cord_rep_flat.h" -#include "absl/strings/internal/cord_rep_ring.h" #include "absl/strings/str_cat.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace cord_internal { -ABSL_CONST_INIT std::atomic<bool> cord_ring_buffer_enabled( - kCordEnableRingBufferDefault); ABSL_CONST_INIT std::atomic<bool> shallow_subcords_enabled( kCordShallowSubcordsDefault); @@ -47,9 +44,6 @@ void CordRep::Destroy(CordRep* rep) { if (rep->tag == BTREE) { CordRepBtree::Destroy(rep->btree()); return; - } else if (rep->tag == RING) { - CordRepRing::Destroy(rep->ring()); - return; } else if (rep->tag == EXTERNAL) { CordRepExternal::Delete(rep); return; 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 20dd008cfa..8744540e2a 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h @@ -55,24 +55,15 @@ struct CordRepExternal; struct CordRepFlat; struct CordRepSubstring; struct CordRepCrc; -class CordRepRing; class CordRepBtree; class CordzInfo; // Default feature enable states for cord ring buffers -enum CordFeatureDefaults { - kCordEnableRingBufferDefault = false, - kCordShallowSubcordsDefault = false -}; +enum CordFeatureDefaults { kCordShallowSubcordsDefault = false }; -extern std::atomic<bool> cord_ring_buffer_enabled; extern std::atomic<bool> shallow_subcords_enabled; -inline void enable_cord_ring_buffer(bool enable) { - cord_ring_buffer_enabled.store(enable, std::memory_order_relaxed); -} - inline void enable_shallow_subcords(bool enable) { shallow_subcords_enabled.store(enable, std::memory_order_relaxed); } @@ -110,8 +101,16 @@ inline void SmallMemmove(char* dst, const char* src, size_t n) { if (nullify_tail) { memset(dst + 7, 0, 8); } + // GCC 12 has a false-positive -Wstringop-overflow warning here. +#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif memcpy(dst, &buf1, 8); memcpy(dst + n - 8, &buf2, 8); +#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0) +#pragma GCC diagnostic pop +#endif } else if (n >= 4) { uint32_t buf1; uint32_t buf2; @@ -158,18 +157,18 @@ class RefcountAndFlags { // false. Always returns false when the immortal bit is set. inline bool Decrement() { int32_t refcount = count_.load(std::memory_order_acquire); - assert((refcount & kRefcountMask) > 0 || refcount & kImmortalFlag); + assert(refcount > 0 || refcount & kImmortalFlag); return refcount != kRefIncrement && - (count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) & - kHighRefcountMask) != 0; + count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) != + kRefIncrement; } // Same as Decrement but expect that refcount is greater than 1. inline bool DecrementExpectHighRefcount() { int32_t refcount = count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel); - assert((refcount & kRefcountMask) > 0 || refcount & kImmortalFlag); - return (refcount & kHighRefcountMask) != 0; + assert(refcount > 0 || refcount & kImmortalFlag); + return refcount != kRefIncrement; } // Returns the current reference count using acquire semantics. @@ -185,10 +184,9 @@ class RefcountAndFlags { // This call performs the test for a reference count of one, and // performs the memory barrier needed for the owning thread // to act on the object, knowing that it has exclusive access to the - // object. Always returns false when the immortal bit is set. + // object. Always returns false when the immortal bit is set. inline bool IsOne() { - return (count_.load(std::memory_order_acquire) & kRefcountMask) == - kRefIncrement; + return count_.load(std::memory_order_acquire) == kRefIncrement; } bool IsImmortal() const { @@ -196,32 +194,15 @@ class RefcountAndFlags { } private: - // We reserve the bottom bits for flags. + // We reserve the bottom bit for flag. // kImmortalBit indicates that this entity should never be collected; it is // used for the StringConstant constructor to avoid collecting immutable // constant cords. - // kReservedFlag is reserved for future use. enum Flags { - kNumFlags = 2, + kNumFlags = 1, kImmortalFlag = 0x1, - kReservedFlag = 0x2, kRefIncrement = (1 << kNumFlags), - - // Bitmask to use when checking refcount by equality. This masks out - // all flags except kImmortalFlag, which is part of the refcount for - // purposes of equality. (A refcount of 0 or 1 does not count as 0 or 1 - // if the immortal bit is set.) - kRefcountMask = ~kReservedFlag, - - // Bitmask to use when checking if refcount is equal to 1 and not - // immortal when decrementing the refcount. This masks out kRefIncrement and - // all flags except kImmortalFlag. If the masked RefcountAndFlags is 0, we - // assume the refcount is equal to 1, since we know it's not immortal and - // not greater than 1. If the masked RefcountAndFlags is not 0, we can - // assume the refcount is not equal to 1 since either a higher bit in the - // refcount is set, or kImmortal is set. - kHighRefcountMask = kRefcountMask & ~kRefIncrement, }; std::atomic<int32_t> count_; @@ -233,7 +214,7 @@ enum CordRepKind { SUBSTRING = 1, CRC = 2, BTREE = 3, - RING = 4, + UNUSED_4 = 4, EXTERNAL = 5, // We have different tags for different sized flat arrays, @@ -252,12 +233,8 @@ enum CordRepKind { // There are various locations where we want to check if some rep is a 'plain' // data edge, i.e. an external or flat rep. By having FLAT == EXTERNAL + 1, we // can perform this check in a single branch as 'tag >= EXTERNAL' -// Likewise, we have some locations where we check for 'ring or external/flat', -// so likewise align RING to EXTERNAL. // Note that we can leave this optimization to the compiler. The compiler will // DTRT when it sees a condition like `tag == EXTERNAL || tag >= FLAT`. -static_assert(RING == BTREE + 1, "BTREE and RING not consecutive"); -static_assert(EXTERNAL == RING + 1, "BTREE and EXTERNAL not consecutive"); static_assert(FLAT == EXTERNAL + 1, "EXTERNAL and FLAT not consecutive"); struct CordRep { @@ -301,15 +278,12 @@ struct CordRep { // # LINT.ThenChange(cord_rep_btree.h:copy_raw) // Returns true if this instance's tag matches the requested type. - constexpr bool IsRing() const { return tag == RING; } constexpr bool IsSubstring() const { return tag == SUBSTRING; } constexpr bool IsCrc() const { return tag == CRC; } constexpr bool IsExternal() const { return tag == EXTERNAL; } constexpr bool IsFlat() const { return tag >= FLAT; } constexpr bool IsBtree() const { return tag == BTREE; } - inline CordRepRing* ring(); - inline const CordRepRing* ring() const; inline CordRepSubstring* substring(); inline const CordRepSubstring* substring() const; inline CordRepCrc* crc(); diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_ring.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_ring.cc deleted file mode 100644 index af2fc7683d..0000000000 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_ring.cc +++ /dev/null @@ -1,773 +0,0 @@ -// Copyright 2020 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/strings/internal/cord_rep_ring.h" - -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <iostream> -#include <limits> -#include <memory> -#include <string> - -#include "absl/base/internal/raw_logging.h" -#include "absl/base/internal/throw_delegate.h" -#include "absl/base/macros.h" -#include "absl/container/inlined_vector.h" -#include "absl/strings/internal/cord_internal.h" -#include "absl/strings/internal/cord_rep_consume.h" -#include "absl/strings/internal/cord_rep_flat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace cord_internal { - -namespace { - -using index_type = CordRepRing::index_type; - -enum class Direction { kForward, kReversed }; - -inline bool IsFlatOrExternal(CordRep* rep) { - return rep->IsFlat() || rep->IsExternal(); -} - -// Verifies that n + extra <= kMaxCapacity: throws std::length_error otherwise. -inline void CheckCapacity(size_t n, size_t extra) { - if (ABSL_PREDICT_FALSE(extra > CordRepRing::kMaxCapacity - n)) { - base_internal::ThrowStdLengthError("Maximum capacity exceeded"); - } -} - -// Creates a flat from the provided string data, allocating up to `extra` -// capacity in the returned flat depending on kMaxFlatLength limitations. -// Requires `len` to be less or equal to `kMaxFlatLength` -CordRepFlat* CreateFlat(const char* s, size_t n, size_t extra = 0) { // NOLINT - assert(n <= kMaxFlatLength); - auto* rep = CordRepFlat::New(n + extra); - rep->length = n; - memcpy(rep->Data(), s, n); - return rep; -} - -// Unrefs the entries in `[head, tail)`. -// Requires all entries to be a FLAT or EXTERNAL node. -void UnrefEntries(const CordRepRing* rep, index_type head, index_type tail) { - rep->ForEach(head, tail, [rep](index_type ix) { - CordRep* child = rep->entry_child(ix); - if (!child->refcount.Decrement()) { - if (child->tag >= FLAT) { - CordRepFlat::Delete(child->flat()); - } else { - CordRepExternal::Delete(child->external()); - } - } - }); -} - -} // namespace - -std::ostream& operator<<(std::ostream& s, const CordRepRing& rep) { - // Note: 'pos' values are defined as size_t (for overflow reasons), but that - // prints really awkward for small prepended values such as -5. ssize_t is not - // portable (POSIX), so we use ptrdiff_t instead to cast to signed values. - s << " CordRepRing(" << &rep << ", length = " << rep.length - << ", head = " << rep.head_ << ", tail = " << rep.tail_ - << ", cap = " << rep.capacity_ << ", rc = " << rep.refcount.Get() - << ", begin_pos_ = " << static_cast<ptrdiff_t>(rep.begin_pos_) << ") {\n"; - CordRepRing::index_type head = rep.head(); - do { - CordRep* child = rep.entry_child(head); - s << " entry[" << head << "] length = " << rep.entry_length(head) - << ", child " << child << ", clen = " << child->length - << ", tag = " << static_cast<int>(child->tag) - << ", rc = " << child->refcount.Get() - << ", offset = " << rep.entry_data_offset(head) - << ", end_pos = " << static_cast<ptrdiff_t>(rep.entry_end_pos(head)) - << "\n"; - head = rep.advance(head); - } while (head != rep.tail()); - return s << "}\n"; -} - -void CordRepRing::AddDataOffset(index_type index, size_t n) { - entry_data_offset()[index] += static_cast<offset_type>(n); -} - -void CordRepRing::SubLength(index_type index, size_t n) { - entry_end_pos()[index] -= n; -} - -class CordRepRing::Filler { - public: - Filler(CordRepRing* rep, index_type pos) : rep_(rep), head_(pos), pos_(pos) {} - - index_type head() const { return head_; } - index_type pos() const { return pos_; } - - void Add(CordRep* child, size_t offset, pos_type end_pos) { - rep_->entry_end_pos()[pos_] = end_pos; - rep_->entry_child()[pos_] = child; - rep_->entry_data_offset()[pos_] = static_cast<offset_type>(offset); - pos_ = rep_->advance(pos_); - } - - private: - CordRepRing* rep_; - index_type head_; - index_type pos_; -}; - -#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL -constexpr size_t CordRepRing::kMaxCapacity; -#endif - -bool CordRepRing::IsValid(std::ostream& output) const { - if (capacity_ == 0) { - output << "capacity == 0"; - return false; - } - - if (head_ >= capacity_ || tail_ >= capacity_) { - output << "head " << head_ << " and/or tail " << tail_ << "exceed capacity " - << capacity_; - return false; - } - - const index_type back = retreat(tail_); - size_t pos_length = Distance(begin_pos_, entry_end_pos(back)); - if (pos_length != length) { - output << "length " << length << " does not match positional length " - << pos_length << " from begin_pos " << begin_pos_ << " and entry[" - << back << "].end_pos " << entry_end_pos(back); - return false; - } - - index_type head = head_; - pos_type begin_pos = begin_pos_; - do { - pos_type end_pos = entry_end_pos(head); - size_t entry_length = Distance(begin_pos, end_pos); - if (entry_length == 0) { - output << "entry[" << head << "] has an invalid length " << entry_length - << " from begin_pos " << begin_pos << " and end_pos " << end_pos; - return false; - } - - CordRep* child = entry_child(head); - if (child == nullptr) { - output << "entry[" << head << "].child == nullptr"; - return false; - } - if (child->tag < FLAT && child->tag != EXTERNAL) { - output << "entry[" << head << "].child has an invalid tag " - << static_cast<int>(child->tag); - return false; - } - - size_t offset = entry_data_offset(head); - if (offset >= child->length || entry_length > child->length - offset) { - output << "entry[" << head << "] has offset " << offset - << " and entry length " << entry_length - << " which are outside of the child's length of " << child->length; - return false; - } - - begin_pos = end_pos; - head = advance(head); - } while (head != tail_); - - return true; -} - -#ifdef EXTRA_CORD_RING_VALIDATION -CordRepRing* CordRepRing::Validate(CordRepRing* rep, const char* file, - int line) { - if (!rep->IsValid(std::cerr)) { - std::cerr << "\nERROR: CordRepRing corrupted"; - if (line) std::cerr << " at line " << line; - if (file) std::cerr << " in file " << file; - std::cerr << "\nContent = " << *rep; - abort(); - } - return rep; -} -#endif // EXTRA_CORD_RING_VALIDATION - -CordRepRing* CordRepRing::New(size_t capacity, size_t extra) { - CheckCapacity(capacity, extra); - - size_t size = AllocSize(capacity += extra); - void* mem = ::operator new(size); - auto* rep = new (mem) CordRepRing(static_cast<index_type>(capacity)); - rep->tag = RING; - rep->capacity_ = static_cast<index_type>(capacity); - rep->begin_pos_ = 0; - return rep; -} - -void CordRepRing::SetCapacityForTesting(size_t capacity) { - // Adjust for the changed layout - assert(capacity <= capacity_); - assert(head() == 0 || head() < tail()); - memmove(Layout::Partial(capacity).Pointer<1>(data_) + head(), - Layout::Partial(capacity_).Pointer<1>(data_) + head(), - entries() * sizeof(Layout::ElementType<1>)); - memmove(Layout::Partial(capacity, capacity).Pointer<2>(data_) + head(), - Layout::Partial(capacity_, capacity_).Pointer<2>(data_) + head(), - entries() * sizeof(Layout::ElementType<2>)); - capacity_ = static_cast<index_type>(capacity); -} - -void CordRepRing::Delete(CordRepRing* rep) { - assert(rep != nullptr && rep->IsRing()); -#if defined(__cpp_sized_deallocation) - size_t size = AllocSize(rep->capacity_); - rep->~CordRepRing(); - ::operator delete(rep, size); -#else - rep->~CordRepRing(); - ::operator delete(rep); -#endif -} - -void CordRepRing::Destroy(CordRepRing* rep) { - UnrefEntries(rep, rep->head(), rep->tail()); - Delete(rep); -} - -template <bool ref> -void CordRepRing::Fill(const CordRepRing* src, index_type head, - index_type tail) { - this->length = src->length; - head_ = 0; - tail_ = advance(0, src->entries(head, tail)); - begin_pos_ = src->begin_pos_; - - // TODO(mvels): there may be opportunities here for large buffers. - auto* dst_pos = entry_end_pos(); - auto* dst_child = entry_child(); - auto* dst_offset = entry_data_offset(); - src->ForEach(head, tail, [&](index_type index) { - *dst_pos++ = src->entry_end_pos(index); - CordRep* child = src->entry_child(index); - *dst_child++ = ref ? CordRep::Ref(child) : child; - *dst_offset++ = src->entry_data_offset(index); - }); -} - -CordRepRing* CordRepRing::Copy(CordRepRing* rep, index_type head, - index_type tail, size_t extra) { - CordRepRing* newrep = CordRepRing::New(rep->entries(head, tail), extra); - newrep->Fill<true>(rep, head, tail); - CordRep::Unref(rep); - return newrep; -} - -CordRepRing* CordRepRing::Mutable(CordRepRing* rep, size_t extra) { - // Get current number of entries, and check for max capacity. - size_t entries = rep->entries(); - - if (!rep->refcount.IsOne()) { - return Copy(rep, rep->head(), rep->tail(), extra); - } else if (entries + extra > rep->capacity()) { - const size_t min_grow = rep->capacity() + rep->capacity() / 2; - const size_t min_extra = (std::max)(extra, min_grow - entries); - CordRepRing* newrep = CordRepRing::New(entries, min_extra); - newrep->Fill<false>(rep, rep->head(), rep->tail()); - CordRepRing::Delete(rep); - return newrep; - } else { - return rep; - } -} - -Span<char> CordRepRing::GetAppendBuffer(size_t size) { - assert(refcount.IsOne()); - index_type back = retreat(tail_); - CordRep* child = entry_child(back); - if (child->tag >= FLAT && child->refcount.IsOne()) { - size_t capacity = child->flat()->Capacity(); - pos_type end_pos = entry_end_pos(back); - size_t data_offset = entry_data_offset(back); - size_t entry_length = Distance(entry_begin_pos(back), end_pos); - size_t used = data_offset + entry_length; - if (size_t n = (std::min)(capacity - used, size)) { - child->length = data_offset + entry_length + n; - entry_end_pos()[back] = end_pos + n; - this->length += n; - return {child->flat()->Data() + used, n}; - } - } - return {nullptr, 0}; -} - -Span<char> CordRepRing::GetPrependBuffer(size_t size) { - assert(refcount.IsOne()); - CordRep* child = entry_child(head_); - size_t data_offset = entry_data_offset(head_); - if (data_offset && child->refcount.IsOne() && child->tag >= FLAT) { - size_t n = (std::min)(data_offset, size); - this->length += n; - begin_pos_ -= n; - data_offset -= n; - entry_data_offset()[head_] = static_cast<offset_type>(data_offset); - return {child->flat()->Data() + data_offset, n}; - } - return {nullptr, 0}; -} - -CordRepRing* CordRepRing::CreateFromLeaf(CordRep* child, size_t offset, - size_t len, size_t extra) { - CordRepRing* rep = CordRepRing::New(1, extra); - rep->head_ = 0; - rep->tail_ = rep->advance(0); - rep->length = len; - rep->entry_end_pos()[0] = len; - rep->entry_child()[0] = child; - rep->entry_data_offset()[0] = static_cast<offset_type>(offset); - return Validate(rep); -} - -CordRepRing* CordRepRing::CreateSlow(CordRep* child, size_t extra) { - CordRepRing* rep = nullptr; - Consume(child, [&](CordRep* child_arg, size_t offset, size_t len) { - if (IsFlatOrExternal(child_arg)) { - rep = rep ? AppendLeaf(rep, child_arg, offset, len) - : CreateFromLeaf(child_arg, offset, len, extra); - } else if (rep) { - rep = AddRing<AddMode::kAppend>(rep, child_arg->ring(), offset, len); - } else if (offset == 0 && child_arg->length == len) { - rep = Mutable(child_arg->ring(), extra); - } else { - rep = SubRing(child_arg->ring(), offset, len, extra); - } - }); - return Validate(rep, nullptr, __LINE__); -} - -CordRepRing* CordRepRing::Create(CordRep* child, size_t extra) { - size_t length = child->length; - if (IsFlatOrExternal(child)) { - return CreateFromLeaf(child, 0, length, extra); - } - if (child->IsRing()) { - return Mutable(child->ring(), extra); - } - return CreateSlow(child, extra); -} - -template <CordRepRing::AddMode mode> -CordRepRing* CordRepRing::AddRing(CordRepRing* rep, CordRepRing* ring, - size_t offset, size_t len) { - assert(offset < ring->length); - constexpr bool append = mode == AddMode::kAppend; - Position head = ring->Find(offset); - Position tail = ring->FindTail(head.index, offset + len); - const index_type entries = ring->entries(head.index, tail.index); - - rep = Mutable(rep, entries); - - // The delta for making ring[head].end_pos into 'len - offset' - const pos_type delta_length = - (append ? rep->begin_pos_ + rep->length : rep->begin_pos_ - len) - - ring->entry_begin_pos(head.index) - head.offset; - - // Start filling at `tail`, or `entries` before `head` - Filler filler(rep, append ? rep->tail_ : rep->retreat(rep->head_, entries)); - - if (ring->refcount.IsOne()) { - // Copy entries from source stealing the ref and adjusting the end position. - // Commit the filler as this is no-op. - ring->ForEach(head.index, tail.index, [&](index_type ix) { - filler.Add(ring->entry_child(ix), ring->entry_data_offset(ix), - ring->entry_end_pos(ix) + delta_length); - }); - - // Unref entries we did not copy over, and delete source. - if (head.index != ring->head_) UnrefEntries(ring, ring->head_, head.index); - if (tail.index != ring->tail_) UnrefEntries(ring, tail.index, ring->tail_); - CordRepRing::Delete(ring); - } else { - ring->ForEach(head.index, tail.index, [&](index_type ix) { - CordRep* child = ring->entry_child(ix); - filler.Add(child, ring->entry_data_offset(ix), - ring->entry_end_pos(ix) + delta_length); - CordRep::Ref(child); - }); - CordRepRing::Unref(ring); - } - - if (head.offset) { - // Increase offset of first 'source' entry appended or prepended. - // This is always the entry in `filler.head()` - rep->AddDataOffset(filler.head(), head.offset); - } - - if (tail.offset) { - // Reduce length of last 'source' entry appended or prepended. - // This is always the entry tailed by `filler.pos()` - rep->SubLength(rep->retreat(filler.pos()), tail.offset); - } - - // Commit changes - rep->length += len; - if (append) { - rep->tail_ = filler.pos(); - } else { - rep->head_ = filler.head(); - rep->begin_pos_ -= len; - } - - return Validate(rep); -} - -CordRepRing* CordRepRing::AppendSlow(CordRepRing* rep, CordRep* child) { - Consume(child, [&rep](CordRep* child_arg, size_t offset, size_t len) { - if (child_arg->IsRing()) { - rep = AddRing<AddMode::kAppend>(rep, child_arg->ring(), offset, len); - } else { - rep = AppendLeaf(rep, child_arg, offset, len); - } - }); - return rep; -} - -CordRepRing* CordRepRing::AppendLeaf(CordRepRing* rep, CordRep* child, - size_t offset, size_t len) { - rep = Mutable(rep, 1); - index_type back = rep->tail_; - const pos_type begin_pos = rep->begin_pos_ + rep->length; - rep->tail_ = rep->advance(rep->tail_); - rep->length += len; - rep->entry_end_pos()[back] = begin_pos + len; - rep->entry_child()[back] = child; - rep->entry_data_offset()[back] = static_cast<offset_type>(offset); - return Validate(rep, nullptr, __LINE__); -} - -CordRepRing* CordRepRing::Append(CordRepRing* rep, CordRep* child) { - size_t length = child->length; - if (IsFlatOrExternal(child)) { - return AppendLeaf(rep, child, 0, length); - } - if (child->IsRing()) { - return AddRing<AddMode::kAppend>(rep, child->ring(), 0, length); - } - return AppendSlow(rep, child); -} - -CordRepRing* CordRepRing::PrependSlow(CordRepRing* rep, CordRep* child) { - ReverseConsume(child, [&](CordRep* child_arg, size_t offset, size_t len) { - if (IsFlatOrExternal(child_arg)) { - rep = PrependLeaf(rep, child_arg, offset, len); - } else { - rep = AddRing<AddMode::kPrepend>(rep, child_arg->ring(), offset, len); - } - }); - return Validate(rep); -} - -CordRepRing* CordRepRing::PrependLeaf(CordRepRing* rep, CordRep* child, - size_t offset, size_t len) { - rep = Mutable(rep, 1); - index_type head = rep->retreat(rep->head_); - pos_type end_pos = rep->begin_pos_; - rep->head_ = head; - rep->length += len; - rep->begin_pos_ -= len; - rep->entry_end_pos()[head] = end_pos; - rep->entry_child()[head] = child; - rep->entry_data_offset()[head] = static_cast<offset_type>(offset); - return Validate(rep); -} - -CordRepRing* CordRepRing::Prepend(CordRepRing* rep, CordRep* child) { - size_t length = child->length; - if (IsFlatOrExternal(child)) { - return PrependLeaf(rep, child, 0, length); - } - if (child->IsRing()) { - return AddRing<AddMode::kPrepend>(rep, child->ring(), 0, length); - } - return PrependSlow(rep, child); -} - -CordRepRing* CordRepRing::Append(CordRepRing* rep, absl::string_view data, - size_t extra) { - if (rep->refcount.IsOne()) { - Span<char> avail = rep->GetAppendBuffer(data.length()); - if (!avail.empty()) { - memcpy(avail.data(), data.data(), avail.length()); - data.remove_prefix(avail.length()); - } - } - if (data.empty()) return Validate(rep); - - const size_t flats = (data.length() - 1) / kMaxFlatLength + 1; - rep = Mutable(rep, flats); - - Filler filler(rep, rep->tail_); - pos_type pos = rep->begin_pos_ + rep->length; - - while (data.length() >= kMaxFlatLength) { - auto* flat = CreateFlat(data.data(), kMaxFlatLength); - filler.Add(flat, 0, pos += kMaxFlatLength); - data.remove_prefix(kMaxFlatLength); - } - - if (data.length()) { - auto* flat = CreateFlat(data.data(), data.length(), extra); - filler.Add(flat, 0, pos += data.length()); - } - - rep->length = pos - rep->begin_pos_; - rep->tail_ = filler.pos(); - - return Validate(rep); -} - -CordRepRing* CordRepRing::Prepend(CordRepRing* rep, absl::string_view data, - size_t extra) { - if (rep->refcount.IsOne()) { - Span<char> avail = rep->GetPrependBuffer(data.length()); - if (!avail.empty()) { - const char* tail = data.data() + data.length() - avail.length(); - memcpy(avail.data(), tail, avail.length()); - data.remove_suffix(avail.length()); - } - } - if (data.empty()) return rep; - - const size_t flats = (data.length() - 1) / kMaxFlatLength + 1; - rep = Mutable(rep, flats); - pos_type pos = rep->begin_pos_; - Filler filler(rep, rep->retreat(rep->head_, static_cast<index_type>(flats))); - - size_t first_size = data.size() - (flats - 1) * kMaxFlatLength; - CordRepFlat* flat = CordRepFlat::New(first_size + extra); - flat->length = first_size + extra; - memcpy(flat->Data() + extra, data.data(), first_size); - data.remove_prefix(first_size); - filler.Add(flat, extra, pos); - pos -= first_size; - - while (!data.empty()) { - assert(data.size() >= kMaxFlatLength); - flat = CreateFlat(data.data(), kMaxFlatLength); - filler.Add(flat, 0, pos); - pos -= kMaxFlatLength; - data.remove_prefix(kMaxFlatLength); - } - - rep->head_ = filler.head(); - rep->length += rep->begin_pos_ - pos; - rep->begin_pos_ = pos; - - return Validate(rep); -} - -// 32 entries is 32 * sizeof(pos_type) = 4 cache lines on x86 -static constexpr index_type kBinarySearchThreshold = 32; -static constexpr index_type kBinarySearchEndCount = 8; - -template <bool wrap> -CordRepRing::index_type CordRepRing::FindBinary(index_type head, - index_type tail, - size_t offset) const { - index_type count = tail + (wrap ? capacity_ : 0) - head; - do { - count = (count - 1) / 2; - assert(count < entries(head, tail_)); - index_type mid = wrap ? advance(head, count) : head + count; - index_type after_mid = wrap ? advance(mid) : mid + 1; - bool larger = (offset >= entry_end_offset(mid)); - head = larger ? after_mid : head; - tail = larger ? tail : mid; - assert(head != tail); - } while (ABSL_PREDICT_TRUE(count > kBinarySearchEndCount)); - return head; -} - -CordRepRing::Position CordRepRing::FindSlow(index_type head, - size_t offset) const { - index_type tail = tail_; - - // Binary search until we are good for linear search - // Optimize for branchless / non wrapping ops - if (tail > head) { - index_type count = tail - head; - if (count > kBinarySearchThreshold) { - head = FindBinary<false>(head, tail, offset); - } - } else { - index_type count = capacity_ + tail - head; - if (count > kBinarySearchThreshold) { - head = FindBinary<true>(head, tail, offset); - } - } - - pos_type pos = entry_begin_pos(head); - pos_type end_pos = entry_end_pos(head); - while (offset >= Distance(begin_pos_, end_pos)) { - head = advance(head); - pos = end_pos; - end_pos = entry_end_pos(head); - } - - return {head, offset - Distance(begin_pos_, pos)}; -} - -CordRepRing::Position CordRepRing::FindTailSlow(index_type head, - size_t offset) const { - index_type tail = tail_; - const size_t tail_offset = offset - 1; - - // Binary search until we are good for linear search - // Optimize for branchless / non wrapping ops - if (tail > head) { - index_type count = tail - head; - if (count > kBinarySearchThreshold) { - head = FindBinary<false>(head, tail, tail_offset); - } - } else { - index_type count = capacity_ + tail - head; - if (count > kBinarySearchThreshold) { - head = FindBinary<true>(head, tail, tail_offset); - } - } - - size_t end_offset = entry_end_offset(head); - while (tail_offset >= end_offset) { - head = advance(head); - end_offset = entry_end_offset(head); - } - - return {advance(head), end_offset - offset}; -} - -char CordRepRing::GetCharacter(size_t offset) const { - assert(offset < length); - - Position pos = Find(offset); - size_t data_offset = entry_data_offset(pos.index) + pos.offset; - return GetRepData(entry_child(pos.index))[data_offset]; -} - -CordRepRing* CordRepRing::SubRing(CordRepRing* rep, size_t offset, - size_t len, size_t extra) { - assert(offset <= rep->length); - assert(offset <= rep->length - len); - - if (len == 0) { - CordRep::Unref(rep); - return nullptr; - } - - // Find position of first byte - Position head = rep->Find(offset); - Position tail = rep->FindTail(head.index, offset + len); - const size_t new_entries = rep->entries(head.index, tail.index); - - if (rep->refcount.IsOne() && extra <= (rep->capacity() - new_entries)) { - // We adopt a privately owned rep and no extra entries needed. - if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index); - if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_); - rep->head_ = head.index; - rep->tail_ = tail.index; - } else { - // Copy subset to new rep - rep = Copy(rep, head.index, tail.index, extra); - head.index = rep->head_; - tail.index = rep->tail_; - } - - // Adjust begin_pos and length - rep->length = len; - rep->begin_pos_ += offset; - - // Adjust head and tail blocks - if (head.offset) { - rep->AddDataOffset(head.index, head.offset); - } - if (tail.offset) { - rep->SubLength(rep->retreat(tail.index), tail.offset); - } - - return Validate(rep); -} - -CordRepRing* CordRepRing::RemovePrefix(CordRepRing* rep, size_t len, - size_t extra) { - assert(len <= rep->length); - if (len == rep->length) { - CordRep::Unref(rep); - return nullptr; - } - - Position head = rep->Find(len); - if (rep->refcount.IsOne()) { - if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index); - rep->head_ = head.index; - } else { - rep = Copy(rep, head.index, rep->tail_, extra); - head.index = rep->head_; - } - - // Adjust begin_pos and length - rep->length -= len; - rep->begin_pos_ += len; - - // Adjust head block - if (head.offset) { - rep->AddDataOffset(head.index, head.offset); - } - - return Validate(rep); -} - -CordRepRing* CordRepRing::RemoveSuffix(CordRepRing* rep, size_t len, - size_t extra) { - assert(len <= rep->length); - - if (len == rep->length) { - CordRep::Unref(rep); - return nullptr; - } - - Position tail = rep->FindTail(rep->length - len); - if (rep->refcount.IsOne()) { - // We adopt a privately owned rep, scrub. - if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_); - rep->tail_ = tail.index; - } else { - // Copy subset to new rep - rep = Copy(rep, rep->head_, tail.index, extra); - tail.index = rep->tail_; - } - - // Adjust length - rep->length -= len; - - // Adjust tail block - if (tail.offset) { - rep->SubLength(rep->retreat(tail.index), tail.offset); - } - - return Validate(rep); -} - -} // namespace cord_internal -ABSL_NAMESPACE_END -} // namespace absl diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_ring.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_ring.h deleted file mode 100644 index 79a2fdb1c3..0000000000 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_ring.h +++ /dev/null @@ -1,607 +0,0 @@ -// Copyright 2020 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_STRINGS_INTERNAL_CORD_REP_RING_H_ -#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_ - -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <iosfwd> -#include <limits> -#include <memory> - -#include "absl/container/internal/layout.h" -#include "absl/strings/internal/cord_internal.h" -#include "absl/strings/internal/cord_rep_flat.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace cord_internal { - -// All operations modifying a ring buffer are implemented as static methods -// requiring a CordRepRing instance with a reference adopted by the method. -// -// The methods return the modified ring buffer, which may be equal to the input -// if the input was not shared, and having large enough capacity to accommodate -// any newly added node(s). Otherwise, a copy of the input rep with the new -// node(s) added is returned. -// -// Any modification on non shared ring buffers with enough capacity will then -// require minimum atomic operations. Caller should where possible provide -// reasonable `extra` hints for both anticipated extra `flat` byte space, as -// well as anticipated extra nodes required for complex operations. -// -// Example of code creating a ring buffer, adding some data to it, -// and discarding the buffer when done: -// -// void FunWithRings() { -// // Create ring with 3 flats -// CordRep* flat = CreateFlat("Hello"); -// CordRepRing* ring = CordRepRing::Create(flat, 2); -// ring = CordRepRing::Append(ring, CreateFlat(" ")); -// ring = CordRepRing::Append(ring, CreateFlat("world")); -// DoSomethingWithRing(ring); -// CordRep::Unref(ring); -// } -// -// Example of code Copying an existing ring buffer and modifying it: -// -// void MoreFunWithRings(CordRepRing* src) { -// CordRepRing* ring = CordRep::Ref(src)->ring(); -// ring = CordRepRing::Append(ring, CreateFlat("Hello")); -// ring = CordRepRing::Append(ring, CreateFlat(" ")); -// ring = CordRepRing::Append(ring, CreateFlat("world")); -// DoSomethingWithRing(ring); -// CordRep::Unref(ring); -// } -// -class CordRepRing : public CordRep { - public: - // `pos_type` represents a 'logical position'. A CordRepRing instance has a - // `begin_pos` (default 0), and each node inside the buffer will have an - // `end_pos` which is the `end_pos` of the previous node (or `begin_pos`) plus - // this node's length. The purpose is to allow for a binary search on this - // position, while allowing O(1) prepend and append operations. - using pos_type = size_t; - - // `index_type` is the type for the `head`, `tail` and `capacity` indexes. - // Ring buffers are limited to having no more than four billion entries. - using index_type = uint32_t; - - // `offset_type` is the type for the data offset inside a child rep's data. - using offset_type = uint32_t; - - // Position holds the node index and relative offset into the node for - // some physical offset in the contained data as returned by the Find() - // and FindTail() methods. - struct Position { - index_type index; - size_t offset; - }; - - // The maximum # of child nodes that can be hosted inside a CordRepRing. - static constexpr size_t kMaxCapacity = (std::numeric_limits<uint32_t>::max)(); - - // CordRepring can not be default constructed, moved, copied or assigned. - CordRepRing() = delete; - CordRepRing(const CordRepRing&) = delete; - CordRepRing& operator=(const CordRepRing&) = delete; - - // Returns true if this instance is valid, false if some or all of the - // invariants are broken. Intended for debug purposes only. - // `output` receives an explanation of the broken invariants. - bool IsValid(std::ostream& output) const; - - // Returns the size in bytes for a CordRepRing with `capacity' entries. - static constexpr size_t AllocSize(size_t capacity); - - // Returns the distance in bytes from `pos` to `end_pos`. - static constexpr size_t Distance(pos_type pos, pos_type end_pos); - - // Creates a new ring buffer from the provided `rep`. Adopts a reference - // on `rep`. The returned ring buffer has a capacity of at least `extra + 1` - static CordRepRing* Create(CordRep* child, size_t extra = 0); - - // `head`, `tail` and `capacity` indexes defining the ring buffer boundaries. - index_type head() const { return head_; } - index_type tail() const { return tail_; } - index_type capacity() const { return capacity_; } - - // Returns the number of entries in this instance. - index_type entries() const { return entries(head_, tail_); } - - // Returns the logical begin position of this instance. - pos_type begin_pos() const { return begin_pos_; } - - // Returns the number of entries for a given head-tail range. - // Requires `head` and `tail` values to be less than `capacity()`. - index_type entries(index_type head, index_type tail) const { - assert(head < capacity_ && tail < capacity_); - return tail - head + ((tail > head) ? 0 : capacity_); - } - - // Returns the logical end position of entry `index`. - pos_type const& entry_end_pos(index_type index) const { - assert(IsValidIndex(index)); - return Layout::Partial().Pointer<0>(data_)[index]; - } - - // Returns the child pointer of entry `index`. - CordRep* const& entry_child(index_type index) const { - assert(IsValidIndex(index)); - return Layout::Partial(capacity()).Pointer<1>(data_)[index]; - } - - // Returns the data offset of entry `index` - offset_type const& entry_data_offset(index_type index) const { - assert(IsValidIndex(index)); - return Layout::Partial(capacity(), capacity()).Pointer<2>(data_)[index]; - } - - // Appends the provided child node to the `rep` instance. - // Adopts a reference from `rep` and `child` which may not be null. - // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node - // containing a FLAT or EXTERNAL node, then flat or external the node is added - // 'as is', with an offset added for the SUBSTRING case. - // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING or - // CONCAT tree, then all child nodes not excluded by any start offset or - // length values are added recursively. - static CordRepRing* Append(CordRepRing* rep, CordRep* child); - - // Appends the provided string data to the `rep` instance. - // This function will attempt to utilize any remaining capacity in the last - // node of the input if that node is not shared (directly or indirectly), and - // of type FLAT. Remaining data will be added as one or more FLAT nodes. - // Any last node added to the ring buffer will be allocated with up to - // `extra` bytes of capacity for (anticipated) subsequent append actions. - static CordRepRing* Append(CordRepRing* rep, string_view data, - size_t extra = 0); - - // Prepends the provided child node to the `rep` instance. - // Adopts a reference from `rep` and `child` which may not be null. - // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node - // containing a FLAT or EXTERNAL node, then flat or external the node is - // prepended 'as is', with an optional offset added for the SUBSTRING case. - // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING - // or CONCAT tree, then all child nodes not excluded by any start offset or - // length values are added recursively. - static CordRepRing* Prepend(CordRepRing* rep, CordRep* child); - - // Prepends the provided string data to the `rep` instance. - // This function will attempt to utilize any remaining capacity in the first - // node of the input if that node is not shared (directly or indirectly), and - // of type FLAT. Remaining data will be added as one or more FLAT nodes. - // Any first node prepnded to the ring buffer will be allocated with up to - // `extra` bytes of capacity for (anticipated) subsequent prepend actions. - static CordRepRing* Prepend(CordRepRing* rep, string_view data, - size_t extra = 0); - - // Returns a span referencing potentially unused capacity in the last node. - // The returned span may be empty if no such capacity is available, or if the - // current instance is shared. Else, a span of size `n <= size` is returned. - // If non empty, the ring buffer is adjusted to the new length, with the newly - // added capacity left uninitialized. Callers should assign a value to the - // entire span before any other operations on this instance. - Span<char> GetAppendBuffer(size_t size); - - // Returns a span referencing potentially unused capacity in the first node. - // This function is identical to GetAppendBuffer except that it returns a span - // referencing up to `size` capacity directly before the existing data. - Span<char> GetPrependBuffer(size_t size); - - // Returns a cord ring buffer containing `len` bytes of data starting at - // `offset`. If the input is not shared, this function will remove all head - // and tail child nodes outside of the requested range, and adjust the new - // head and tail nodes as required. If the input is shared, this function - // returns a new instance sharing some or all of the nodes from the input. - static CordRepRing* SubRing(CordRepRing* r, size_t offset, size_t len, - size_t extra = 0); - - // Returns a cord ring buffer with the first `len` bytes removed. - // If the input is not shared, this function will remove all head child nodes - // fully inside the first `length` bytes, and adjust the new head as required. - // If the input is shared, this function returns a new instance sharing some - // or all of the nodes from the input. - static CordRepRing* RemoveSuffix(CordRepRing* r, size_t len, - size_t extra = 0); - - // Returns a cord ring buffer with the last `len` bytes removed. - // If the input is not shared, this function will remove all head child nodes - // fully inside the first `length` bytes, and adjust the new head as required. - // If the input is shared, this function returns a new instance sharing some - // or all of the nodes from the input. - static CordRepRing* RemovePrefix(CordRepRing* r, size_t len, - size_t extra = 0); - - // Returns the character at `offset`. Requires that `offset < length`. - char GetCharacter(size_t offset) const; - - // Returns true if this instance manages a single contiguous buffer, in which - // case the (optional) output parameter `fragment` is set. Otherwise, the - // function returns false, and `fragment` is left unchanged. - bool IsFlat(absl::string_view* fragment) const; - - // Returns true if the data starting at `offset` with length `len` is - // managed by this instance inside a single contiguous buffer, in which case - // the (optional) output parameter `fragment` is set to the contiguous memory - // starting at offset `offset` with length `length`. Otherwise, the function - // returns false, and `fragment` is left unchanged. - bool IsFlat(size_t offset, size_t len, absl::string_view* fragment) const; - - // Testing only: set capacity to requested capacity. - void SetCapacityForTesting(size_t capacity); - - // Returns the CordRep data pointer for the provided CordRep. - // Requires that the provided `rep` is either a FLAT or EXTERNAL CordRep. - static const char* GetLeafData(const CordRep* rep); - - // Returns the CordRep data pointer for the provided CordRep. - // Requires that `rep` is either a FLAT, EXTERNAL, or SUBSTRING CordRep. - static const char* GetRepData(const CordRep* rep); - - // Advances the provided position, wrapping around capacity as needed. - // Requires `index` < capacity() - inline index_type advance(index_type index) const; - - // Advances the provided position by 'n`, wrapping around capacity as needed. - // Requires `index` < capacity() and `n` <= capacity. - inline index_type advance(index_type index, index_type n) const; - - // Retreats the provided position, wrapping around 0 as needed. - // Requires `index` < capacity() - inline index_type retreat(index_type index) const; - - // Retreats the provided position by 'n', wrapping around 0 as needed. - // Requires `index` < capacity() - inline index_type retreat(index_type index, index_type n) const; - - // Returns the logical begin position of entry `index` - pos_type const& entry_begin_pos(index_type index) const { - return (index == head_) ? begin_pos_ : entry_end_pos(retreat(index)); - } - - // Returns the physical start offset of entry `index` - size_t entry_start_offset(index_type index) const { - return Distance(begin_pos_, entry_begin_pos(index)); - } - - // Returns the physical end offset of entry `index` - size_t entry_end_offset(index_type index) const { - return Distance(begin_pos_, entry_end_pos(index)); - } - - // Returns the data length for entry `index` - size_t entry_length(index_type index) const { - return Distance(entry_begin_pos(index), entry_end_pos(index)); - } - - // Returns the data for entry `index` - absl::string_view entry_data(index_type index) const; - - // Returns the position for `offset` as {index, prefix}. `index` holds the - // index of the entry at the specified offset and `prefix` holds the relative - // offset inside that entry. - // Requires `offset` < length. - // - // For example we can implement GetCharacter(offset) as: - // char GetCharacter(size_t offset) { - // Position pos = this->Find(offset); - // return this->entry_data(pos.pos)[pos.offset]; - // } - inline Position Find(size_t offset) const; - - // Find starting at `head` - inline Position Find(index_type head, size_t offset) const; - - // Returns the tail position for `offset` as {tail index, suffix}. - // `tail index` holds holds the index of the entry holding the offset directly - // before 'offset` advanced by one. 'suffix` holds the relative offset from - // that relative offset in the entry to the end of the entry. - // For example, FindTail(length) will return {tail(), 0}, FindTail(length - 5) - // will return {retreat(tail), 5)} provided the preceding entry contains at - // least 5 bytes of data. - // Requires offset >= 1 && offset <= length. - // - // This function is very useful in functions that need to clip the end of some - // ring buffer such as 'RemovePrefix'. - // For example, we could implement RemovePrefix for non shared instances as: - // void RemoveSuffix(size_t n) { - // Position pos = FindTail(length - n); - // UnrefEntries(pos.pos, this->tail_); - // this->tail_ = pos.pos; - // entry(retreat(pos.pos)).end_pos -= pos.offset; - // } - inline Position FindTail(size_t offset) const; - - // Find tail starting at `head` - inline Position FindTail(index_type head, size_t offset) const; - - // Invokes f(index_type index) for each entry inside the range [head, tail> - template <typename F> - void ForEach(index_type head, index_type tail, F&& f) const { - index_type n1 = (tail > head) ? tail : capacity_; - for (index_type i = head; i < n1; ++i) f(i); - if (tail <= head) { - for (index_type i = 0; i < tail; ++i) f(i); - } - } - - // Invokes f(index_type index) for each entry inside this instance. - template <typename F> - void ForEach(F&& f) const { - ForEach(head_, tail_, std::forward<F>(f)); - } - - // Dump this instance's data tp stream `s` in human readable format, excluding - // the actual data content itself. Intended for debug purposes only. - friend std::ostream& operator<<(std::ostream& s, const CordRepRing& rep); - - private: - enum class AddMode { kAppend, kPrepend }; - - using Layout = container_internal::Layout<pos_type, CordRep*, offset_type>; - - class Filler; - class Transaction; - class CreateTransaction; - - static constexpr size_t kLayoutAlignment = Layout::Partial().Alignment(); - - // Creates a new CordRepRing. - explicit CordRepRing(index_type capacity) : capacity_(capacity) {} - - // Returns true if `index` is a valid index into this instance. - bool IsValidIndex(index_type index) const; - - // Debug use only: validates the provided CordRepRing invariants. - // Verification of all CordRepRing methods can be enabled by defining - // EXTRA_CORD_RING_VALIDATION, i.e.: `--copts=-DEXTRA_CORD_RING_VALIDATION` - // Verification is VERY expensive, so only do it for debugging purposes. - static CordRepRing* Validate(CordRepRing* rep, const char* file = nullptr, - int line = 0); - - // Allocates a CordRepRing large enough to hold `capacity + extra' entries. - // The returned capacity may be larger if the allocated memory allows for it. - // The maximum capacity of a CordRepRing is capped at kMaxCapacity. - // Throws `std::length_error` if `capacity + extra' exceeds kMaxCapacity. - static CordRepRing* New(size_t capacity, size_t extra); - - // Deallocates (but does not destroy) the provided ring buffer. - static void Delete(CordRepRing* rep); - - // Destroys the provided ring buffer, decrementing the reference count of all - // contained child CordReps. The provided 1\`rep` should have a ref count of - // one (pre decrement destroy call observing `refcount.IsOne()`) or zero - // (post decrement destroy call observing `!refcount.Decrement()`). - static void Destroy(CordRepRing* rep); - - // Returns a mutable reference to the logical end position array. - pos_type* entry_end_pos() { - return Layout::Partial().Pointer<0>(data_); - } - - // Returns a mutable reference to the child pointer array. - CordRep** entry_child() { - return Layout::Partial(capacity()).Pointer<1>(data_); - } - - // Returns a mutable reference to the data offset array. - offset_type* entry_data_offset() { - return Layout::Partial(capacity(), capacity()).Pointer<2>(data_); - } - - // Find implementations for the non fast path 0 / length cases. - Position FindSlow(index_type head, size_t offset) const; - Position FindTailSlow(index_type head, size_t offset) const; - - // Finds the index of the first node that is inside a reasonable distance - // of the node at `offset` from which we can continue with a linear search. - template <bool wrap> - index_type FindBinary(index_type head, index_type tail, size_t offset) const; - - // Fills the current (initialized) instance from the provided source, copying - // entries [head, tail). Adds a reference to copied entries if `ref` is true. - template <bool ref> - void Fill(const CordRepRing* src, index_type head, index_type tail); - - // Create a copy of 'rep', copying all entries [head, tail), allocating room - // for `extra` entries. Adds a reference on all copied entries. - static CordRepRing* Copy(CordRepRing* rep, index_type head, index_type tail, - size_t extra = 0); - - // Returns a Mutable CordRepRing reference from `rep` with room for at least - // `extra` additional nodes. Adopts a reference count from `rep`. - // This function will return `rep` if, and only if: - // - rep.entries + extra <= rep.capacity - // - rep.refcount == 1 - // Otherwise, this function will create a new copy of `rep` with additional - // capacity to satisfy `extra` extra nodes, and unref the old `rep` instance. - // - // If a new CordRepRing can not be allocated, or the new capacity would exceed - // the maximum capacity, then the input is consumed only, and an exception is - // thrown. - static CordRepRing* Mutable(CordRepRing* rep, size_t extra); - - // Slow path for Append(CordRepRing* rep, CordRep* child). This function is - // exercised if the provided `child` in Append() is not a leaf node, i.e., a - // ring buffer or old (concat) cord tree. - static CordRepRing* AppendSlow(CordRepRing* rep, CordRep* child); - - // Appends the provided leaf node. Requires `child` to be FLAT or EXTERNAL. - static CordRepRing* AppendLeaf(CordRepRing* rep, CordRep* child, - size_t offset, size_t length); - - // Prepends the provided leaf node. Requires `child` to be FLAT or EXTERNAL. - static CordRepRing* PrependLeaf(CordRepRing* rep, CordRep* child, - size_t offset, size_t length); - - // Slow path for Prepend(CordRepRing* rep, CordRep* child). This function is - // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a - // ring buffer or old (concat) cord tree. - static CordRepRing* PrependSlow(CordRepRing* rep, CordRep* child); - - // Slow path for Create(CordRep* child, size_t extra). This function is - // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a - // ring buffer or old (concat) cord tree. - static CordRepRing* CreateSlow(CordRep* child, size_t extra); - - // Creates a new ring buffer from the provided `child` leaf node. Requires - // `child` to be FLAT or EXTERNAL. on `rep`. - // The returned ring buffer has a capacity of at least `1 + extra` - static CordRepRing* CreateFromLeaf(CordRep* child, size_t offset, - size_t length, size_t extra); - - // Appends or prepends (depending on AddMode) the ring buffer in `ring' to - // `rep` starting at `offset` with length `len`. - template <AddMode mode> - static CordRepRing* AddRing(CordRepRing* rep, CordRepRing* ring, - size_t offset, size_t len); - - // Increases the data offset for entry `index` by `n`. - void AddDataOffset(index_type index, size_t n); - - // Decreases the length for entry `index` by `n`. - void SubLength(index_type index, size_t n); - - index_type head_; - index_type tail_; - index_type capacity_; - pos_type begin_pos_; - - alignas(kLayoutAlignment) char data_[kLayoutAlignment]; - - friend struct CordRep; -}; - -constexpr size_t CordRepRing::AllocSize(size_t capacity) { - return sizeof(CordRepRing) - sizeof(data_) + - Layout(capacity, capacity, capacity).AllocSize(); -} - -inline constexpr size_t CordRepRing::Distance(pos_type pos, pos_type end_pos) { - return (end_pos - pos); -} - -inline const char* CordRepRing::GetLeafData(const CordRep* rep) { - return rep->tag != EXTERNAL ? rep->flat()->Data() : rep->external()->base; -} - -inline const char* CordRepRing::GetRepData(const CordRep* rep) { - if (rep->tag >= FLAT) return rep->flat()->Data(); - if (rep->tag == EXTERNAL) return rep->external()->base; - return GetLeafData(rep->substring()->child) + rep->substring()->start; -} - -inline CordRepRing::index_type CordRepRing::advance(index_type index) const { - assert(index < capacity_); - return ++index == capacity_ ? 0 : index; -} - -inline CordRepRing::index_type CordRepRing::advance(index_type index, - index_type n) const { - assert(index < capacity_ && n <= capacity_); - return (index += n) >= capacity_ ? index - capacity_ : index; -} - -inline CordRepRing::index_type CordRepRing::retreat(index_type index) const { - assert(index < capacity_); - return (index > 0 ? index : capacity_) - 1; -} - -inline CordRepRing::index_type CordRepRing::retreat(index_type index, - index_type n) const { - assert(index < capacity_ && n <= capacity_); - return index >= n ? index - n : capacity_ - n + index; -} - -inline absl::string_view CordRepRing::entry_data(index_type index) const { - size_t data_offset = entry_data_offset(index); - return {GetRepData(entry_child(index)) + data_offset, entry_length(index)}; -} - -inline bool CordRepRing::IsValidIndex(index_type index) const { - if (index >= capacity_) return false; - return (tail_ > head_) ? (index >= head_ && index < tail_) - : (index >= head_ || index < tail_); -} - -#ifndef EXTRA_CORD_RING_VALIDATION -inline CordRepRing* CordRepRing::Validate(CordRepRing* rep, - const char* /*file*/, int /*line*/) { - return rep; -} -#endif - -inline CordRepRing::Position CordRepRing::Find(size_t offset) const { - assert(offset < length); - return (offset == 0) ? Position{head_, 0} : FindSlow(head_, offset); -} - -inline CordRepRing::Position CordRepRing::Find(index_type head, - size_t offset) const { - assert(offset < length); - assert(IsValidIndex(head) && offset >= entry_start_offset(head)); - return (offset == 0) ? Position{head_, 0} : FindSlow(head, offset); -} - -inline CordRepRing::Position CordRepRing::FindTail(size_t offset) const { - assert(offset > 0 && offset <= length); - return (offset == length) ? Position{tail_, 0} : FindTailSlow(head_, offset); -} - -inline CordRepRing::Position CordRepRing::FindTail(index_type head, - size_t offset) const { - assert(offset > 0 && offset <= length); - assert(IsValidIndex(head) && offset >= entry_start_offset(head) + 1); - return (offset == length) ? Position{tail_, 0} : FindTailSlow(head, offset); -} - -// Now that CordRepRing is defined, we can define CordRep's helper casts: -inline CordRepRing* CordRep::ring() { - assert(IsRing()); - return static_cast<CordRepRing*>(this); -} - -inline const CordRepRing* CordRep::ring() const { - assert(IsRing()); - return static_cast<const CordRepRing*>(this); -} - -inline bool CordRepRing::IsFlat(absl::string_view* fragment) const { - if (entries() == 1) { - if (fragment) *fragment = entry_data(head()); - return true; - } - return false; -} - -inline bool CordRepRing::IsFlat(size_t offset, size_t len, - absl::string_view* fragment) const { - const Position pos = Find(offset); - const absl::string_view data = entry_data(pos.index); - if (data.length() >= len && data.length() - len >= pos.offset) { - if (fragment) *fragment = data.substr(pos.offset, len); - return true; - } - return false; -} - -std::ostream& operator<<(std::ostream& s, const CordRepRing& rep); - -} // namespace cord_internal -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_ diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc index 515dfafbb3..b24c3da712 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc @@ -21,7 +21,6 @@ #include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_rep_btree.h" #include "absl/strings/internal/cord_rep_crc.h" -#include "absl/strings/internal/cord_rep_ring.h" #include "absl/strings/internal/cordz_handle.h" #include "absl/strings/internal/cordz_statistics.h" #include "absl/strings/internal/cordz_update_tracker.h" @@ -33,8 +32,6 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace cord_internal { -using ::absl::base_internal::SpinLockHolder; - #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL constexpr size_t CordzInfo::kMaxStackDepth; #endif @@ -79,6 +76,8 @@ class CordRepAnalyzer { // adds the results to `statistics`. Note that node counts and memory sizes // are not initialized, computed values are added to any existing values. void AnalyzeCordRep(const CordRep* rep) { + ABSL_ASSERT(rep != nullptr); + // Process all linear nodes. // As per the class comments, use refcout - 1 on the top level node, as the // top level node is assumed to be referenced only for analysis purposes. @@ -86,7 +85,7 @@ class CordRepAnalyzer { RepRef repref{rep, (refcount > 1) ? refcount - 1 : 1}; // Process the top level CRC node, if present. - if (repref.rep->tag == CRC) { + if (repref.tag() == CRC) { statistics_.node_count++; statistics_.node_counts.crc++; memory_usage_.Add(sizeof(CordRepCrc), repref.refcount); @@ -96,15 +95,14 @@ class CordRepAnalyzer { // Process all top level linear nodes (substrings and flats). repref = CountLinearReps(repref, memory_usage_); - if (repref.rep != nullptr) { - if (repref.rep->tag == RING) { - AnalyzeRing(repref); - } else if (repref.rep->tag == BTREE) { + switch (repref.tag()) { + case CordRepKind::BTREE: AnalyzeBtree(repref); - } else { - // We should have either a concat, btree, or ring node if not null. - assert(false); - } + break; + default: + // We should have a btree node if not null. + ABSL_ASSERT(repref.tag() == CordRepKind::UNUSED_0); + break; } // Adds values to output @@ -122,11 +120,19 @@ class CordRepAnalyzer { const CordRep* rep; size_t refcount; - // Returns a 'child' RepRef which contains the cumulative reference count of - // this instance multiplied by the child's reference count. + // Returns a 'child' RepRef which contains the cumulative reference count + // of this instance multiplied by the child's reference count. Returns a + // nullptr RepRef value with a refcount of 0 if `child` is nullptr. RepRef Child(const CordRep* child) const { + if (child == nullptr) return RepRef{nullptr, 0}; return RepRef{child, refcount * child->refcount.Get()}; } + + // Returns the tag of this rep, or UNUSED_0 if this instance is null + constexpr CordRepKind tag() const { + ABSL_ASSERT(rep == nullptr || rep->tag != CordRepKind::UNUSED_0); + return rep ? static_cast<CordRepKind>(rep->tag) : CordRepKind::UNUSED_0; + } }; // Memory usage values @@ -167,7 +173,7 @@ class CordRepAnalyzer { // buffers where we count children unrounded. RepRef CountLinearReps(RepRef rep, MemoryUsage& memory_usage) { // Consume all substrings - while (rep.rep->tag == SUBSTRING) { + while (rep.tag() == SUBSTRING) { statistics_.node_count++; statistics_.node_counts.substring++; memory_usage.Add(sizeof(CordRepSubstring), rep.refcount); @@ -175,7 +181,7 @@ class CordRepAnalyzer { } // Consume possible FLAT - if (rep.rep->tag >= FLAT) { + if (rep.tag() >= FLAT) { size_t size = rep.rep->flat()->AllocatedSize(); CountFlat(size); memory_usage.Add(size, rep.refcount); @@ -183,7 +189,7 @@ class CordRepAnalyzer { } // Consume possible external - if (rep.rep->tag == EXTERNAL) { + if (rep.tag() == EXTERNAL) { statistics_.node_count++; statistics_.node_counts.external++; size_t size = rep.rep->length + sizeof(CordRepExternalImpl<intptr_t>); @@ -194,17 +200,6 @@ class CordRepAnalyzer { return rep; } - // Analyzes the provided ring. - void AnalyzeRing(RepRef rep) { - statistics_.node_count++; - statistics_.node_counts.ring++; - const CordRepRing* ring = rep.rep->ring(); - memory_usage_.Add(CordRepRing::AllocSize(ring->capacity()), rep.refcount); - ring->ForEach([&](CordRepRing::index_type pos) { - CountLinearReps(rep.Child(ring->entry_child(pos)), memory_usage_); - }); - } - // Analyzes the provided btree. void AnalyzeBtree(RepRef rep) { statistics_.node_count++; diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc index e2e7347c49..0bbd8aa1bd 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc @@ -27,10 +27,18 @@ int memcasecmp(const char* s1, const char* s2, size_t len) { const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2); for (size_t i = 0; i < len; i++) { - const int diff = - int{static_cast<unsigned char>(absl::ascii_tolower(us1[i]))} - - int{static_cast<unsigned char>(absl::ascii_tolower(us2[i]))}; - if (diff != 0) return diff; + unsigned char c1 = us1[i]; + unsigned char c2 = us2[i]; + // If bytes are the same, they will be the same when converted to lower. + // So we only need to convert if bytes are not equal. + // NOTE(b/308193381): We do not use `absl::ascii_tolower` here in order + // to avoid its lookup table and improve performance. + if (c1 != c2) { + c1 = c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1; + c2 = c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2; + const int diff = int{c1} - int{c2}; + if (diff != 0) return diff; + } } return 0; } diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc index c0a9a28ef9..eeb2108154 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc @@ -18,15 +18,28 @@ // #include "absl/strings/internal/str_format/arg.h" +#include <algorithm> #include <cassert> -#include <cerrno> +#include <cstddef> +#include <cstdint> #include <cstdlib> +#include <cstring> +#include <cwchar> #include <string> #include <type_traits> -#include "absl/base/port.h" +#include "absl/base/config.h" +#include "absl/base/optimization.h" +#include "absl/container/fixed_array.h" +#include "absl/numeric/int128.h" +#include "absl/strings/internal/str_format/extension.h" #include "absl/strings/internal/str_format/float_conversion.h" #include "absl/strings/numbers.h" +#include "absl/strings/string_view.h" + +#if defined(ABSL_HAVE_STD_STRING_VIEW) +#include <string_view> +#endif namespace absl { ABSL_NAMESPACE_BEGIN @@ -298,6 +311,83 @@ inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv, conv.has_left_flag()); } +struct ShiftState { + bool saw_high_surrogate = false; + uint8_t bits = 0; +}; + +// Converts `v` from UTF-16 or UTF-32 to UTF-8 and writes to `buf`. `buf` is +// assumed to have enough space for the output. `s` is used to carry state +// between successive calls with a UTF-16 surrogate pair. Returns the number of +// chars written, or `static_cast<size_t>(-1)` on failure. +// +// This is basically std::wcrtomb(), but always outputting UTF-8 instead of +// respecting the current locale. +inline size_t WideToUtf8(wchar_t wc, char *buf, ShiftState &s) { + const auto v = static_cast<uint32_t>(wc); + if (v < 0x80) { + *buf = static_cast<char>(v); + return 1; + } else if (v < 0x800) { + *buf++ = static_cast<char>(0xc0 | (v >> 6)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + return 2; + } else if (v < 0xd800 || (v - 0xe000) < 0x2000) { + *buf++ = static_cast<char>(0xe0 | (v >> 12)); + *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + return 3; + } else if ((v - 0x10000) < 0x100000) { + *buf++ = static_cast<char>(0xf0 | (v >> 18)); + *buf++ = static_cast<char>(0x80 | ((v >> 12) & 0x3f)); + *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + return 4; + } else if (v < 0xdc00) { + s.saw_high_surrogate = true; + s.bits = static_cast<uint8_t>(v & 0x3); + const uint8_t high_bits = ((v >> 6) & 0xf) + 1; + *buf++ = static_cast<char>(0xf0 | (high_bits >> 2)); + *buf = + static_cast<char>(0x80 | static_cast<uint8_t>((high_bits & 0x3) << 4) | + static_cast<uint8_t>((v >> 2) & 0xf)); + return 2; + } else if (v < 0xe000 && s.saw_high_surrogate) { + *buf++ = static_cast<char>(0x80 | static_cast<uint8_t>(s.bits << 4) | + static_cast<uint8_t>((v >> 6) & 0xf)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + s.saw_high_surrogate = false; + s.bits = 0; + return 2; + } else { + return static_cast<size_t>(-1); + } +} + +inline bool ConvertStringArg(const wchar_t *v, + size_t len, + const FormatConversionSpecImpl conv, + FormatSinkImpl *sink) { + FixedArray<char> mb(len * 4); + ShiftState s; + size_t chars_written = 0; + for (size_t i = 0; i < len; ++i) { + const size_t chars = WideToUtf8(v[i], &mb[chars_written], s); + if (chars == static_cast<size_t>(-1)) { return false; } + chars_written += chars; + } + return ConvertStringArg(string_view(mb.data(), chars_written), conv, sink); +} + +bool ConvertWCharTImpl(wchar_t v, const FormatConversionSpecImpl conv, + FormatSinkImpl *sink) { + char mb[4]; + ShiftState s; + const size_t chars_written = WideToUtf8(v, mb, s); + return chars_written != static_cast<size_t>(-1) && !s.saw_high_surrogate && + ConvertStringArg(string_view(mb, chars_written), conv, sink); +} + } // namespace bool ConvertBoolArg(bool v, FormatSinkImpl *sink) { @@ -316,11 +406,14 @@ bool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl *sink) { // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes // it to complain about a switch/case type mismatch, even though both are - // FormatConverionChar. Likely this is because at this point + // FormatConversionChar. Likely this is because at this point // FormatConversionChar is declared, but not defined. switch (static_cast<uint8_t>(conv.conversion_char())) { case static_cast<uint8_t>(FormatConversionCharInternal::c): - return ConvertCharImpl(static_cast<char>(v), conv, sink); + return (std::is_same<T, wchar_t>::value || + (conv.length_mod() == LengthMod::l)) + ? ConvertWCharTImpl(static_cast<wchar_t>(v), conv, sink) + : ConvertCharImpl(static_cast<char>(v), conv, sink); case static_cast<uint8_t>(FormatConversionCharInternal::o): as_digits.PrintAsOct(static_cast<U>(v)); @@ -372,6 +465,8 @@ template bool ConvertIntArg<signed char>(signed char v, template bool ConvertIntArg<unsigned char>(unsigned char v, FormatConversionSpecImpl conv, FormatSinkImpl *sink); +template bool ConvertIntArg<wchar_t>(wchar_t v, FormatConversionSpecImpl conv, + FormatSinkImpl *sink); template bool ConvertIntArg<short>(short v, // NOLINT FormatConversionSpecImpl conv, FormatSinkImpl *sink); @@ -403,16 +498,29 @@ StringConvertResult FormatConvertImpl(const std::string &v, return {ConvertStringArg(v, conv, sink)}; } +StringConvertResult FormatConvertImpl(const std::wstring &v, + const FormatConversionSpecImpl conv, + FormatSinkImpl *sink) { + return {ConvertStringArg(v.data(), v.size(), conv, sink)}; +} + StringConvertResult FormatConvertImpl(string_view v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertStringArg(v, conv, sink)}; } -ArgConvertResult<FormatConversionCharSetUnion( - FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)> -FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv, - FormatSinkImpl *sink) { +#if defined(ABSL_HAVE_STD_STRING_VIEW) +StringConvertResult FormatConvertImpl(std::wstring_view v, + const FormatConversionSpecImpl conv, + FormatSinkImpl* sink) { + return {ConvertStringArg(v.data(), v.size(), conv, sink)}; +} +#endif + +StringPtrConvertResult FormatConvertImpl(const char* v, + const FormatConversionSpecImpl conv, + FormatSinkImpl* sink) { if (conv.conversion_char() == FormatConversionCharInternal::p) return {FormatConvertImpl(VoidPtr(v), conv, sink).value}; size_t len; @@ -427,6 +535,30 @@ FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv, return {ConvertStringArg(string_view(v, len), conv, sink)}; } +StringPtrConvertResult FormatConvertImpl(const wchar_t* v, + const FormatConversionSpecImpl conv, + FormatSinkImpl* sink) { + if (conv.conversion_char() == FormatConversionCharInternal::p) { + return {FormatConvertImpl(VoidPtr(v), conv, sink).value}; + } + size_t len; + if (v == nullptr) { + len = 0; + } else if (conv.precision() < 0) { + len = std::wcslen(v); + } else { + // If precision is set, we look for the NUL-terminator on the valid range. + len = static_cast<size_t>(std::find(v, v + conv.precision(), L'\0') - v); + } + return {ConvertStringArg(v, len, conv, sink)}; +} + +StringPtrConvertResult FormatConvertImpl(std::nullptr_t, + const FormatConversionSpecImpl conv, + FormatSinkImpl* sink) { + return FormatConvertImpl(static_cast<const char*>(nullptr), conv, sink); +} + // ==================== Raw pointers ==================== ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl( VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { @@ -461,6 +593,11 @@ CharConvertResult FormatConvertImpl(char v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } +CharConvertResult FormatConvertImpl(wchar_t v, + const FormatConversionSpecImpl conv, + FormatSinkImpl* sink) { + return {ConvertIntArg(v, conv, sink)}; +} // ==================== Ints ==================== IntegralConvertResult FormatConvertImpl(signed char v, diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h index 3ce30feb49..309161d591 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h @@ -19,8 +19,9 @@ #include <wchar.h> #include <algorithm> +#include <cstddef> +#include <cstdint> #include <cstdio> -#include <iomanip> #include <limits> #include <memory> #include <sstream> @@ -28,13 +29,18 @@ #include <type_traits> #include <utility> -#include "absl/base/port.h" +#include "absl/base/config.h" +#include "absl/base/optimization.h" #include "absl/meta/type_traits.h" #include "absl/numeric/int128.h" -#include "absl/strings/internal/has_absl_stringify.h" +#include "absl/strings/has_absl_stringify.h" #include "absl/strings/internal/str_format/extension.h" #include "absl/strings/string_view.h" +#if defined(ABSL_HAVE_STD_STRING_VIEW) +#include <string_view> +#endif + namespace absl { ABSL_NAMESPACE_BEGIN @@ -97,6 +103,9 @@ extern template bool ConvertIntArg<signed char>(signed char v, extern template bool ConvertIntArg<unsigned char>(unsigned char v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); +extern template bool ConvertIntArg<wchar_t>(wchar_t v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); extern template bool ConvertIntArg<short>(short v, // NOLINT FormatConversionSpecImpl conv, FormatSinkImpl* sink); @@ -158,6 +167,7 @@ template <typename T> auto FormatConvertImpl(const T& v, FormatConversionSpecImpl, FormatSinkImpl* sink) -> std::enable_if_t<!std::is_enum<T>::value && + !std::is_same<T, absl::Cord>::value && std::is_void<decltype(AbslStringify( std::declval<FormatSink&>(), v))>::value, ArgConvertResult<FormatConversionCharSetInternal::v>> { @@ -202,30 +212,49 @@ constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) { return C; } -using StringConvertResult = ArgConvertResult<FormatConversionCharSetUnion( - FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::v)>; ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl( VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); // Strings. +using StringConvertResult = ArgConvertResult<FormatConversionCharSetUnion( + FormatConversionCharSetInternal::s, + FormatConversionCharSetInternal::v)>; StringConvertResult FormatConvertImpl(const std::string& v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); +StringConvertResult FormatConvertImpl(const std::wstring& v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); StringConvertResult FormatConvertImpl(string_view v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -#if defined(ABSL_HAVE_STD_STRING_VIEW) && !defined(ABSL_USES_STD_STRING_VIEW) +#if defined(ABSL_HAVE_STD_STRING_VIEW) +StringConvertResult FormatConvertImpl(std::wstring_view v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); +#if !defined(ABSL_USES_STD_STRING_VIEW) inline StringConvertResult FormatConvertImpl(std::string_view v, FormatConversionSpecImpl conv, FormatSinkImpl* sink) { return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink); } -#endif // ABSL_HAVE_STD_STRING_VIEW && !ABSL_USES_STD_STRING_VIEW - -ArgConvertResult<FormatConversionCharSetUnion( - FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)> -FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv, - FormatSinkImpl* sink); +#endif // !ABSL_USES_STD_STRING_VIEW +#endif // ABSL_HAVE_STD_STRING_VIEW + +using StringPtrConvertResult = ArgConvertResult<FormatConversionCharSetUnion( + FormatConversionCharSetInternal::s, + FormatConversionCharSetInternal::p)>; +StringPtrConvertResult FormatConvertImpl(const char* v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); +StringPtrConvertResult FormatConvertImpl(const wchar_t* v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); +// This overload is needed to disambiguate, since `nullptr` could match either +// of the other overloads equally well. +StringPtrConvertResult FormatConvertImpl(std::nullptr_t, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); template <class AbslCord, typename std::enable_if<std::is_same< AbslCord, absl::Cord>::value>::type* = nullptr> @@ -279,6 +308,9 @@ FloatingConvertResult FormatConvertImpl(long double v, // Chars. CharConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); +CharConvertResult FormatConvertImpl(wchar_t v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); // Ints. IntegralConvertResult FormatConvertImpl(signed char v, @@ -333,7 +365,7 @@ IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv, template <typename T> typename std::enable_if<std::is_enum<T>::value && !HasUserDefinedConvert<T>::value && - !strings_internal::HasAbslStringify<T>::value, + !HasAbslStringify<T>::value, IntegralConvertResult>::type FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); @@ -440,6 +472,7 @@ class FormatArgImpl { // Anything with a user-defined Convert will get its own vtable. // For everything else: // - Decay char* and char arrays into `const char*` + // - Decay wchar_t* and wchar_t arrays into `const wchar_t*` // - Decay any other pointer to `const void*` // - Decay all enums to the integral promotion of their underlying type. // - Decay function pointers to void*. @@ -447,20 +480,23 @@ class FormatArgImpl { struct DecayType { static constexpr bool kHasUserDefined = str_format_internal::HasUserDefinedConvert<T>::value || - strings_internal::HasAbslStringify<T>::value; + HasAbslStringify<T>::value; using type = typename std::conditional< !kHasUserDefined && std::is_convertible<T, const char*>::value, const char*, - typename std::conditional<!kHasUserDefined && - std::is_convertible<T, VoidPtr>::value, - VoidPtr, const T&>::type>::type; + typename std::conditional< + !kHasUserDefined && std::is_convertible<T, const wchar_t*>::value, + const wchar_t*, + typename std::conditional< + !kHasUserDefined && std::is_convertible<T, VoidPtr>::value, + VoidPtr, + const T&>::type>::type>::type; }; template <typename T> - struct DecayType<T, - typename std::enable_if< - !str_format_internal::HasUserDefinedConvert<T>::value && - !strings_internal::HasAbslStringify<T>::value && - std::is_enum<T>::value>::type> { + struct DecayType< + T, typename std::enable_if< + !str_format_internal::HasUserDefinedConvert<T>::value && + !HasAbslStringify<T>::value && std::is_enum<T>::value>::type> { using type = decltype(+typename std::underlying_type<T>::type()); }; @@ -585,7 +621,7 @@ class FormatArgImpl { E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \ void*) -#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ +#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(...) \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \ __VA_ARGS__); \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \ @@ -611,7 +647,19 @@ class FormatArgImpl { ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \ - ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__) + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const wchar_t*, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring, __VA_ARGS__) + +#if defined(ABSL_HAVE_STD_STRING_VIEW) +#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ + ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_( \ + __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring_view, __VA_ARGS__) +#else +#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ + ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(__VA_ARGS__) +#endif ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern); diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc index 77a4222337..87e23b565c 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc @@ -14,10 +14,24 @@ #include "absl/strings/internal/str_format/bind.h" +#include <algorithm> +#include <cassert> #include <cerrno> +#include <cstddef> +#include <cstdio> +#include <ios> #include <limits> +#include <ostream> #include <sstream> #include <string> +#include "absl/base/config.h" +#include "absl/base/optimization.h" +#include "absl/strings/internal/str_format/arg.h" +#include "absl/strings/internal/str_format/constexpr_parser.h" +#include "absl/strings/internal/str_format/extension.h" +#include "absl/strings/internal/str_format/output.h" +#include "absl/strings/string_view.h" +#include "absl/types/span.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -90,6 +104,8 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound, } else { FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound); } + + FormatConversionSpecImplFriend::SetLengthMod(unbound->length_mod, bound); } else { FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound); FormatConversionSpecImplFriend::SetWidth(-1, bound); @@ -215,7 +231,7 @@ std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format, return *out; } -std::string FormatPack(const UntypedFormatSpecImpl format, +std::string FormatPack(UntypedFormatSpecImpl format, absl::Span<const FormatArgImpl> args) { std::string out; if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) { diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h index 5e2a43d5c9..120bc355c7 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h @@ -15,16 +15,19 @@ #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_ -#include <array> +#include <cassert> #include <cstdio> -#include <sstream> +#include <ostream> #include <string> -#include "absl/base/port.h" +#include "absl/base/config.h" #include "absl/container/inlined_vector.h" #include "absl/strings/internal/str_format/arg.h" #include "absl/strings/internal/str_format/checker.h" +#include "absl/strings/internal/str_format/constexpr_parser.h" +#include "absl/strings/internal/str_format/extension.h" #include "absl/strings/internal/str_format/parser.h" +#include "absl/strings/string_view.h" #include "absl/types/span.h" #include "absl/utility/utility.h" @@ -203,7 +206,7 @@ bool FormatUntyped(FormatRawSinkImpl raw_sink, UntypedFormatSpecImpl format, std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format, absl::Span<const FormatArgImpl> args); -std::string FormatPack(const UntypedFormatSpecImpl format, +std::string FormatPack(UntypedFormatSpecImpl format, absl::Span<const FormatArgImpl> args); int FprintF(std::FILE* output, UntypedFormatSpecImpl format, diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h index b70a16e40c..8f59387047 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h @@ -17,17 +17,18 @@ #include <cassert> #include <cstdint> +#include <cstdio> #include <limits> +#include "absl/base/config.h" #include "absl/base/const_init.h" +#include "absl/base/optimization.h" #include "absl/strings/internal/str_format/extension.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace str_format_internal { -enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none }; - // The analyzed properties of a single specified conversion. struct UnboundConversion { // This is a user defined default constructor on purpose to skip the @@ -306,7 +307,6 @@ constexpr const char* ConsumeConversion(const char* pos, const char* const end, if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr; // It is a length modifier. - using str_format_internal::LengthMod; LengthMod length_mod = tag.as_length(); ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR(); if (c == 'h' && length_mod == LengthMod::h) { @@ -322,6 +322,11 @@ constexpr const char* ConsumeConversion(const char* pos, const char* const end, if (ABSL_PREDICT_FALSE(c == 'v')) return nullptr; if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr; + + // `wchar_t` args are marked non-basic so `Bind()` will copy the length mod. + if (conv->length_mod == LengthMod::l && c == 'c') { + conv->flags = conv->flags | Flags::kNonBasic; + } } #undef ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h index 8de42d2cfc..173284c6c7 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h @@ -16,16 +16,14 @@ #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ -#include <limits.h> #include <cstddef> #include <cstdint> #include <cstring> #include <ostream> +#include <string> #include "absl/base/config.h" -#include "absl/base/port.h" -#include "absl/meta/type_traits.h" #include "absl/strings/internal/str_format/output.h" #include "absl/strings/string_view.h" @@ -34,6 +32,7 @@ ABSL_NAMESPACE_BEGIN enum class FormatConversionChar : uint8_t; enum class FormatConversionCharSet : uint64_t; +enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none }; namespace str_format_internal { @@ -139,7 +138,8 @@ enum class Flags : uint8_t { kAlt = 1 << 3, kZero = 1 << 4, // This is not a real flag. It just exists to turn off kBasic when no other - // flags are set. This is for when width/precision are specified. + // flags are set. This is for when width/precision are specified, or a length + // modifier affects the behavior ("%lc"). kNonBasic = 1 << 5, }; @@ -285,6 +285,8 @@ class FormatConversionSpecImpl { bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); } bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); } + LengthMod length_mod() const { return length_mod_; } + FormatConversionChar conversion_char() const { // Keep this field first in the struct . It generates better code when // accessing it when ConversionSpec is passed by value in registers. @@ -310,6 +312,7 @@ class FormatConversionSpecImpl { friend struct str_format_internal::FormatConversionSpecImplFriend; FormatConversionChar conv_ = FormatConversionCharInternal::kNone; Flags flags_; + LengthMod length_mod_ = LengthMod::none; int width_; int precision_; }; @@ -318,6 +321,9 @@ struct FormatConversionSpecImplFriend final { static void SetFlags(Flags f, FormatConversionSpecImpl* conv) { conv->flags_ = f; } + static void SetLengthMod(LengthMod l, FormatConversionSpecImpl* conv) { + conv->length_mod_ = l; + } static void SetConversionChar(FormatConversionChar c, FormatConversionSpecImpl* conv) { conv->conv_ = c; diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h index 35b6d49c14..b1d6d5fd0e 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h +++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h @@ -15,22 +15,23 @@ #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_ -#include <limits.h> #include <stddef.h> #include <stdlib.h> #include <cassert> -#include <cstdint> +#include <cstring> #include <initializer_list> -#include <iosfwd> -#include <iterator> #include <memory> #include <string> +#include <utility> #include <vector> +#include "absl/base/config.h" +#include "absl/base/optimization.h" #include "absl/strings/internal/str_format/checker.h" #include "absl/strings/internal/str_format/constexpr_parser.h" #include "absl/strings/internal/str_format/extension.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/strings/match.cc b/contrib/restricted/abseil-cpp/absl/strings/match.cc index 3b81b2c052..72ae6a430a 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/match.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/match.cc @@ -17,10 +17,13 @@ #include <algorithm> #include <cstdint> +#include "absl/base/config.h" #include "absl/base/internal/endian.h" +#include "absl/base/optimization.h" #include "absl/numeric/bits.h" #include "absl/strings/ascii.h" #include "absl/strings/internal/memutil.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc index c43c6bcc19..882c3a8b85 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc @@ -20,32 +20,36 @@ #include <algorithm> #include <cassert> #include <cfloat> // for DBL_DIG and FLT_DIG +#include <climits> #include <cmath> // for HUGE_VAL +#include <cstddef> #include <cstdint> #include <cstdio> #include <cstdlib> #include <cstring> #include <iterator> #include <limits> -#include <memory> +#include <system_error> // NOLINT(build/c++11) +#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/raw_logging.h" +#include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/numeric/bits.h" +#include "absl/numeric/int128.h" #include "absl/strings/ascii.h" #include "absl/strings/charconv.h" -#include "absl/strings/escaping.h" -#include "absl/strings/internal/memutil.h" #include "absl/strings/match.h" -#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN -bool SimpleAtof(absl::string_view str, float* out) { +bool SimpleAtof(absl::string_view str, absl::Nonnull<float*> out) { *out = 0.0; str = StripAsciiWhitespace(str); // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one @@ -76,7 +80,7 @@ bool SimpleAtof(absl::string_view str, float* out) { return true; } -bool SimpleAtod(absl::string_view str, double* out) { +bool SimpleAtod(absl::string_view str, absl::Nonnull<double*> out) { *out = 0.0; str = StripAsciiWhitespace(str); // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one @@ -107,7 +111,7 @@ bool SimpleAtod(absl::string_view str, double* out) { return true; } -bool SimpleAtob(absl::string_view str, bool* out) { +bool SimpleAtob(absl::string_view str, absl::Nonnull<bool*> out) { ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr."); if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") || EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") || @@ -155,29 +159,71 @@ constexpr uint32_t kTwoZeroBytes = 0x0101 * '0'; constexpr uint64_t kFourZeroBytes = 0x01010101 * '0'; constexpr uint64_t kEightZeroBytes = 0x0101010101010101ull * '0'; -// * 103 / 1024 is a division by 10 for values from 0 to 99. It's also a -// division of a structure [k takes 2 bytes][m takes 2 bytes], then * 103 / 1024 -// will be [k / 10][m / 10]. It allows parallel division. -constexpr uint64_t kDivisionBy10Mul = 103u; +template <typename T> +constexpr T Pow(T base, uint32_t n) { + // Exponentiation by squaring + return static_cast<T>((n > 1 ? Pow(base * base, n >> 1) : static_cast<T>(1)) * + ((n & 1) ? base : static_cast<T>(1))); +} + +// Given n, calculates C where the following holds for all 0 <= x < Pow(100, n): +// x / Pow(10, n) == x * C / Pow(2, n * 10) +// In other words, it allows us to divide by a power of 10 via a single +// multiplication and bit shifts, assuming the input will be smaller than the +// square of that power of 10. +template <typename T> +constexpr T ComputePowerOf100DivisionCoefficient(uint32_t n) { + if (n > 4) { + // This doesn't work for large powers of 100, due to overflow + abort(); + } + T denom = 16 - 1; + T num = (denom + 1) - 10; + T gcd = 3; // Greatest common divisor of numerator and denominator + denom = Pow(denom / gcd, n); + num = Pow(num / gcd, 9 * n); + T quotient = num / denom; + if (num % denom >= denom / 2) { + // Round up, since the remainder is more than half the denominator + ++quotient; + } + return quotient; +} + +// * kDivisionBy10Mul / kDivisionBy10Div is a division by 10 for values from 0 +// to 99. It's also a division of a structure [k takes 2 bytes][m takes 2 +// bytes], then * kDivisionBy10Mul / kDivisionBy10Div will be [k / 10][m / 10]. +// It allows parallel division. +constexpr uint64_t kDivisionBy10Mul = + ComputePowerOf100DivisionCoefficient<uint64_t>(1); +static_assert(kDivisionBy10Mul == 103, + "division coefficient for 10 is incorrect"); constexpr uint64_t kDivisionBy10Div = 1 << 10; -// * 10486 / 1048576 is a division by 100 for values from 0 to 9999. -constexpr uint64_t kDivisionBy100Mul = 10486u; +// * kDivisionBy100Mul / kDivisionBy100Div is a division by 100 for values from +// 0 to 9999. +constexpr uint64_t kDivisionBy100Mul = + ComputePowerOf100DivisionCoefficient<uint64_t>(2); +static_assert(kDivisionBy100Mul == 10486, + "division coefficient for 100 is incorrect"); constexpr uint64_t kDivisionBy100Div = 1 << 20; -// Encode functions write the ASCII output of input `n` to `out_str`. -inline char* EncodeHundred(uint32_t n, char* out_str) { - int num_digits = static_cast<int>(n - 10) >> 8; - uint32_t base = kTwoZeroBytes; - uint32_t div10 = (n * kDivisionBy10Mul) / kDivisionBy10Div; - uint32_t mod10 = n - 10u * div10; - base += div10 + (mod10 << 8); - base >>= num_digits & 8; - little_endian::Store16(out_str, static_cast<uint16_t>(base)); - return out_str + 2 + num_digits; +static_assert(ComputePowerOf100DivisionCoefficient<uint64_t>(3) == 1073742, + "division coefficient for 1000 is incorrect"); + +// Same as `PrepareEightDigits`, but produces 2 digits for integers < 100. +inline uint32_t PrepareTwoDigitsImpl(uint32_t i, bool reversed) { + assert(i < 100); + uint32_t div10 = (i * kDivisionBy10Mul) / kDivisionBy10Div; + uint32_t mod10 = i - 10u * div10; + return (div10 << (reversed ? 8 : 0)) + (mod10 << (reversed ? 0 : 8)); +} +inline uint32_t PrepareTwoDigits(uint32_t i) { + return PrepareTwoDigitsImpl(i, false); } -inline char* EncodeTenThousand(uint32_t n, char* out_str) { +// Same as `PrepareEightDigits`, but produces 4 digits for integers < 10000. +inline uint32_t PrepareFourDigitsImpl(uint32_t n, bool reversed) { // We split lower 2 digits and upper 2 digits of n into 2 byte consecutive // blocks. 123 -> [\0\1][\0\23]. We divide by 10 both blocks // (it's 1 division + zeroing upper bits), and compute modulo 10 as well "in @@ -185,146 +231,335 @@ inline char* EncodeTenThousand(uint32_t n, char* out_str) { // strip trailing zeros, add ASCII '0000' and return. uint32_t div100 = (n * kDivisionBy100Mul) / kDivisionBy100Div; uint32_t mod100 = n - 100ull * div100; - uint32_t hundreds = (mod100 << 16) + div100; + uint32_t hundreds = + (mod100 << (reversed ? 0 : 16)) + (div100 << (reversed ? 16 : 0)); uint32_t tens = (hundreds * kDivisionBy10Mul) / kDivisionBy10Div; tens &= (0xFull << 16) | 0xFull; - tens += (hundreds - 10ull * tens) << 8; - ABSL_ASSUME(tens != 0); - // The result can contain trailing zero bits, we need to strip them to a first - // significant byte in a final representation. For example, for n = 123, we - // have tens to have representation \0\1\2\3. We do `& -8` to round - // to a multiple to 8 to strip zero bytes, not all zero bits. - // countr_zero to help. - // 0 minus 8 to make MSVC happy. - uint32_t zeroes = static_cast<uint32_t>(absl::countr_zero(tens)) & (0 - 8ull); - tens += kFourZeroBytes; - tens >>= zeroes; - little_endian::Store32(out_str, tens); - return out_str + sizeof(tens) - zeroes / 8; + tens = (tens << (reversed ? 8 : 0)) + + static_cast<uint32_t>((hundreds - 10ull * tens) << (reversed ? 0 : 8)); + return tens; +} +inline uint32_t PrepareFourDigits(uint32_t n) { + return PrepareFourDigitsImpl(n, false); +} +inline uint32_t PrepareFourDigitsReversed(uint32_t n) { + return PrepareFourDigitsImpl(n, true); } -// Prepare functions return an integer that should be written to out_str -// (but possibly include trailing zeros). -// For hi < 10000, lo < 10000 returns uint64_t as encoded in ASCII with -// possibly trailing zeroes of the number hi * 10000 + lo. -inline uint64_t PrepareTenThousands(uint64_t hi, uint64_t lo) { - uint64_t merged = hi | (lo << 32); +// Helper function to produce an ASCII representation of `i`. +// +// Function returns an 8-byte integer which when summed with `kEightZeroBytes`, +// can be treated as a printable buffer with ascii representation of `i`, +// possibly with leading zeros. +// +// Example: +// +// uint64_t buffer = PrepareEightDigits(102030) + kEightZeroBytes; +// char* ascii = reinterpret_cast<char*>(&buffer); +// // Note two leading zeros: +// EXPECT_EQ(absl::string_view(ascii, 8), "00102030"); +// +// If `Reversed` is set to true, the result becomes reversed to "03020100". +// +// Pre-condition: `i` must be less than 100000000. +inline uint64_t PrepareEightDigitsImpl(uint32_t i, bool reversed) { + ABSL_ASSUME(i < 10000'0000); + // Prepare 2 blocks of 4 digits "in parallel". + uint32_t hi = i / 10000; + uint32_t lo = i % 10000; + uint64_t merged = (uint64_t{hi} << (reversed ? 32 : 0)) | + (uint64_t{lo} << (reversed ? 0 : 32)); uint64_t div100 = ((merged * kDivisionBy100Mul) / kDivisionBy100Div) & ((0x7Full << 32) | 0x7Full); uint64_t mod100 = merged - 100ull * div100; - uint64_t hundreds = (mod100 << 16) + div100; + uint64_t hundreds = + (mod100 << (reversed ? 0 : 16)) + (div100 << (reversed ? 16 : 0)); uint64_t tens = (hundreds * kDivisionBy10Mul) / kDivisionBy10Div; tens &= (0xFull << 48) | (0xFull << 32) | (0xFull << 16) | 0xFull; - tens += (hundreds - 10ull * tens) << 8; + tens = (tens << (reversed ? 8 : 0)) + + ((hundreds - 10ull * tens) << (reversed ? 0 : 8)); return tens; } +inline uint64_t PrepareEightDigits(uint32_t i) { + return PrepareEightDigitsImpl(i, false); +} +inline uint64_t PrepareEightDigitsReversed(uint32_t i) { + return PrepareEightDigitsImpl(i, true); +} + +template <typename T, typename BackwardIt> +class FastUIntToStringConverter { + static_assert( + std::is_same<T, decltype(+std::declval<T>())>::value, + "to avoid code bloat, only instantiate this for int and larger types"); + static_assert(std::is_unsigned<T>::value, + "this class is only for unsigned types"); + + public: + // Outputs the given number backward (like with std::copy_backward), + // starting from the end of the string. + // The number of digits in the number must have been already measured and + // passed *exactly*, otherwise the behavior is undefined. + // (This is an optimization, as calculating the number of digits again would + // slow down the hot path.) + // Returns an iterator to the start of the suffix that was appended. + static BackwardIt FastIntToBufferBackward(T v, BackwardIt end) { + // THIS IS A HOT FUNCTION with a very deliberate structure to exploit branch + // prediction and shorten the critical path for smaller numbers. + // Do not move around the if/else blocks or attempt to simplify it + // without benchmarking any changes. + + if (v < 10) { + goto AT_LEAST_1 /* NOTE: mandatory for the 0 case */; + } + if (v < 1000) { + goto AT_LEAST_10; + } + if (v < 10000000) { + goto AT_LEAST_1000; + } + + if (v >= 100000000 / 10) { + if (v >= 10000000000000000 / 10) { + DoFastIntToBufferBackward<8>(v, end); + } + DoFastIntToBufferBackward<8>(v, end); + } + + if (v >= 10000 / 10) { + AT_LEAST_1000: + DoFastIntToBufferBackward<4>(v, end); + } + + if (v >= 100 / 10) { + AT_LEAST_10: + DoFastIntToBufferBackward<2>(v, end); + } -inline char* EncodeFullU32(uint32_t n, char* out_str) { - if (n < 100'000'000) { - uint64_t bottom = PrepareTenThousands(n / 10000, n % 10000); - ABSL_ASSUME(bottom != 0); - // 0 minus 8 to make MSVC happy. - uint32_t zeroes = static_cast<uint32_t>(absl::countr_zero(bottom)) - & (0 - 8ull); - uint64_t bottom_res = bottom + kEightZeroBytes; - bottom_res >>= zeroes; - little_endian::Store64(out_str, bottom_res); - return out_str + sizeof(bottom) - zeroes / 8; + if (v >= 10 / 10) { + AT_LEAST_1: + end = DoFastIntToBufferBackward(v, end, std::integral_constant<int, 1>()); + } + return end; } - uint32_t top = n / 100'000'000; - n %= 100'000'000; - uint64_t bottom = PrepareTenThousands(n / 10000, n % 10000); - uint64_t bottom_res = bottom + kEightZeroBytes; - out_str = EncodeHundred(top, out_str); - little_endian::Store64(out_str, bottom_res); - return out_str + sizeof(bottom); -} -} // namespace + private: + // Only assume pointers are contiguous for now. String and vector iterators + // could be special-cased as well, but there's no need for them here. + // With C++20 we can probably switch to std::contiguous_iterator_tag. + static constexpr bool kIsContiguousIterator = + std::is_pointer<BackwardIt>::value; + + template <int Exponent> + static void DoFastIntToBufferBackward(T& v, BackwardIt& end) { + constexpr T kModulus = Pow<T>(10, Exponent); + T remainder = static_cast<T>(v % kModulus); + v = static_cast<T>(v / kModulus); + end = DoFastIntToBufferBackward(remainder, end, + std::integral_constant<int, Exponent>()); + } -void numbers_internal::PutTwoDigits(uint32_t i, char* buf) { - assert(i < 100); - uint32_t base = kTwoZeroBytes; - uint32_t div10 = (i * kDivisionBy10Mul) / kDivisionBy10Div; - uint32_t mod10 = i - 10u * div10; - base += div10 + (mod10 << 8); - little_endian::Store16(buf, static_cast<uint16_t>(base)); -} + static BackwardIt DoFastIntToBufferBackward(const T&, BackwardIt end, + std::integral_constant<int, 0>) { + return end; + } -char* numbers_internal::FastIntToBuffer(uint32_t n, char* out_str) { - if (n < 100) { - out_str = EncodeHundred(n, out_str); - goto set_last_zero; + static BackwardIt DoFastIntToBufferBackward(T v, BackwardIt end, + std::integral_constant<int, 1>) { + *--end = static_cast<char>('0' + v); + return DoFastIntToBufferBackward(v, end, std::integral_constant<int, 0>()); } - if (n < 10000) { - out_str = EncodeTenThousand(n, out_str); - goto set_last_zero; + + static BackwardIt DoFastIntToBufferBackward(T v, BackwardIt end, + std::integral_constant<int, 4>) { + if (kIsContiguousIterator) { + const uint32_t digits = + PrepareFourDigits(static_cast<uint32_t>(v)) + kFourZeroBytes; + end -= sizeof(digits); + little_endian::Store32(&*end, digits); + } else { + uint32_t digits = + PrepareFourDigitsReversed(static_cast<uint32_t>(v)) + kFourZeroBytes; + for (size_t i = 0; i < sizeof(digits); ++i) { + *--end = static_cast<char>(digits); + digits >>= CHAR_BIT; + } + } + return end; } - out_str = EncodeFullU32(n, out_str); -set_last_zero: - *out_str = '\0'; - return out_str; -} -char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) { - uint32_t u = static_cast<uint32_t>(i); - if (i < 0) { - *buffer++ = '-'; - // We need to do the negation in modular (i.e., "unsigned") - // arithmetic; MSVC++ apparently warns for plain "-u", so - // we write the equivalent expression "0 - u" instead. - u = 0 - u; + static BackwardIt DoFastIntToBufferBackward(T v, BackwardIt end, + std::integral_constant<int, 8>) { + if (kIsContiguousIterator) { + const uint64_t digits = + PrepareEightDigits(static_cast<uint32_t>(v)) + kEightZeroBytes; + end -= sizeof(digits); + little_endian::Store64(&*end, digits); + } else { + uint64_t digits = PrepareEightDigitsReversed(static_cast<uint32_t>(v)) + + kEightZeroBytes; + for (size_t i = 0; i < sizeof(digits); ++i) { + *--end = static_cast<char>(digits); + digits >>= CHAR_BIT; + } + } + return end; } - return numbers_internal::FastIntToBuffer(u, buffer); -} -char* numbers_internal::FastIntToBuffer(uint64_t i, char* buffer) { - uint32_t u32 = static_cast<uint32_t>(i); - if (u32 == i) return numbers_internal::FastIntToBuffer(u32, buffer); - - // 10**9 < 2**32 <= i < 10**10, we can do 2+8 - uint64_t div08 = i / 100'000'000ull; - uint64_t mod08 = i % 100'000'000ull; - uint64_t mod_result = - PrepareTenThousands(mod08 / 10000, mod08 % 10000) + kEightZeroBytes; - if (i < 10'000'000'000ull) { - buffer = EncodeHundred(static_cast<uint32_t>(div08), buffer); - little_endian::Store64(buffer, mod_result); - buffer += 8; - goto set_last_zero; + template <int Digits> + static BackwardIt DoFastIntToBufferBackward( + T v, BackwardIt end, std::integral_constant<int, Digits>) { + constexpr int kLogModulus = Digits - Digits / 2; + constexpr T kModulus = Pow(static_cast<T>(10), kLogModulus); + bool is_safe_to_use_division_trick = Digits <= 8; + T quotient, remainder; + if (is_safe_to_use_division_trick) { + constexpr uint64_t kCoefficient = + ComputePowerOf100DivisionCoefficient<uint64_t>(kLogModulus); + quotient = (v * kCoefficient) >> (10 * kLogModulus); + remainder = v - quotient * kModulus; + } else { + quotient = v / kModulus; + remainder = v % kModulus; + } + end = DoFastIntToBufferBackward(remainder, end, + std::integral_constant<int, kLogModulus>()); + return DoFastIntToBufferBackward( + quotient, end, std::integral_constant<int, Digits - kLogModulus>()); } +}; - // i < 10**16, in this case 8+8 - if (i < 10'000'000'000'000'000ull) { - buffer = EncodeFullU32(static_cast<uint32_t>(div08), buffer); - little_endian::Store64(buffer, mod_result); - buffer += 8; - goto set_last_zero; - } else { - // 4 + 8 + 8 - uint64_t div016 = i / 10'000'000'000'000'000ull; - buffer = EncodeTenThousand(static_cast<uint32_t>(div016), buffer); - uint64_t mid_result = div08 - div016 * 100'000'000ull; - mid_result = PrepareTenThousands(mid_result / 10000, mid_result % 10000) + - kEightZeroBytes; - little_endian::Store64(buffer, mid_result); - buffer += 8; - little_endian::Store64(buffer, mod_result); - buffer += 8; - goto set_last_zero; +// Returns an iterator to the start of the suffix that was appended +template <typename T, typename BackwardIt> +std::enable_if_t<std::is_unsigned<T>::value, BackwardIt> +DoFastIntToBufferBackward(T v, BackwardIt end, uint32_t digits) { + using PromotedT = std::decay_t<decltype(+v)>; + using Converter = FastUIntToStringConverter<PromotedT, BackwardIt>; + (void)digits; + return Converter().FastIntToBufferBackward(v, end); +} + +template <typename T, typename BackwardIt> +std::enable_if_t<std::is_signed<T>::value, BackwardIt> +DoFastIntToBufferBackward(T v, BackwardIt end, uint32_t digits) { + if (absl::numbers_internal::IsNegative(v)) { + // Store the minus sign *before* we produce the number itself, not after. + // This gets us a tail call. + end[-static_cast<ptrdiff_t>(digits) - 1] = '-'; } -set_last_zero: - *buffer = '\0'; + return DoFastIntToBufferBackward( + absl::numbers_internal::UnsignedAbsoluteValue(v), end, digits); +} + +template <class T> +std::enable_if_t<std::is_integral<T>::value, int> +GetNumDigitsOrNegativeIfNegativeImpl(T v) { + const auto /* either bool or std::false_type */ is_negative = + absl::numbers_internal::IsNegative(v); + const int digits = static_cast<int>(absl::numbers_internal::Base10Digits( + absl::numbers_internal::UnsignedAbsoluteValue(v))); + return is_negative ? ~digits : digits; +} + +} // namespace + +void numbers_internal::PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf) { + little_endian::Store16( + buf, static_cast<uint16_t>(PrepareTwoDigits(i) + kTwoZeroBytes)); +} + +absl::Nonnull<char*> numbers_internal::FastIntToBuffer( + uint32_t i, absl::Nonnull<char*> buffer) { + const uint32_t digits = absl::numbers_internal::Base10Digits(i); + buffer += digits; + *buffer = '\0'; // We're going backward, so store this first + FastIntToBufferBackward(i, buffer, digits); return buffer; } -char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) { - uint64_t u = static_cast<uint64_t>(i); - if (i < 0) { - *buffer++ = '-'; - u = 0 - u; - } - return numbers_internal::FastIntToBuffer(u, buffer); +absl::Nonnull<char*> numbers_internal::FastIntToBuffer( + int32_t i, absl::Nonnull<char*> buffer) { + buffer += static_cast<int>(i < 0); + uint32_t digits = absl::numbers_internal::Base10Digits( + absl::numbers_internal::UnsignedAbsoluteValue(i)); + buffer += digits; + *buffer = '\0'; // We're going backward, so store this first + FastIntToBufferBackward(i, buffer, digits); + return buffer; +} + +absl::Nonnull<char*> numbers_internal::FastIntToBuffer( + uint64_t i, absl::Nonnull<char*> buffer) { + uint32_t digits = absl::numbers_internal::Base10Digits(i); + buffer += digits; + *buffer = '\0'; // We're going backward, so store this first + FastIntToBufferBackward(i, buffer, digits); + return buffer; +} + +absl::Nonnull<char*> numbers_internal::FastIntToBuffer( + int64_t i, absl::Nonnull<char*> buffer) { + buffer += static_cast<int>(i < 0); + uint32_t digits = absl::numbers_internal::Base10Digits( + absl::numbers_internal::UnsignedAbsoluteValue(i)); + buffer += digits; + *buffer = '\0'; // We're going backward, so store this first + FastIntToBufferBackward(i, buffer, digits); + return buffer; +} + +absl::Nonnull<char*> numbers_internal::FastIntToBufferBackward( + uint32_t i, absl::Nonnull<char*> buffer_end, uint32_t exact_digit_count) { + return DoFastIntToBufferBackward(i, buffer_end, exact_digit_count); +} + +absl::Nonnull<char*> numbers_internal::FastIntToBufferBackward( + int32_t i, absl::Nonnull<char*> buffer_end, uint32_t exact_digit_count) { + return DoFastIntToBufferBackward(i, buffer_end, exact_digit_count); +} + +absl::Nonnull<char*> numbers_internal::FastIntToBufferBackward( + uint64_t i, absl::Nonnull<char*> buffer_end, uint32_t exact_digit_count) { + return DoFastIntToBufferBackward(i, buffer_end, exact_digit_count); +} + +absl::Nonnull<char*> numbers_internal::FastIntToBufferBackward( + int64_t i, absl::Nonnull<char*> buffer_end, uint32_t exact_digit_count) { + return DoFastIntToBufferBackward(i, buffer_end, exact_digit_count); +} + +int numbers_internal::GetNumDigitsOrNegativeIfNegative(signed char v) { + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative(unsigned char v) { + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative(short v) { // NOLINT + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative( + unsigned short v) { // NOLINT + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative(int v) { + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative(unsigned int v) { + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative(long v) { // NOLINT + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative( + unsigned long v) { // NOLINT + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative(long long v) { // NOLINT + return GetNumDigitsOrNegativeIfNegativeImpl(v); +} +int numbers_internal::GetNumDigitsOrNegativeIfNegative( + unsigned long long v) { // NOLINT + return GetNumDigitsOrNegativeIfNegativeImpl(v); } // Given a 128-bit number expressed as a pair of uint64_t, high half first, @@ -534,7 +769,8 @@ static ExpDigits SplitToSix(const double value) { // Helper function for fast formatting of floating-point. // The result is the same as "%g", a.k.a. "%.6g". -size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) { +size_t numbers_internal::SixDigitsToBuffer(double d, + absl::Nonnull<char*> const buffer) { static_assert(std::numeric_limits<float>::is_iec559, "IEEE-754/IEC-559 support only"); @@ -681,9 +917,10 @@ static const int8_t kAsciiToInt[256] = { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}; // Parse the sign and optional hex or oct prefix in text. -inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/, - int* base_ptr /*inout*/, - bool* negative_ptr /*output*/) { +inline bool safe_parse_sign_and_base( + absl::Nonnull<absl::string_view*> text /*inout*/, + absl::Nonnull<int*> base_ptr /*inout*/, + absl::Nonnull<bool*> negative_ptr /*output*/) { if (text->data() == nullptr) { return false; } @@ -968,7 +1205,7 @@ ABSL_CONST_INIT const IntType LookupTables<IntType>::kVminOverBase[] = template <typename IntType> inline bool safe_parse_positive_int(absl::string_view text, int base, - IntType* value_p) { + absl::Nonnull<IntType*> value_p) { IntType value = 0; const IntType vmax = std::numeric_limits<IntType>::max(); assert(vmax > 0); @@ -1005,7 +1242,7 @@ inline bool safe_parse_positive_int(absl::string_view text, int base, template <typename IntType> inline bool safe_parse_negative_int(absl::string_view text, int base, - IntType* value_p) { + absl::Nonnull<IntType*> value_p) { IntType value = 0; const IntType vmin = std::numeric_limits<IntType>::min(); assert(vmin < 0); @@ -1049,8 +1286,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base, // Input format based on POSIX.1-2008 strtol // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html template <typename IntType> -inline bool safe_int_internal(absl::string_view text, IntType* value_p, - int base) { +inline bool safe_int_internal(absl::string_view text, + absl::Nonnull<IntType*> value_p, int base) { *value_p = 0; bool negative; if (!safe_parse_sign_and_base(&text, &base, &negative)) { @@ -1064,8 +1301,8 @@ inline bool safe_int_internal(absl::string_view text, IntType* value_p, } template <typename IntType> -inline bool safe_uint_internal(absl::string_view text, IntType* value_p, - int base) { +inline bool safe_uint_internal(absl::string_view text, + absl::Nonnull<IntType*> value_p, int base) { *value_p = 0; bool negative; if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) { @@ -1099,27 +1336,33 @@ ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] = "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; -bool safe_strto32_base(absl::string_view text, int32_t* value, int base) { +bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value, + int base) { return safe_int_internal<int32_t>(text, value, base); } -bool safe_strto64_base(absl::string_view text, int64_t* value, int base) { +bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value, + int base) { return safe_int_internal<int64_t>(text, value, base); } -bool safe_strto128_base(absl::string_view text, int128* value, int base) { +bool safe_strto128_base(absl::string_view text, absl::Nonnull<int128*> value, + int base) { return safe_int_internal<absl::int128>(text, value, base); } -bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) { +bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value, + int base) { return safe_uint_internal<uint32_t>(text, value, base); } -bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base) { +bool safe_strtou64_base(absl::string_view text, absl::Nonnull<uint64_t*> value, + int base) { return safe_uint_internal<uint64_t>(text, value, base); } -bool safe_strtou128_base(absl::string_view text, uint128* value, int base) { +bool safe_strtou128_base(absl::string_view text, absl::Nonnull<uint128*> value, + int base) { return safe_uint_internal<absl::uint128>(text, value, base); } diff --git a/contrib/restricted/abseil-cpp/absl/strings/numbers.h b/contrib/restricted/abseil-cpp/absl/strings/numbers.h index d7630cef9c..ad4e66b634 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/numbers.h +++ b/contrib/restricted/abseil-cpp/absl/strings/numbers.h @@ -32,6 +32,7 @@ #endif #include <cstddef> +#include <cstdint> #include <cstdlib> #include <cstring> #include <ctime> @@ -39,9 +40,12 @@ #include <string> #include <type_traits> +#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/endian.h" #include "absl/base/macros.h" +#include "absl/base/nullability.h" +#include "absl/base/optimization.h" #include "absl/base/port.h" #include "absl/numeric/bits.h" #include "absl/numeric/int128.h" @@ -59,7 +63,8 @@ ABSL_NAMESPACE_BEGIN // encountered, this function returns `false`, leaving `out` in an unspecified // state. template <typename int_type> -ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out); +ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, + absl::Nonnull<int_type*> out); // SimpleAtof() // @@ -70,7 +75,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out); // allowed formats for `str`, except SimpleAtof() is locale-independent and will // always use the "C" locale. If any errors are encountered, this function // returns `false`, leaving `out` in an unspecified state. -ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out); +ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, + absl::Nonnull<float*> out); // SimpleAtod() // @@ -81,7 +87,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out); // allowed formats for `str`, except SimpleAtod is locale-independent and will // always use the "C" locale. If any errors are encountered, this function // returns `false`, leaving `out` in an unspecified state. -ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out); +ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, + absl::Nonnull<double*> out); // SimpleAtob() // @@ -91,7 +98,8 @@ ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out); // are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any // errors are encountered, this function returns `false`, leaving `out` in an // unspecified state. -ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out); +ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, + absl::Nonnull<bool*> out); // SimpleHexAtoi() // @@ -104,13 +112,14 @@ ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out); // by this function. If any errors are encountered, this function returns // `false`, leaving `out` in an unspecified state. template <typename int_type> -ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, int_type* out); +ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, + absl::Nonnull<int_type*> out); // Overloads of SimpleHexAtoi() for 128 bit integers. -ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, - absl::int128* out); -ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, - absl::uint128* out); +ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi( + absl::string_view str, absl::Nonnull<absl::int128*> out); +ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi( + absl::string_view str, absl::Nonnull<absl::uint128*> out); ABSL_NAMESPACE_END } // namespace absl @@ -132,42 +141,136 @@ ABSL_DLL extern const char // PutTwoDigits(42, buf); // // buf[0] == '4' // // buf[1] == '2' -void PutTwoDigits(uint32_t i, char* buf); +void PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf); // safe_strto?() functions for implementing SimpleAtoi() -bool safe_strto32_base(absl::string_view text, int32_t* value, int base); -bool safe_strto64_base(absl::string_view text, int64_t* value, int base); -bool safe_strto128_base(absl::string_view text, absl::int128* value, - int base); -bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base); -bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base); -bool safe_strtou128_base(absl::string_view text, absl::uint128* value, - int base); +bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value, + int base); +bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value, + int base); +bool safe_strto128_base(absl::string_view text, + absl::Nonnull<absl::int128*> value, int base); +bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value, + int base); +bool safe_strtou64_base(absl::string_view text, absl::Nonnull<uint64_t*> value, + int base); +bool safe_strtou128_base(absl::string_view text, + absl::Nonnull<absl::uint128*> value, int base); static const int kFastToBufferSize = 32; static const int kSixDigitsToBufferSize = 16; +template <class T> +std::enable_if_t<!std::is_unsigned<T>::value, bool> IsNegative(const T& v) { + return v < T(); +} + +template <class T> +std::enable_if_t<std::is_unsigned<T>::value, std::false_type> IsNegative( + const T&) { + // The integer is unsigned, so return a compile-time constant. + // This can help the optimizer avoid having to prove bool to be false later. + return std::false_type(); +} + +template <class T> +std::enable_if_t<std::is_unsigned<std::decay_t<T>>::value, T&&> +UnsignedAbsoluteValue(T&& v ABSL_ATTRIBUTE_LIFETIME_BOUND) { + // The value is unsigned; just return the original. + return std::forward<T>(v); +} + +template <class T> +ABSL_ATTRIBUTE_CONST_FUNCTION + std::enable_if_t<!std::is_unsigned<T>::value, std::make_unsigned_t<T>> + UnsignedAbsoluteValue(T v) { + using U = std::make_unsigned_t<T>; + return IsNegative(v) ? U() - static_cast<U>(v) : static_cast<U>(v); +} + +// Returns the number of base-10 digits in the given number. +// Note that this strictly counts digits. It does not count the sign. +// The `initial_digits` parameter is the starting point, which is normally equal +// to 1 because the number of digits in 0 is 1 (a special case). +// However, callers may e.g. wish to change it to 2 to account for the sign. +template <typename T> +std::enable_if_t<std::is_unsigned<T>::value, uint32_t> Base10Digits( + T v, const uint32_t initial_digits = 1) { + uint32_t r = initial_digits; + // If code size becomes an issue, the 'if' stage can be removed for a minor + // performance loss. + for (;;) { + if (ABSL_PREDICT_TRUE(v < 10 * 10)) { + r += (v >= 10); + break; + } + if (ABSL_PREDICT_TRUE(v < 1000 * 10)) { + r += (v >= 1000) + 2; + break; + } + if (ABSL_PREDICT_TRUE(v < 100000 * 10)) { + r += (v >= 100000) + 4; + break; + } + r += 6; + v = static_cast<T>(v / 1000000); + } + return r; +} + +template <typename T> +std::enable_if_t<std::is_signed<T>::value, uint32_t> Base10Digits( + T v, uint32_t r = 1) { + // Branchlessly add 1 to account for a minus sign. + r += static_cast<uint32_t>(IsNegative(v)); + return Base10Digits(UnsignedAbsoluteValue(v), r); +} + +// These functions return the number of base-10 digits, but multiplied by -1 if +// the input itself is negative. This is handy and efficient for later usage, +// since the bitwise complement of the result becomes equal to the number of +// characters required. +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + signed char v); +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + unsigned char v); +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + short v); // NOLINT +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + unsigned short v); // NOLINT +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative(int v); +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + unsigned int v); +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + long v); // NOLINT +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + unsigned long v); // NOLINT +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + long long v); // NOLINT +ABSL_ATTRIBUTE_CONST_FUNCTION int GetNumDigitsOrNegativeIfNegative( + unsigned long long v); // NOLINT + // Helper function for fast formatting of floating-point values. // The result is the same as printf's "%g", a.k.a. "%.6g"; that is, six // significant digits are returned, trailing zeros are removed, and numbers // outside the range 0.0001-999999 are output using scientific notation // (1.23456e+06). This routine is heavily optimized. // Required buffer size is `kSixDigitsToBufferSize`. -size_t SixDigitsToBuffer(double d, char* buffer); +size_t SixDigitsToBuffer(double d, absl::Nonnull<char*> buffer); -// These functions are intended for speed. All functions take an output buffer +// All of these functions take an output buffer // as an argument and return a pointer to the last byte they wrote, which is the // terminating '\0'. At most `kFastToBufferSize` bytes are written. -char* FastIntToBuffer(int32_t, char*); -char* FastIntToBuffer(uint32_t, char*); -char* FastIntToBuffer(int64_t, char*); -char* FastIntToBuffer(uint64_t, char*); +absl::Nonnull<char*> FastIntToBuffer(int32_t i, absl::Nonnull<char*> buffer); +absl::Nonnull<char*> FastIntToBuffer(uint32_t i, absl::Nonnull<char*> buffer); +absl::Nonnull<char*> FastIntToBuffer(int64_t i, absl::Nonnull<char*> buffer); +absl::Nonnull<char*> FastIntToBuffer(uint64_t i, absl::Nonnull<char*> buffer); // For enums and integer types that are not an exact match for the types above, // use templates to call the appropriate one of the four overloads above. template <typename int_type> -char* FastIntToBuffer(int_type i, char* buffer) { +absl::Nonnull<char*> FastIntToBuffer(int_type i, absl::Nonnull<char*> buffer) { static_assert(sizeof(i) <= 64 / 8, "FastIntToBuffer works only with 64-bit-or-less integers."); // TODO(jorg): This signed-ness check is used because it works correctly @@ -191,10 +294,63 @@ char* FastIntToBuffer(int_type i, char* buffer) { } } +// These functions do NOT add any null-terminator. +// They return a pointer to the beginning of the written string. +// The digit counts provided must *exactly* match the number of base-10 digits +// in the number, or the behavior is undefined. +// (i.e. do NOT count the minus sign, or over- or under-count the digits.) +absl::Nonnull<char*> FastIntToBufferBackward(int32_t i, + absl::Nonnull<char*> buffer_end, + uint32_t exact_digit_count); +absl::Nonnull<char*> FastIntToBufferBackward(uint32_t i, + absl::Nonnull<char*> buffer_end, + uint32_t exact_digit_count); +absl::Nonnull<char*> FastIntToBufferBackward(int64_t i, + absl::Nonnull<char*> buffer_end, + uint32_t exact_digit_count); +absl::Nonnull<char*> FastIntToBufferBackward(uint64_t i, + absl::Nonnull<char*> buffer_end, + uint32_t exact_digit_count); + +// For enums and integer types that are not an exact match for the types above, +// use templates to call the appropriate one of the four overloads above. +template <typename int_type> +absl::Nonnull<char*> FastIntToBufferBackward(int_type i, + absl::Nonnull<char*> buffer_end, + uint32_t exact_digit_count) { + static_assert( + sizeof(i) <= 64 / 8, + "FastIntToBufferBackward works only with 64-bit-or-less integers."); + // This signed-ness check is used because it works correctly + // with enums, and it also serves to check that int_type is not a pointer. + // If one day something like std::is_signed<enum E> works, switch to it. + // These conditions are constexpr bools to suppress MSVC warning C4127. + constexpr bool kIsSigned = static_cast<int_type>(1) - 2 < 0; + constexpr bool kUse64Bit = sizeof(i) > 32 / 8; + if (kIsSigned) { + if (kUse64Bit) { + return FastIntToBufferBackward(static_cast<int64_t>(i), buffer_end, + exact_digit_count); + } else { + return FastIntToBufferBackward(static_cast<int32_t>(i), buffer_end, + exact_digit_count); + } + } else { + if (kUse64Bit) { + return FastIntToBufferBackward(static_cast<uint64_t>(i), buffer_end, + exact_digit_count); + } else { + return FastIntToBufferBackward(static_cast<uint32_t>(i), buffer_end, + exact_digit_count); + } + } +} + // Implementation of SimpleAtoi, generalized to support arbitrary base (used // with base different from 10 elsewhere in Abseil implementation). template <typename int_type> -ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out, +ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, + absl::Nonnull<int_type*> out, int base) { static_assert(sizeof(*out) == 4 || sizeof(*out) == 8, "SimpleAtoi works only with 32-bit or 64-bit integers."); @@ -237,7 +393,7 @@ ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out, // without the terminating null character. Thus `out` must be of length >= 16. // Returns the number of non-pad digits of the output (it can never be zero // since 0 has one digit). -inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) { +inline size_t FastHexToBufferZeroPad16(uint64_t val, absl::Nonnull<char*> out) { #ifdef ABSL_INTERNAL_HAVE_SSSE3 uint64_t be = absl::big_endian::FromHost64(val); const auto kNibbleMask = _mm_set1_epi8(0xf); @@ -263,32 +419,34 @@ inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) { } // namespace numbers_internal template <typename int_type> -ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out) { +ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, + absl::Nonnull<int_type*> out) { return numbers_internal::safe_strtoi_base(str, out, 10); } ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str, - absl::int128* out) { + absl::Nonnull<absl::int128*> out) { return numbers_internal::safe_strto128_base(str, out, 10); } ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str, - absl::uint128* out) { + absl::Nonnull<absl::uint128*> out) { return numbers_internal::safe_strtou128_base(str, out, 10); } template <typename int_type> -ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, int_type* out) { +ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, + absl::Nonnull<int_type*> out) { return numbers_internal::safe_strtoi_base(str, out, 16); } -ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, - absl::int128* out) { +ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi( + absl::string_view str, absl::Nonnull<absl::int128*> out) { return numbers_internal::safe_strto128_base(str, out, 16); } -ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str, - absl::uint128* out) { +ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi( + absl::string_view str, absl::Nonnull<absl::uint128*> out) { return numbers_internal::safe_strtou128_base(str, out, 16); } diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc b/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc index 2e49c31b68..098ab18388 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc @@ -16,13 +16,15 @@ #include <assert.h> -#include <algorithm> #include <cstddef> #include <cstdint> #include <cstring> +#include <initializer_list> #include <string> +#include <type_traits> -#include "absl/strings/ascii.h" +#include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" @@ -30,6 +32,7 @@ namespace absl { ABSL_NAMESPACE_BEGIN + // ---------------------------------------------------------------------- // StrCat() // This merges the given strings or integers, with no delimiter. This @@ -37,9 +40,10 @@ ABSL_NAMESPACE_BEGIN // of a mix of raw C strings, string_views, strings, and integer values. // ---------------------------------------------------------------------- +namespace { // Append is merely a version of memcpy that returns the address of the byte // after the area just overwritten. -static char* Append(char* out, const AlphaNum& x) { +absl::Nonnull<char*> Append(absl::Nonnull<char*> out, const AlphaNum& x) { // memcpy is allowed to overwrite arbitrary memory, so doing this after the // call would force an extra fetch of x.size(). char* after = out + x.size(); @@ -49,6 +53,8 @@ static char* Append(char* out, const AlphaNum& x) { return after; } +} // namespace + std::string StrCat(const AlphaNum& a, const AlphaNum& b) { std::string result; absl::strings_internal::STLStringResizeUninitialized(&result, @@ -92,6 +98,130 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, namespace strings_internal { // Do not call directly - these are not part of the public API. +void STLStringAppendUninitializedAmortized(std::string* dest, + size_t to_append) { + strings_internal::AppendUninitializedTraits<std::string>::Append(dest, + to_append); +} + +template <typename Integer> +std::enable_if_t<std::is_integral<Integer>::value, std::string> IntegerToString( + Integer i) { + std::string str; + const auto /* either bool or std::false_type */ is_negative = + absl::numbers_internal::IsNegative(i); + const uint32_t digits = absl::numbers_internal::Base10Digits( + absl::numbers_internal::UnsignedAbsoluteValue(i)); + absl::strings_internal::STLStringResizeUninitialized( + &str, digits + static_cast<uint32_t>(is_negative)); + absl::numbers_internal::FastIntToBufferBackward(i, &str[str.size()], digits); + return str; +} + +template <> +std::string IntegerToString(long i) { // NOLINT + if (sizeof(i) <= sizeof(int)) { + return IntegerToString(static_cast<int>(i)); + } else { + return IntegerToString(static_cast<long long>(i)); // NOLINT + } +} + +template <> +std::string IntegerToString(unsigned long i) { // NOLINT + if (sizeof(i) <= sizeof(unsigned int)) { + return IntegerToString(static_cast<unsigned int>(i)); + } else { + return IntegerToString(static_cast<unsigned long long>(i)); // NOLINT + } +} + +template <typename Float> +std::enable_if_t<std::is_floating_point<Float>::value, std::string> +FloatToString(Float f) { + std::string result; + strings_internal::STLStringResizeUninitialized( + &result, numbers_internal::kSixDigitsToBufferSize); + char* start = &result[0]; + result.erase(numbers_internal::SixDigitsToBuffer(f, start)); + return result; +} + +std::string SingleArgStrCat(int x) { return IntegerToString(x); } +std::string SingleArgStrCat(unsigned int x) { return IntegerToString(x); } +// NOLINTNEXTLINE +std::string SingleArgStrCat(long x) { return IntegerToString(x); } +// NOLINTNEXTLINE +std::string SingleArgStrCat(unsigned long x) { return IntegerToString(x); } +// NOLINTNEXTLINE +std::string SingleArgStrCat(long long x) { return IntegerToString(x); } +// NOLINTNEXTLINE +std::string SingleArgStrCat(unsigned long long x) { return IntegerToString(x); } +std::string SingleArgStrCat(float x) { return FloatToString(x); } +std::string SingleArgStrCat(double x) { return FloatToString(x); } + +template <class Integer> +std::enable_if_t<std::is_integral<Integer>::value, void> AppendIntegerToString( + std::string& str, Integer i) { + const auto /* either bool or std::false_type */ is_negative = + absl::numbers_internal::IsNegative(i); + const uint32_t digits = absl::numbers_internal::Base10Digits( + absl::numbers_internal::UnsignedAbsoluteValue(i)); + absl::strings_internal::STLStringAppendUninitializedAmortized( + &str, digits + static_cast<uint32_t>(is_negative)); + absl::numbers_internal::FastIntToBufferBackward(i, &str[str.size()], digits); +} + +template <> +void AppendIntegerToString(std::string& str, long i) { // NOLINT + if (sizeof(i) <= sizeof(int)) { + return AppendIntegerToString(str, static_cast<int>(i)); + } else { + return AppendIntegerToString(str, static_cast<long long>(i)); // NOLINT + } +} + +template <> +void AppendIntegerToString(std::string& str, + unsigned long i) { // NOLINT + if (sizeof(i) <= sizeof(unsigned int)) { + return AppendIntegerToString(str, static_cast<unsigned int>(i)); + } else { + return AppendIntegerToString(str, + static_cast<unsigned long long>(i)); // NOLINT + } +} + +// `SingleArgStrAppend` overloads are defined here for the same reasons as with +// `SingleArgStrCat` above. +void SingleArgStrAppend(std::string& str, int x) { + return AppendIntegerToString(str, x); +} + +void SingleArgStrAppend(std::string& str, unsigned int x) { + return AppendIntegerToString(str, x); +} + +// NOLINTNEXTLINE +void SingleArgStrAppend(std::string& str, long x) { + return AppendIntegerToString(str, x); +} + +// NOLINTNEXTLINE +void SingleArgStrAppend(std::string& str, unsigned long x) { + return AppendIntegerToString(str, x); +} + +// NOLINTNEXTLINE +void SingleArgStrAppend(std::string& str, long long x) { + return AppendIntegerToString(str, x); +} + +// NOLINTNEXTLINE +void SingleArgStrAppend(std::string& str, unsigned long long x) { + return AppendIntegerToString(str, x); +} + std::string CatPieces(std::initializer_list<absl::string_view> pieces) { std::string result; size_t total_size = 0; @@ -120,15 +250,15 @@ std::string CatPieces(std::initializer_list<absl::string_view> pieces) { assert(((src).size() == 0) || \ (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size()))) -void AppendPieces(std::string* dest, +void AppendPieces(absl::Nonnull<std::string*> dest, std::initializer_list<absl::string_view> pieces) { size_t old_size = dest->size(); - size_t total_size = old_size; + size_t to_append = 0; for (absl::string_view piece : pieces) { ASSERT_NO_OVERLAP(*dest, piece); - total_size += piece.size(); + to_append += piece.size(); } - strings_internal::STLStringResizeUninitializedAmortized(dest, total_size); + strings_internal::STLStringAppendUninitializedAmortized(dest, to_append); char* const begin = &(*dest)[0]; char* out = begin + old_size; @@ -144,23 +274,23 @@ void AppendPieces(std::string* dest, } // namespace strings_internal -void StrAppend(std::string* dest, const AlphaNum& a) { +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a) { ASSERT_NO_OVERLAP(*dest, a); std::string::size_type old_size = dest->size(); - strings_internal::STLStringResizeUninitializedAmortized(dest, - old_size + a.size()); + strings_internal::STLStringAppendUninitializedAmortized(dest, a.size()); char* const begin = &(*dest)[0]; char* out = begin + old_size; out = Append(out, a); assert(out == begin + dest->size()); } -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) { +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a, + const AlphaNum& b) { ASSERT_NO_OVERLAP(*dest, a); ASSERT_NO_OVERLAP(*dest, b); std::string::size_type old_size = dest->size(); - strings_internal::STLStringResizeUninitializedAmortized( - dest, old_size + a.size() + b.size()); + strings_internal::STLStringAppendUninitializedAmortized(dest, + a.size() + b.size()); char* const begin = &(*dest)[0]; char* out = begin + old_size; out = Append(out, a); @@ -168,14 +298,14 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) { assert(out == begin + dest->size()); } -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c) { +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c) { ASSERT_NO_OVERLAP(*dest, a); ASSERT_NO_OVERLAP(*dest, b); ASSERT_NO_OVERLAP(*dest, c); std::string::size_type old_size = dest->size(); - strings_internal::STLStringResizeUninitializedAmortized( - dest, old_size + a.size() + b.size() + c.size()); + strings_internal::STLStringAppendUninitializedAmortized( + dest, a.size() + b.size() + c.size()); char* const begin = &(*dest)[0]; char* out = begin + old_size; out = Append(out, a); @@ -184,15 +314,15 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, assert(out == begin + dest->size()); } -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d) { +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c, const AlphaNum& d) { ASSERT_NO_OVERLAP(*dest, a); ASSERT_NO_OVERLAP(*dest, b); ASSERT_NO_OVERLAP(*dest, c); ASSERT_NO_OVERLAP(*dest, d); std::string::size_type old_size = dest->size(); - strings_internal::STLStringResizeUninitializedAmortized( - dest, old_size + a.size() + b.size() + c.size() + d.size()); + strings_internal::STLStringAppendUninitializedAmortized( + dest, a.size() + b.size() + c.size() + d.size()); char* const begin = &(*dest)[0]; char* out = begin + old_size; out = Append(out, a); diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h index d5f71ff003..ea2c4dcad8 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h +++ b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h @@ -89,6 +89,8 @@ #include <algorithm> #include <array> +#include <cassert> +#include <cstddef> #include <cstdint> #include <cstring> #include <string> @@ -97,8 +99,11 @@ #include <vector> #include "absl/base/attributes.h" +#include "absl/base/nullability.h" #include "absl/base/port.h" -#include "absl/strings/internal/has_absl_stringify.h" +#include "absl/meta/type_traits.h" +#include "absl/strings/has_absl_stringify.h" +#include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/stringify_sink.h" #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" @@ -201,7 +206,7 @@ struct Hex { !std::is_pointer<Int>::value>::type* = nullptr) : Hex(spec, static_cast<uint64_t>(v)) {} template <typename Pointee> - explicit Hex(Pointee* v, PadSpec spec = absl::kNoPad) + explicit Hex(absl::Nullable<Pointee*> v, PadSpec spec = absl::kNoPad) : Hex(spec, reinterpret_cast<uintptr_t>(v)) {} template <typename S> @@ -253,10 +258,9 @@ struct Dec { typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr) : value(v >= 0 ? static_cast<uint64_t>(v) : uint64_t{0} - static_cast<uint64_t>(v)), - width(spec == absl::kNoPad - ? 1 - : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2 - : spec - absl::kZeroPad2 + 2), + width(spec == absl::kNoPad ? 1 + : spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2 + : spec - absl::kZeroPad2 + 2), fill(spec >= absl::kSpacePad2 ? ' ' : '0'), neg(v < 0) {} @@ -344,7 +348,7 @@ class AlphaNum { ABSL_ATTRIBUTE_LIFETIME_BOUND) : piece_(&buf.data[0], buf.size) {} - AlphaNum(const char* c_str // NOLINT(runtime/explicit) + AlphaNum(absl::Nullable<const char*> c_str // NOLINT(runtime/explicit) ABSL_ATTRIBUTE_LIFETIME_BOUND) : piece_(NullSafeStringView(c_str)) {} AlphaNum(absl::string_view pc // NOLINT(runtime/explicit) @@ -352,7 +356,7 @@ class AlphaNum { : piece_(pc) {} template <typename T, typename = typename std::enable_if< - strings_internal::HasAbslStringify<T>::value>::type> + HasAbslStringify<T>::value>::type> AlphaNum( // NOLINT(runtime/explicit) const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND, strings_internal::StringifySink&& sink ABSL_ATTRIBUTE_LIFETIME_BOUND = {}) @@ -371,7 +375,7 @@ class AlphaNum { AlphaNum& operator=(const AlphaNum&) = delete; absl::string_view::size_type size() const { return piece_.size(); } - const char* data() const { return piece_.data(); } + absl::Nullable<const char*> data() const { return piece_.data(); } absl::string_view Piece() const { return piece_; } // Match unscoped enums. Use integral promotion so that a `char`-backed @@ -379,17 +383,17 @@ class AlphaNum { template <typename T, typename = typename std::enable_if< std::is_enum<T>{} && std::is_convertible<T, int>{} && - !strings_internal::HasAbslStringify<T>::value>::type> + !HasAbslStringify<T>::value>::type> AlphaNum(T e) // NOLINT(runtime/explicit) : AlphaNum(+e) {} // This overload matches scoped enums. We must explicitly cast to the // underlying type, but use integral promotion for the same reason as above. template <typename T, - typename std::enable_if< - std::is_enum<T>{} && !std::is_convertible<T, int>{} && - !strings_internal::HasAbslStringify<T>::value, - char*>::type = nullptr> + typename std::enable_if<std::is_enum<T>{} && + !std::is_convertible<T, int>{} && + !HasAbslStringify<T>::value, + char*>::type = nullptr> AlphaNum(T e) // NOLINT(runtime/explicit) : AlphaNum(+static_cast<typename std::underlying_type<T>::type>(e)) {} @@ -441,13 +445,48 @@ namespace strings_internal { // Do not call directly - this is not part of the public API. std::string CatPieces(std::initializer_list<absl::string_view> pieces); -void AppendPieces(std::string* dest, +void AppendPieces(absl::Nonnull<std::string*> dest, std::initializer_list<absl::string_view> pieces); +void STLStringAppendUninitializedAmortized(std::string* dest, size_t to_append); + +// `SingleArgStrCat` overloads take built-in `int`, `long` and `long long` types +// (signed / unsigned) to avoid ambiguity on the call side. If we used int32_t +// and int64_t, then at least one of the three (`int` / `long` / `long long`) +// would have been ambiguous when passed to `SingleArgStrCat`. +std::string SingleArgStrCat(int x); +std::string SingleArgStrCat(unsigned int x); +std::string SingleArgStrCat(long x); // NOLINT +std::string SingleArgStrCat(unsigned long x); // NOLINT +std::string SingleArgStrCat(long long x); // NOLINT +std::string SingleArgStrCat(unsigned long long x); // NOLINT +std::string SingleArgStrCat(float x); +std::string SingleArgStrCat(double x); + +// `SingleArgStrAppend` overloads are defined here for the same reasons as with +// `SingleArgStrCat` above. +void SingleArgStrAppend(std::string& str, int x); +void SingleArgStrAppend(std::string& str, unsigned int x); +void SingleArgStrAppend(std::string& str, long x); // NOLINT +void SingleArgStrAppend(std::string& str, unsigned long x); // NOLINT +void SingleArgStrAppend(std::string& str, long long x); // NOLINT +void SingleArgStrAppend(std::string& str, unsigned long long x); // NOLINT + +template <typename T, + typename = std::enable_if_t<std::is_arithmetic<T>::value && + !std::is_same<T, char>::value && + !std::is_same<T, bool>::value>> +using EnableIfFastCase = T; + } // namespace strings_internal ABSL_MUST_USE_RESULT inline std::string StrCat() { return std::string(); } +template <typename T> +ABSL_MUST_USE_RESULT inline std::string StrCat( + strings_internal::EnableIfFastCase<T> a) { + return strings_internal::SingleArgStrCat(a); +} ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) { return std::string(a.data(), a.size()); } @@ -495,24 +534,87 @@ ABSL_MUST_USE_RESULT inline std::string StrCat( // absl::string_view p = s; // StrAppend(&s, p); -inline void StrAppend(std::string*) {} -void StrAppend(std::string* dest, const AlphaNum& a); -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b); -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c); -void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d); +inline void StrAppend(absl::Nonnull<std::string*>) {} +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a); +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a, + const AlphaNum& b); +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c); +void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c, const AlphaNum& d); // Support 5 or more arguments template <typename... AV> -inline void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, const AlphaNum& e, - const AV&... args) { +inline void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AV&... args) { strings_internal::AppendPieces( dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(), static_cast<const AlphaNum&>(args).Piece()...}); } +template <class String, class T> +std::enable_if_t< + std::is_integral<absl::strings_internal::EnableIfFastCase<T>>::value, void> +StrAppend(absl::Nonnull<String*> result, T i) { + return absl::strings_internal::SingleArgStrAppend(*result, i); +} + +// This overload is only selected if all the parameters are numbers that can be +// handled quickly. +// Later we can look into how we can extend this to more general argument +// mixtures without bloating codegen too much, or copying unnecessarily. +template <typename String, typename... T> +std::enable_if_t< + (sizeof...(T) > 1), + std::common_type_t<std::conditional_t< + true, void, absl::strings_internal::EnableIfFastCase<T>>...>> +StrAppend(absl::Nonnull<String*> str, T... args) { + // Do not add unnecessary variables, logic, or even "free" lambdas here. + // They can add overhead for the compiler and/or at run time. + // Furthermore, assume this function will be inlined. + // This function is carefully tailored to be able to be largely optimized away + // so that it becomes near-equivalent to the caller handling each argument + // individually while minimizing register pressure, so that the compiler + // can inline it with minimal overhead. + + // First, calculate the total length, so we can perform just a single resize. + // Save all the lengths for later. + size_t total_length = 0; + const ptrdiff_t lengths[] = { + absl::numbers_internal::GetNumDigitsOrNegativeIfNegative(args)...}; + for (const ptrdiff_t possibly_negative_length : lengths) { + // Lengths are negative for negative numbers. Keep them for later use, but + // take their absolute values for calculating total lengths; + total_length += possibly_negative_length < 0 + ? static_cast<size_t>(-possibly_negative_length) + : static_cast<size_t>(possibly_negative_length); + } + + // Now reserve space for all the arguments. + const size_t old_size = str->size(); + absl::strings_internal::STLStringAppendUninitializedAmortized(str, + total_length); + + // Finally, output each argument one-by-one, from left to right. + size_t i = 0; // The current argument we're processing + ptrdiff_t n; // The length of the current argument + typename String::pointer pos = &(*str)[old_size]; + using SomeTrivialEmptyType = std::false_type; + // Ugly code due to the lack of C++14 fold expression makes us. + const SomeTrivialEmptyType dummy1; + for (const SomeTrivialEmptyType& dummy2 : + {(/* Comma expressions are poor man's C++17 fold expression for C++14 */ + (void)(n = lengths[i]), + (void)(n < 0 ? (void)(*pos++ = '-'), (n = ~n) : 0), + (void)absl::numbers_internal::FastIntToBufferBackward( + absl::numbers_internal::UnsignedAbsoluteValue(std::move(args)), + pos += n, static_cast<uint32_t>(n)), + (void)++i, dummy1)...}) { + (void)dummy2; // Remove & migrate to fold expressions in C++17 + } +} + // Helper function for the future StrCat default floating-point format, %.6g // This is fast. inline strings_internal::AlphaNumBuffer< diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_format.h b/contrib/restricted/abseil-cpp/absl/strings/str_format.h index 023e4350d3..66b6af5854 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_format.h +++ b/contrib/restricted/abseil-cpp/absl/strings/str_format.h @@ -72,14 +72,21 @@ #ifndef ABSL_STRINGS_STR_FORMAT_H_ #define ABSL_STRINGS_STR_FORMAT_H_ +#include <cstdint> #include <cstdio> #include <string> +#include <type_traits> +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/strings/internal/str_format/arg.h" // IWYU pragma: export #include "absl/strings/internal/str_format/bind.h" // IWYU pragma: export #include "absl/strings/internal/str_format/checker.h" // IWYU pragma: export #include "absl/strings/internal/str_format/extension.h" // IWYU pragma: export #include "absl/strings/internal/str_format/parser.h" // IWYU pragma: export +#include "absl/strings/string_view.h" +#include "absl/types/span.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -104,7 +111,8 @@ class UntypedFormatSpec { explicit UntypedFormatSpec(string_view s) : spec_(s) {} protected: - explicit UntypedFormatSpec(const str_format_internal::ParsedFormatBase* pc) + explicit UntypedFormatSpec( + absl::Nonnull<const str_format_internal::ParsedFormatBase*> pc) : spec_(pc) {} private: @@ -144,7 +152,7 @@ str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) { // EXPECT_EQ(8, n); class FormatCountCapture { public: - explicit FormatCountCapture(int* p) : p_(p) {} + explicit FormatCountCapture(absl::Nonnull<int*> p) : p_(p) {} private: // FormatCountCaptureHelper is used to define FormatConvertImpl() for this @@ -153,8 +161,8 @@ class FormatCountCapture { // Unused() is here because of the false positive from -Wunused-private-field // p_ is used in the templated function of the friend FormatCountCaptureHelper // class. - int* Unused() { return p_; } - int* p_; + absl::Nonnull<int*> Unused() { return p_; } + absl::Nonnull<int*> p_; }; // FormatSpec @@ -250,13 +258,13 @@ class FormatCountCapture { // `v` uses `d` for signed integer values, `u` for unsigned integer values, `g` // for floating point values, and formats boolean values as "true"/"false" // (instead of 1 or 0 for booleans formatted using d). `const char*` is not -// supported; please use `std:string` and `string_view`. `char` is also not +// supported; please use `std::string` and `string_view`. `char` is also not // supported due to ambiguity of the type. This specifier does not support // modifiers. // // The `FormatSpec` intrinsically supports all of these fundamental C++ types: // -// * Characters: `char`, `signed char`, `unsigned char` +// * Characters: `char`, `signed char`, `unsigned char`, `wchar_t` // * Integers: `int`, `short`, `unsigned short`, `unsigned`, `long`, // `unsigned long`, `long long`, `unsigned long long` // * Enums: printed as their underlying integral value @@ -264,9 +272,9 @@ class FormatCountCapture { // // However, in the `str_format` library, a format conversion specifies a broader // C++ conceptual category instead of an exact type. For example, `%s` binds to -// any string-like argument, so `std::string`, `absl::string_view`, and -// `const char*` are all accepted. Likewise, `%d` accepts any integer-like -// argument, etc. +// any string-like argument, so `std::string`, `std::wstring`, +// `absl::string_view`, `const char*`, and `const wchar_t*` are all accepted. +// Likewise, `%d` accepts any integer-like argument, etc. template <typename... Args> using FormatSpec = str_format_internal::FormatSpecTemplate< @@ -287,8 +295,8 @@ using FormatSpec = str_format_internal::FormatSpecTemplate< // Example: // // // Verified at compile time. -// absl::ParsedFormat<'s', 'd'> formatString("Welcome to %s, Number %d!"); -// absl::StrFormat(formatString, "TheVillage", 6); +// absl::ParsedFormat<'s', 'd'> format_string("Welcome to %s, Number %d!"); +// absl::StrFormat(format_string, "TheVillage", 6); // // // Verified at runtime. // auto format_runtime = absl::ParsedFormat<'d'>::New(format_string); @@ -369,7 +377,7 @@ ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format, // std::string orig("For example PI is approximately "); // std::cout << StrAppendFormat(&orig, "%12.6f", 3.14); template <typename... Args> -std::string& StrAppendFormat(std::string* dst, +std::string& StrAppendFormat(absl::Nonnull<std::string*> dst, const FormatSpec<Args...>& format, const Args&... args) { return str_format_internal::AppendPack( @@ -381,7 +389,7 @@ std::string& StrAppendFormat(std::string* dst, // // Writes to an output stream given a format string and zero or more arguments, // generally in a manner that is more efficient than streaming the result of -// `absl:: StrFormat()`. The returned object must be streamed before the full +// `absl::StrFormat()`. The returned object must be streamed before the full // expression ends. // // Example: @@ -429,7 +437,7 @@ int PrintF(const FormatSpec<Args...>& format, const Args&... args) { // Outputs: "The capital of Mongolia is Ulaanbaatar" // template <typename... Args> -int FPrintF(std::FILE* output, const FormatSpec<Args...>& format, +int FPrintF(absl::Nonnull<std::FILE*> output, const FormatSpec<Args...>& format, const Args&... args) { return str_format_internal::FprintF( output, str_format_internal::UntypedFormatSpecImpl::Extract(format), @@ -458,8 +466,8 @@ int FPrintF(std::FILE* output, const FormatSpec<Args...>& format, // Post-condition: output == "The capital of Mongolia is Ulaanbaatar" // template <typename... Args> -int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format, - const Args&... args) { +int SNPrintF(absl::Nonnull<char*> output, std::size_t size, + const FormatSpec<Args...>& format, const Args&... args) { return str_format_internal::SnprintF( output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format), {str_format_internal::FormatArgImpl(args)...}); @@ -492,7 +500,7 @@ class FormatRawSink { template <typename T, typename = typename std::enable_if<std::is_constructible< str_format_internal::FormatRawSinkImpl, T*>::value>::type> - FormatRawSink(T* raw) // NOLINT + FormatRawSink(absl::Nonnull<T*> raw) // NOLINT : sink_(raw) {} private: @@ -849,14 +857,16 @@ class FormatSink { } // Support `absl::Format(&sink, format, args...)`. - friend void AbslFormatFlush(FormatSink* sink, absl::string_view v) { + friend void AbslFormatFlush(absl::Nonnull<FormatSink*> sink, + absl::string_view v) { sink->Append(v); } private: friend str_format_internal::FormatSinkImpl; - explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {} - str_format_internal::FormatSinkImpl* sink_; + explicit FormatSink(absl::Nonnull<str_format_internal::FormatSinkImpl*> s) + : sink_(s) {} + absl::Nonnull<str_format_internal::FormatSinkImpl*> sink_; }; // FormatConvertResult diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_join.h b/contrib/restricted/abseil-cpp/absl/strings/str_join.h index ee5ae7efdf..6a92c0f53a 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_join.h +++ b/contrib/restricted/abseil-cpp/absl/strings/str_join.h @@ -80,7 +80,7 @@ ABSL_NAMESPACE_BEGIN // absl::StrJoin(v, ", ", [](std::string* out, absl::Duration dur) { // absl::StrAppend(out, absl::FormatDuration(dur)); // }); -// EXPECT_EQ("1s, 10ms", s); +// EXPECT_EQ(s, "1s, 10ms"); // // The following standard formatters are provided within this file: // @@ -164,21 +164,21 @@ DereferenceFormatter() { // // of `absl::string_view` or even `const char*`. // std::vector<std::string> v = {"foo", "bar", "baz"}; // std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("foo-bar-baz", s); +// EXPECT_EQ(s, "foo-bar-baz"); // // Example 2: // // Joins the values in the given `std::initializer_list<>` specified using // // brace initialization. This pattern also works with an initializer_list // // of ints or `absl::string_view` -- any `AlphaNum`-compatible type. // std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-"); -// EXPECT_EQ("foo-bar-baz", s); +// EXPECT_EQs, "foo-bar-baz"); // // Example 3: // // Joins a collection of ints. This pattern also works with floats, // // doubles, int64s -- any `StrCat()`-compatible type. // std::vector<int> v = {1, 2, 3, -4}; // std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("1-2-3--4", s); +// EXPECT_EQ(s, "1-2-3--4"); // // Example 4: // // Joins a collection of pointer-to-int. By default, pointers are @@ -189,7 +189,7 @@ DereferenceFormatter() { // int x = 1, y = 2, z = 3; // std::vector<int*> v = {&x, &y, &z}; // std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("1-2-3", s); +// EXPECT_EQ(s, "1-2-3"); // // Example 5: // // Dereferencing of `std::unique_ptr<>` is also supported: @@ -198,42 +198,42 @@ DereferenceFormatter() { // v.emplace_back(new int(2)); // v.emplace_back(new int(3)); // std::string s = absl::StrJoin(v, "-"); -// EXPECT_EQ("1-2-3", s); +// EXPECT_EQ(s, "1-2-3"); // // Example 6: // // Joins a `std::map`, with each key-value pair separated by an equals // // sign. This pattern would also work with, say, a // // `std::vector<std::pair<>>`. // std::map<std::string, int> m = { -// std::make_pair("a", 1), -// std::make_pair("b", 2), -// std::make_pair("c", 3)}; +// {"a", 1}, +// {"b", 2}, +// {"c", 3}}; // std::string s = absl::StrJoin(m, ",", absl::PairFormatter("=")); -// EXPECT_EQ("a=1,b=2,c=3", s); +// EXPECT_EQ(s, "a=1,b=2,c=3"); // // Example 7: // // These examples show how `absl::StrJoin()` handles a few common edge // // cases: // std::vector<std::string> v_empty; -// EXPECT_EQ("", absl::StrJoin(v_empty, "-")); +// EXPECT_EQ(absl::StrJoin(v_empty, "-"), ""); // // std::vector<std::string> v_one_item = {"foo"}; -// EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-")); +// EXPECT_EQ(absl::StrJoin(v_one_item, "-"), "foo"); // // std::vector<std::string> v_empty_string = {""}; -// EXPECT_EQ("", absl::StrJoin(v_empty_string, "-")); +// EXPECT_EQ(absl::StrJoin(v_empty_string, "-"), ""); // // std::vector<std::string> v_one_item_empty_string = {"a", ""}; -// EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-")); +// EXPECT_EQ(absl::StrJoin(v_one_item_empty_string, "-"), "a-"); // // std::vector<std::string> v_two_empty_string = {"", ""}; -// EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-")); +// EXPECT_EQ(absl::StrJoin(v_two_empty_string, "-"), "-"); // // Example 8: // // Joins a `std::tuple<T...>` of heterogeneous types, converting each to // // a std::string using the `absl::AlphaNum` class. // std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-"); -// EXPECT_EQ("123-abc-0.456", s); +// EXPECT_EQ(s, "123-abc-0.456"); template <typename Iterator, typename Formatter> std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc b/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc index 2bd5fa9821..a7ab52fed5 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/str_replace.cc @@ -14,7 +14,16 @@ #include "absl/strings/str_replace.h" +#include <cstddef> +#include <initializer_list> +#include <string> +#include <utility> +#include <vector> + +#include "absl/base/config.h" +#include "absl/base/nullability.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -28,8 +37,8 @@ using FixedMapping = // occurred. int ApplySubstitutions( absl::string_view s, - std::vector<strings_internal::ViableSubstitution>* subs_ptr, - std::string* result_ptr) { + absl::Nonnull<std::vector<strings_internal::ViableSubstitution>*> subs_ptr, + absl::Nonnull<std::string*> result_ptr) { auto& subs = *subs_ptr; int substitutions = 0; size_t pos = 0; @@ -74,7 +83,7 @@ std::string StrReplaceAll(absl::string_view s, } int StrReplaceAll(strings_internal::FixedMapping replacements, - std::string* target) { + absl::Nonnull<std::string*> target) { return StrReplaceAll<strings_internal::FixedMapping>(replacements, target); } diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_replace.h b/contrib/restricted/abseil-cpp/absl/strings/str_replace.h index 273c707735..e77ced3e57 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_replace.h +++ b/contrib/restricted/abseil-cpp/absl/strings/str_replace.h @@ -43,6 +43,7 @@ #include <vector> #include "absl/base/attributes.h" +#include "absl/base/nullability.h" #include "absl/strings/string_view.h" namespace absl { @@ -113,7 +114,7 @@ std::string StrReplaceAll(absl::string_view s, int StrReplaceAll( std::initializer_list<std::pair<absl::string_view, absl::string_view>> replacements, - std::string* target); + absl::Nonnull<std::string*> target); // Overload of `StrReplaceAll()` to replace patterns within a given output // string *in place* with replacements provided within a container of key/value @@ -128,7 +129,8 @@ int StrReplaceAll( // EXPECT_EQ(count, 2); // EXPECT_EQ("if (ptr < &foo)", s); template <typename StrToStrMapping> -int StrReplaceAll(const StrToStrMapping& replacements, std::string* target); +int StrReplaceAll(const StrToStrMapping& replacements, + absl::Nonnull<std::string*> target); // Implementation details only, past this point. namespace strings_internal { @@ -185,8 +187,8 @@ std::vector<ViableSubstitution> FindSubstitutions( } int ApplySubstitutions(absl::string_view s, - std::vector<ViableSubstitution>* subs_ptr, - std::string* result_ptr); + absl::Nonnull<std::vector<ViableSubstitution>*> subs_ptr, + absl::Nonnull<std::string*> result_ptr); } // namespace strings_internal @@ -201,7 +203,8 @@ std::string StrReplaceAll(absl::string_view s, } template <typename StrToStrMapping> -int StrReplaceAll(const StrToStrMapping& replacements, std::string* target) { +int StrReplaceAll(const StrToStrMapping& replacements, + absl::Nonnull<std::string*> target) { auto subs = strings_internal::FindSubstitutions(*target, replacements); if (subs.empty()) return 0; diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_split.cc b/contrib/restricted/abseil-cpp/absl/strings/str_split.cc index 72ba7c02df..abe486b915 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_split.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/str_split.cc @@ -15,16 +15,13 @@ #include "absl/strings/str_split.h" #include <algorithm> -#include <cassert> -#include <cstdint> +#include <cstddef> #include <cstdlib> #include <cstring> -#include <iterator> -#include <limits> -#include <memory> +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" -#include "absl/strings/ascii.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -99,6 +96,11 @@ absl::string_view ByString::Find(absl::string_view text, size_t pos) const { return GenericFind(text, delimiter_, pos, LiteralPolicy()); } +absl::string_view ByAsciiWhitespace::Find(absl::string_view text, + size_t pos) const { + return GenericFind(text, " \t\v\f\r\n", pos, AnyOfPolicy()); +} + // // ByChar // diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_split.h b/contrib/restricted/abseil-cpp/absl/strings/str_split.h index 7bbb68a343..87540278ad 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/str_split.h +++ b/contrib/restricted/abseil-cpp/absl/strings/str_split.h @@ -130,6 +130,24 @@ class ByString { const std::string delimiter_; }; +// ByAsciiWhitespace +// +// A sub-string delimiter that splits by ASCII whitespace +// (space, tab, vertical tab, formfeed, linefeed, or carriage return). +// Note: you probably want to use absl::SkipEmpty() as well! +// +// This class is equivalent to ByAnyChar with ASCII whitespace chars. +// +// Example: +// +// std::vector<std::string> v = absl::StrSplit( +// "a b\tc\n d \n", absl::ByAsciiWhitespace(), absl::SkipEmpty()); +// // v[0] == "a", v[1] == "b", v[2] == "c", v[3] == "d" +class ByAsciiWhitespace { + public: + absl::string_view Find(absl::string_view text, size_t pos) const; +}; + // ByChar // // A single character delimiter. `ByChar` is functionally equivalent to a diff --git a/contrib/restricted/abseil-cpp/absl/strings/string_view.cc b/contrib/restricted/abseil-cpp/absl/strings/string_view.cc index f20ff5306e..97025c32a5 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/string_view.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/string_view.cc @@ -21,6 +21,8 @@ #include <cstring> #include <ostream> +#include "absl/base/nullability.h" + namespace absl { ABSL_NAMESPACE_BEGIN @@ -28,8 +30,10 @@ namespace { // This is significantly faster for case-sensitive matches with very // few possible matches. -const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, - size_t neelen) { +absl::Nullable<const char*> memmatch(absl::Nullable<const char*> phaystack, + size_t haylen, + absl::Nullable<const char*> pneedle, + size_t neelen) { if (0 == neelen) { return phaystack; // even if haylen is 0 } @@ -37,8 +41,8 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, const char* match; const char* hayend = phaystack + haylen - neelen + 1; - // A static cast is used here to work around the fact that memchr returns - // a void* on Posix-compliant systems and const void* on Windows. + // A static cast is used here as memchr returns a const void *, and pointer + // arithmetic is not allowed on pointers to void. while ( (match = static_cast<const char*>(memchr( phaystack, pneedle[0], static_cast<size_t>(hayend - phaystack))))) { @@ -229,7 +233,6 @@ string_view::size_type string_view::find_last_not_of( return npos; } - #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL constexpr string_view::size_type string_view::npos; constexpr string_view::size_type string_view::kMaxSize; @@ -238,4 +241,22 @@ constexpr string_view::size_type string_view::kMaxSize; ABSL_NAMESPACE_END } // namespace absl +#else + +// https://github.com/abseil/abseil-cpp/issues/1465 +// CMake builds on Apple platforms error when libraries are empty. +// Our CMake configuration can avoid this error on header-only libraries, +// but since this library is conditionally empty, including a single +// variable is an easy workaround. +#ifdef __APPLE__ +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace strings_internal { +extern const char kAvoidEmptyStringViewLibraryWarning; +const char kAvoidEmptyStringViewLibraryWarning = 0; +} // namespace strings_internal +ABSL_NAMESPACE_END +} // namespace absl +#endif // __APPLE__ + #endif // ABSL_USES_STD_STRING_VIEW diff --git a/contrib/restricted/abseil-cpp/absl/strings/string_view.h b/contrib/restricted/abseil-cpp/absl/strings/string_view.h index eae11b2ab6..04ca0a38ae 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/string_view.h +++ b/contrib/restricted/abseil-cpp/absl/strings/string_view.h @@ -37,6 +37,7 @@ #include <string> #include "absl/base/attributes.h" +#include "absl/base/nullability.h" #include "absl/base/config.h" #include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" @@ -162,11 +163,11 @@ class string_view { public: using traits_type = std::char_traits<char>; using value_type = char; - using pointer = char*; - using const_pointer = const char*; + using pointer = absl::Nullable<char*>; + using const_pointer = absl::Nullable<const char*>; using reference = char&; using const_reference = const char&; - using const_iterator = const char*; + using const_iterator = absl::Nullable<const char*>; using iterator = const_iterator; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using reverse_iterator = const_reverse_iterator; @@ -194,11 +195,12 @@ class string_view { // accepting possibly null strings, use `absl::NullSafeStringView(str)` // instead (see below). // The length check is skipped since it is unnecessary and causes code bloat. - constexpr string_view(const char* str) // NOLINT(runtime/explicit) + constexpr string_view( // NOLINT(runtime/explicit) + absl::Nonnull<const char*> str) : ptr_(str), length_(str ? StrlenInternal(str) : 0) {} // Implicit constructor of a `string_view` from a `const char*` and length. - constexpr string_view(const char* data, size_type len) + constexpr string_view(absl::Nullable<const char*> data, size_type len) : ptr_(data), length_(CheckLengthInternal(len)) {} // NOTE: Harmlessly omitted to work around gdb bug. @@ -427,18 +429,21 @@ class string_view { // Overload of `string_view::compare()` for comparing a `string_view` and a // a different C-style string `s`. - constexpr int compare(const char* s) const { return compare(string_view(s)); } + constexpr int compare(absl::Nonnull<const char*> s) const { + return compare(string_view(s)); + } // Overload of `string_view::compare()` for comparing a substring of the // `string_view` and a different string C-style string `s`. - constexpr int compare(size_type pos1, size_type count1, const char* s) const { + constexpr int compare(size_type pos1, size_type count1, + absl::Nonnull<const char*> s) const { return substr(pos1, count1).compare(string_view(s)); } // Overload of `string_view::compare()` for comparing a substring of the // `string_view` and a substring of a different C-style string `s`. - constexpr int compare(size_type pos1, size_type count1, const char* s, - size_type count2) const { + constexpr int compare(size_type pos1, size_type count1, + absl::Nonnull<const char*> s, size_type count2) const { return substr(pos1, count1).compare(string_view(s, count2)); } @@ -457,13 +462,14 @@ class string_view { // Overload of `string_view::find()` for finding a substring of a different // C-style string `s` within the `string_view`. - size_type find(const char* s, size_type pos, size_type count) const { + size_type find(absl::Nonnull<const char*> s, size_type pos, + size_type count) const { return find(string_view(s, count), pos); } // Overload of `string_view::find()` for finding a different C-style string // `s` within the `string_view`. - size_type find(const char* s, size_type pos = 0) const { + size_type find(absl::Nonnull<const char *> s, size_type pos = 0) const { return find(string_view(s), pos); } @@ -480,13 +486,14 @@ class string_view { // Overload of `string_view::rfind()` for finding a substring of a different // C-style string `s` within the `string_view`. - size_type rfind(const char* s, size_type pos, size_type count) const { + size_type rfind(absl::Nonnull<const char*> s, size_type pos, + size_type count) const { return rfind(string_view(s, count), pos); } // Overload of `string_view::rfind()` for finding a different C-style string // `s` within the `string_view`. - size_type rfind(const char* s, size_type pos = npos) const { + size_type rfind(absl::Nonnull<const char*> s, size_type pos = npos) const { return rfind(string_view(s), pos); } @@ -505,14 +512,15 @@ class string_view { // Overload of `string_view::find_first_of()` for finding a substring of a // different C-style string `s` within the `string_view`. - size_type find_first_of(const char* s, size_type pos, - size_type count) const { + size_type find_first_of(absl::Nonnull<const char*> s, size_type pos, + size_type count) const { return find_first_of(string_view(s, count), pos); } // Overload of `string_view::find_first_of()` for finding a different C-style // string `s` within the `string_view`. - size_type find_first_of(const char* s, size_type pos = 0) const { + size_type find_first_of(absl::Nonnull<const char*> s, + size_type pos = 0) const { return find_first_of(string_view(s), pos); } @@ -531,13 +539,15 @@ class string_view { // Overload of `string_view::find_last_of()` for finding a substring of a // different C-style string `s` within the `string_view`. - size_type find_last_of(const char* s, size_type pos, size_type count) const { + size_type find_last_of(absl::Nonnull<const char*> s, size_type pos, + size_type count) const { return find_last_of(string_view(s, count), pos); } // Overload of `string_view::find_last_of()` for finding a different C-style // string `s` within the `string_view`. - size_type find_last_of(const char* s, size_type pos = npos) const { + size_type find_last_of(absl::Nonnull<const char*> s, + size_type pos = npos) const { return find_last_of(string_view(s), pos); } @@ -554,14 +564,15 @@ class string_view { // Overload of `string_view::find_first_not_of()` for finding a substring of a // different C-style string `s` within the `string_view`. - size_type find_first_not_of(const char* s, size_type pos, + size_type find_first_not_of(absl::Nonnull<const char*> s, size_type pos, size_type count) const { return find_first_not_of(string_view(s, count), pos); } // Overload of `string_view::find_first_not_of()` for finding a different // C-style string `s` within the `string_view`. - size_type find_first_not_of(const char* s, size_type pos = 0) const { + size_type find_first_not_of(absl::Nonnull<const char*> s, + size_type pos = 0) const { return find_first_not_of(string_view(s), pos); } @@ -579,22 +590,76 @@ class string_view { // Overload of `string_view::find_last_not_of()` for finding a substring of a // different C-style string `s` within the `string_view`. - size_type find_last_not_of(const char* s, size_type pos, + size_type find_last_not_of(absl::Nonnull<const char*> s, size_type pos, size_type count) const { return find_last_not_of(string_view(s, count), pos); } // Overload of `string_view::find_last_not_of()` for finding a different // C-style string `s` within the `string_view`. - size_type find_last_not_of(const char* s, size_type pos = npos) const { + size_type find_last_not_of(absl::Nonnull<const char*> s, + size_type pos = npos) const { return find_last_not_of(string_view(s), pos); } +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + // string_view::starts_with() + // + // Returns true if the `string_view` starts with the prefix `s`. + // + // This method only exists when targeting at least C++20. + // If support for C++ prior to C++20 is required, use `absl::StartsWith()` + // from `//absl/strings/match.h` for compatibility. + constexpr bool starts_with(string_view s) const noexcept { + return s.empty() || + (size() >= s.size() && + ABSL_INTERNAL_STRING_VIEW_MEMCMP(data(), s.data(), s.size()) == 0); + } + + // Overload of `string_view::starts_with()` that returns true if `c` is the + // first character of the `string_view`. + constexpr bool starts_with(char c) const noexcept { + return !empty() && front() == c; + } + + // Overload of `string_view::starts_with()` that returns true if the + // `string_view` starts with the C-style prefix `s`. + constexpr bool starts_with(const char* s) const { + return starts_with(string_view(s)); + } + + // string_view::ends_with() + // + // Returns true if the `string_view` ends with the suffix `s`. + // + // This method only exists when targeting at least C++20. + // If support for C++ prior to C++20 is required, use `absl::EndsWith()` + // from `//absl/strings/match.h` for compatibility. + constexpr bool ends_with(string_view s) const noexcept { + return s.empty() || (size() >= s.size() && ABSL_INTERNAL_STRING_VIEW_MEMCMP( + data() + (size() - s.size()), + s.data(), s.size()) == 0); + } + + // Overload of `string_view::ends_with()` that returns true if `c` is the + // last character of the `string_view`. + constexpr bool ends_with(char c) const noexcept { + return !empty() && back() == c; + } + + // Overload of `string_view::ends_with()` that returns true if the + // `string_view` ends with the C-style suffix `s`. + constexpr bool ends_with(const char* s) const { + return ends_with(string_view(s)); + } +#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + private: // The constructor from std::string delegates to this constructor. // See the comment on that constructor for the rationale. struct SkipCheckLengthTag {}; - string_view(const char* data, size_type len, SkipCheckLengthTag) noexcept + string_view(absl::Nullable<const char*> data, size_type len, + SkipCheckLengthTag) noexcept : ptr_(data), length_(len) {} static constexpr size_type kMaxSize = @@ -604,7 +669,7 @@ class string_view { return ABSL_HARDENING_ASSERT(len <= kMaxSize), len; } - static constexpr size_type StrlenInternal(const char* str) { + static constexpr size_type StrlenInternal(absl::Nonnull<const char*> str) { #if defined(_MSC_VER) && _MSC_VER >= 1910 && !defined(__clang__) // MSVC 2017+ can evaluate this at compile-time. const char* begin = str; @@ -633,7 +698,7 @@ class string_view { : (compare_result < 0 ? -1 : 1); } - const char* ptr_; + absl::Nullable<const char*> ptr_; size_type length_; }; @@ -694,7 +759,7 @@ inline string_view ClippedSubstr(string_view s, size_t pos, // Creates an `absl::string_view` from a pointer `p` even if it's null-valued. // This function should be used where an `absl::string_view` can be created from // a possibly-null pointer. -constexpr string_view NullSafeStringView(const char* p) { +constexpr string_view NullSafeStringView(absl::Nullable<const char*> p) { return p ? string_view(p) : string_view(); } diff --git a/contrib/restricted/abseil-cpp/absl/strings/strip.h b/contrib/restricted/abseil-cpp/absl/strings/strip.h index 341e66fc92..e3cda5bac3 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/strip.h +++ b/contrib/restricted/abseil-cpp/absl/strings/strip.h @@ -25,6 +25,7 @@ #include <string> #include "absl/base/macros.h" +#include "absl/base/nullability.h" #include "absl/strings/ascii.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" @@ -43,7 +44,8 @@ ABSL_NAMESPACE_BEGIN // absl::string_view input("abc"); // EXPECT_TRUE(absl::ConsumePrefix(&input, "a")); // EXPECT_EQ(input, "bc"); -inline bool ConsumePrefix(absl::string_view* str, absl::string_view expected) { +inline 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; @@ -59,7 +61,8 @@ inline bool ConsumePrefix(absl::string_view* str, absl::string_view expected) { // absl::string_view input("abcdef"); // EXPECT_TRUE(absl::ConsumeSuffix(&input, "def")); // EXPECT_EQ(input, "abc"); -inline bool ConsumeSuffix(absl::string_view* str, absl::string_view expected) { +inline 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; diff --git a/contrib/restricted/abseil-cpp/absl/strings/substitute.cc b/contrib/restricted/abseil-cpp/absl/strings/substitute.cc index 33a39305db..dd32c75f69 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/substitute.cc +++ b/contrib/restricted/abseil-cpp/absl/strings/substitute.cc @@ -15,20 +15,28 @@ #include "absl/strings/substitute.h" #include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <string> +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" +#include "absl/base/nullability.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" #include "absl/strings/internal/resize_uninitialized.h" +#include "absl/strings/numbers.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace substitute_internal { -void SubstituteAndAppendArray(std::string* output, absl::string_view format, - const absl::string_view* args_array, - size_t num_args) { +void SubstituteAndAppendArray( + absl::Nonnull<std::string*> output, absl::string_view format, + absl::Nullable<const absl::string_view*> args_array, size_t num_args) { // Determine total size needed. size_t size = 0; for (size_t i = 0; i < format.size(); i++) { @@ -97,7 +105,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format, assert(target == output->data() + output->size()); } -Arg::Arg(const void* value) { +Arg::Arg(absl::Nullable<const void*> value) { static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2, "fix sizeof(scratch_)"); if (value == nullptr) { diff --git a/contrib/restricted/abseil-cpp/absl/strings/substitute.h b/contrib/restricted/abseil-cpp/absl/strings/substitute.h index d6a5a690d7..6c7cba4be5 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/substitute.h +++ b/contrib/restricted/abseil-cpp/absl/strings/substitute.h @@ -78,6 +78,7 @@ #include <vector> #include "absl/base/macros.h" +#include "absl/base/nullability.h" #include "absl/base/port.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" @@ -105,7 +106,7 @@ class Arg { // Overloads for string-y things // // Explicitly overload `const char*` so the compiler doesn't cast to `bool`. - Arg(const char* value) // NOLINT(google-explicit-constructor) + Arg(absl::Nullable<const char*> value) // NOLINT(google-explicit-constructor) : piece_(absl::NullSafeStringView(value)) {} template <typename Allocator> Arg( // NOLINT @@ -176,7 +177,7 @@ class Arg { : piece_(value ? "true" : "false") {} template <typename T, typename = typename std::enable_if< - strings_internal::HasAbslStringify<T>::value>::type> + HasAbslStringify<T>::value>::type> Arg( // NOLINT(google-explicit-constructor) const T& v, strings_internal::StringifySink&& sink = {}) : piece_(strings_internal::ExtractStringification(sink, v)) {} @@ -197,14 +198,15 @@ class Arg { // `void*` values, with the exception of `char*`, are printed as // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed. - Arg(const void* value); // NOLINT(google-explicit-constructor) + Arg( // NOLINT(google-explicit-constructor) + absl::Nullable<const void*> value); // Normal enums are already handled by the integer formatters. // This overload matches only scoped enums. template <typename T, typename = typename std::enable_if< std::is_enum<T>{} && !std::is_convertible<T, int>{} && - !strings_internal::HasAbslStringify<T>::value>::type> + !HasAbslStringify<T>::value>::type> Arg(T value) // NOLINT(google-explicit-constructor) : Arg(static_cast<typename std::underlying_type<T>::type>(value)) {} @@ -220,12 +222,12 @@ class Arg { // Internal helper function. Don't call this from outside this implementation. // This interface may change without notice. -void SubstituteAndAppendArray(std::string* output, absl::string_view format, - const absl::string_view* args_array, - size_t num_args); +void SubstituteAndAppendArray( + absl::Nonnull<std::string*> output, absl::string_view format, + absl::Nullable<const absl::string_view*> args_array, size_t num_args); #if defined(ABSL_BAD_CALL_IF) -constexpr int CalculateOneBit(const char* format) { +constexpr int CalculateOneBit(absl::Nonnull<const char*> format) { // Returns: // * 2^N for '$N' when N is in [0-9] // * 0 for correct '$' escaping: '$$'. @@ -234,11 +236,11 @@ constexpr int CalculateOneBit(const char* format) { : (1 << (*format - '0')); } -constexpr const char* SkipNumber(const char* format) { +constexpr const char* SkipNumber(absl::Nonnull<const char*> format) { return !*format ? format : (format + 1); } -constexpr int PlaceholderBitmask(const char* format) { +constexpr int PlaceholderBitmask(absl::Nonnull<const char*> format) { return !*format ? 0 : *format != '$' ? PlaceholderBitmask(format + 1) @@ -271,18 +273,21 @@ constexpr int PlaceholderBitmask(const char* format) { // absl::SubstituteAndAppend(boilerplate, format, args...); // } // -inline void SubstituteAndAppend(std::string* output, absl::string_view format) { +inline void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::string_view format) { substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0); } -inline void SubstituteAndAppend(std::string* output, absl::string_view format, +inline void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::string_view format, const substitute_internal::Arg& a0) { const absl::string_view args[] = {a0.piece()}; substitute_internal::SubstituteAndAppendArray(output, format, args, ABSL_ARRAYSIZE(args)); } -inline void SubstituteAndAppend(std::string* output, absl::string_view format, +inline void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::string_view format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1) { const absl::string_view args[] = {a0.piece(), a1.piece()}; @@ -290,7 +295,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ABSL_ARRAYSIZE(args)); } -inline void SubstituteAndAppend(std::string* output, absl::string_view format, +inline void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::string_view format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) { @@ -299,7 +305,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ABSL_ARRAYSIZE(args)); } -inline void SubstituteAndAppend(std::string* output, absl::string_view format, +inline void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::string_view format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, @@ -310,7 +317,8 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ABSL_ARRAYSIZE(args)); } -inline void SubstituteAndAppend(std::string* output, absl::string_view format, +inline void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::string_view format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, @@ -322,27 +330,23 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, ABSL_ARRAYSIZE(args)); } -inline void SubstituteAndAppend(std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5) { +inline void SubstituteAndAppend( + absl::Nonnull<std::string*> output, absl::string_view format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, + const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, + const substitute_internal::Arg& a4, const substitute_internal::Arg& a5) { const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(), a5.piece()}; substitute_internal::SubstituteAndAppendArray(output, format, args, ABSL_ARRAYSIZE(args)); } -inline void SubstituteAndAppend(std::string* output, absl::string_view format, - const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6) { +inline void SubstituteAndAppend( + absl::Nonnull<std::string*> output, absl::string_view format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, + const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, + const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, + const substitute_internal::Arg& a6) { const absl::string_view args[] = {a0.piece(), a1.piece(), a2.piece(), a3.piece(), a4.piece(), a5.piece(), a6.piece()}; @@ -351,7 +355,7 @@ inline void SubstituteAndAppend(std::string* output, absl::string_view format, } inline void SubstituteAndAppend( - std::string* output, absl::string_view format, + absl::Nonnull<std::string*> output, absl::string_view format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, @@ -364,7 +368,7 @@ inline void SubstituteAndAppend( } inline void SubstituteAndAppend( - std::string* output, absl::string_view format, + absl::Nonnull<std::string*> output, absl::string_view format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, @@ -378,7 +382,7 @@ inline void SubstituteAndAppend( } inline void SubstituteAndAppend( - std::string* output, absl::string_view format, + absl::Nonnull<std::string*> output, absl::string_view format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, @@ -394,14 +398,16 @@ inline void SubstituteAndAppend( #if defined(ABSL_BAD_CALL_IF) // This body of functions catches cases where the number of placeholders // doesn't match the number of data arguments. -void SubstituteAndAppend(std::string* output, const char* format) +void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::Nonnull<const char*> format) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 0, "There were no substitution arguments " "but this format string either has a $[0-9] in it or contains " "an unescaped $ character (use $$ instead)"); -void SubstituteAndAppend(std::string* output, const char* format, +void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0) ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1, "There was 1 substitution argument given, but " @@ -409,7 +415,8 @@ void SubstituteAndAppend(std::string* output, const char* format, "one of $1-$9, or contains an unescaped $ character (use " "$$ instead)"); -void SubstituteAndAppend(std::string* output, const char* format, +void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1) ABSL_BAD_CALL_IF( @@ -418,7 +425,8 @@ void SubstituteAndAppend(std::string* output, const char* format, "missing its $0/$1, contains one of $2-$9, or contains an " "unescaped $ character (use $$ instead)"); -void SubstituteAndAppend(std::string* output, const char* format, +void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) @@ -428,7 +436,8 @@ void SubstituteAndAppend(std::string* output, const char* format, "this format string is missing its $0/$1/$2, contains one of " "$3-$9, or contains an unescaped $ character (use $$ instead)"); -void SubstituteAndAppend(std::string* output, const char* format, +void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, @@ -439,7 +448,8 @@ void SubstituteAndAppend(std::string* output, const char* format, "this format string is missing its $0-$3, contains one of " "$4-$9, or contains an unescaped $ character (use $$ instead)"); -void SubstituteAndAppend(std::string* output, const char* format, +void SubstituteAndAppend(absl::Nonnull<std::string*> output, + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, @@ -451,13 +461,11 @@ void SubstituteAndAppend(std::string* output, const char* format, "this format string is missing its $0-$4, contains one of " "$5-$9, or contains an unescaped $ character (use $$ instead)"); -void SubstituteAndAppend(std::string* output, const char* format, - const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5) +void SubstituteAndAppend( + absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, + const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, + const substitute_internal::Arg& a4, const substitute_internal::Arg& a5) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 63, "There were 6 substitution arguments given, but " @@ -465,10 +473,11 @@ void SubstituteAndAppend(std::string* output, const char* format, "$6-$9, or contains an unescaped $ character (use $$ instead)"); void SubstituteAndAppend( - std::string* output, const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) + absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, + const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, + const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, + const substitute_internal::Arg& a6) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 127, "There were 7 substitution arguments given, but " @@ -476,11 +485,11 @@ void SubstituteAndAppend( "$7-$9, or contains an unescaped $ character (use $$ instead)"); void SubstituteAndAppend( - std::string* output, const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7) + absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, + const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, + const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, + const substitute_internal::Arg& a6, const substitute_internal::Arg& a7) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 255, "There were 8 substitution arguments given, but " @@ -488,11 +497,12 @@ void SubstituteAndAppend( "$8-$9, or contains an unescaped $ character (use $$ instead)"); void SubstituteAndAppend( - std::string* output, const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7, const substitute_internal::Arg& a8) + absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, + const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, + const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, + const substitute_internal::Arg& a6, const substitute_internal::Arg& a7, + const substitute_internal::Arg& a8) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 511, "There were 9 substitution arguments given, but " @@ -500,12 +510,12 @@ void SubstituteAndAppend( "contains an unescaped $ character (use $$ instead)"); void SubstituteAndAppend( - std::string* output, const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7, const substitute_internal::Arg& a8, - const substitute_internal::Arg& a9) + absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, + const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, + const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, + const substitute_internal::Arg& a6, const substitute_internal::Arg& a7, + const substitute_internal::Arg& a8, const substitute_internal::Arg& a9) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 1023, "There were 10 substitution arguments given, but this " @@ -633,20 +643,22 @@ ABSL_MUST_USE_RESULT inline std::string Substitute( #if defined(ABSL_BAD_CALL_IF) // This body of functions catches cases where the number of placeholders // doesn't match the number of data arguments. -std::string Substitute(const char* format) +std::string Substitute(absl::Nonnull<const char*> format) ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0, "There were no substitution arguments " "but this format string either has a $[0-9] in it or " "contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0) +std::string Substitute(absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 1, "There was 1 substitution argument given, but " "this format string is missing its $0, contains one of $1-$9, " "or contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0, +std::string Substitute(absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 3, @@ -654,7 +666,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, "this format string is missing its $0/$1, contains one of " "$2-$9, or contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0, +std::string Substitute(absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) ABSL_BAD_CALL_IF( @@ -663,7 +676,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, "this format string is missing its $0/$1/$2, contains one of " "$3-$9, or contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0, +std::string Substitute(absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3) @@ -673,7 +687,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, "this format string is missing its $0-$3, contains one of " "$4-$9, or contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0, +std::string Substitute(absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, @@ -684,7 +699,8 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, "this format string is missing its $0-$4, contains one of " "$5-$9, or contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0, +std::string Substitute(absl::Nonnull<const char*> format, + const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, @@ -696,27 +712,23 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, "this format string is missing its $0-$5, contains one of " "$6-$9, or contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6) +std::string Substitute( + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, + const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, + const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, + const substitute_internal::Arg& a5, const substitute_internal::Arg& a6) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 127, "There were 7 substitution arguments given, but " "this format string is missing its $0-$6, contains one of " "$7-$9, or contains an unescaped $ character (use $$ instead)"); -std::string Substitute(const char* format, const substitute_internal::Arg& a0, - const substitute_internal::Arg& a1, - const substitute_internal::Arg& a2, - const substitute_internal::Arg& a3, - const substitute_internal::Arg& a4, - const substitute_internal::Arg& a5, - const substitute_internal::Arg& a6, - const substitute_internal::Arg& a7) +std::string Substitute( + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, + const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, + const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, + const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, + const substitute_internal::Arg& a7) ABSL_BAD_CALL_IF( substitute_internal::PlaceholderBitmask(format) != 255, "There were 8 substitution arguments given, but " @@ -724,7 +736,7 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0, "$8-$9, or contains an unescaped $ character (use $$ instead)"); std::string Substitute( - const char* format, const substitute_internal::Arg& a0, + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, @@ -736,7 +748,7 @@ std::string Substitute( "contains an unescaped $ character (use $$ instead)"); std::string Substitute( - const char* format, const substitute_internal::Arg& a0, + absl::Nonnull<const char*> format, const substitute_internal::Arg& a0, const substitute_internal::Arg& a1, const substitute_internal::Arg& a2, const substitute_internal::Arg& a3, const substitute_internal::Arg& a4, const substitute_internal::Arg& a5, const substitute_internal::Arg& a6, diff --git a/contrib/restricted/abseil-cpp/absl/strings/ya.make b/contrib/restricted/abseil-cpp/absl/strings/ya.make index 99b03d7bd6..dffec44d18 100644 --- a/contrib/restricted/abseil-cpp/absl/strings/ya.make +++ b/contrib/restricted/abseil-cpp/absl/strings/ya.make @@ -27,7 +27,7 @@ SRCS( crc/internal/crc.cc crc/internal/crc_cord_state.cc crc/internal/crc_memcpy_fallback.cc - crc/internal/crc_memcpy_x86_64.cc + crc/internal/crc_memcpy_x86_arm_combined.cc crc/internal/crc_non_temporal_memcpy.cc crc/internal/crc_x86_arm_combined.cc status/statusor.cc @@ -45,7 +45,6 @@ SRCS( strings/internal/cord_rep_btree_reader.cc strings/internal/cord_rep_consume.cc strings/internal/cord_rep_crc.cc - strings/internal/cord_rep_ring.cc strings/internal/cordz_functions.cc strings/internal/cordz_handle.cc strings/internal/cordz_info.cc diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/internal/pthread_waiter.h b/contrib/restricted/abseil-cpp/absl/synchronization/internal/pthread_waiter.h index 206aefa47c..23db76ad44 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/internal/pthread_waiter.h +++ b/contrib/restricted/abseil-cpp/absl/synchronization/internal/pthread_waiter.h @@ -16,7 +16,7 @@ #ifndef ABSL_SYNCHRONIZATION_INTERNAL_PTHREAD_WAITER_H_ #define ABSL_SYNCHRONIZATION_INTERNAL_PTHREAD_WAITER_H_ -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__MINGW32__) #include <pthread.h> #include "absl/base/config.h" @@ -55,6 +55,6 @@ class PthreadWaiter : public WaiterCrtp<PthreadWaiter> { ABSL_NAMESPACE_END } // namespace absl -#endif // ndef _WIN32 +#endif // !defined(_WIN32) && !defined(__MINGW32__) #endif // ABSL_SYNCHRONIZATION_INTERNAL_PTHREAD_WAITER_H_ diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/internal/win32_waiter.h b/contrib/restricted/abseil-cpp/absl/synchronization/internal/win32_waiter.h index 87eb617cbd..fdab264e8c 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/internal/win32_waiter.h +++ b/contrib/restricted/abseil-cpp/absl/synchronization/internal/win32_waiter.h @@ -20,7 +20,8 @@ #include <sdkddkver.h> #endif -#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#if defined(_WIN32) && !defined(__MINGW32__) && \ + _WIN32_WINNT >= _WIN32_WINNT_VISTA #include "absl/base/config.h" #include "absl/synchronization/internal/kernel_timeout.h" @@ -65,6 +66,7 @@ class Win32Waiter : public WaiterCrtp<Win32Waiter> { ABSL_NAMESPACE_END } // namespace absl -#endif // defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#endif // defined(_WIN32) && !defined(__MINGW32__) && + // _WIN32_WINNT >= _WIN32_WINNT_VISTA #endif // ABSL_SYNCHRONIZATION_INTERNAL_WIN32_WAITER_H_ diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc index 3aa5560a32..cb3c7e74ec 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc +++ b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc @@ -129,11 +129,15 @@ enum DelayMode { AGGRESSIVE, GENTLE }; struct ABSL_CACHELINE_ALIGNED MutexGlobals { absl::once_flag once; - int spinloop_iterations = 0; + // Note: this variable is initialized separately in Mutex::LockSlow, + // so that Mutex::Lock does not have a stack frame in optimized build. + std::atomic<int> spinloop_iterations{0}; int32_t mutex_sleep_spins[2] = {}; absl::Duration mutex_sleep_time; }; +ABSL_CONST_INIT static MutexGlobals globals; + absl::Duration MeasureTimeToYield() { absl::Time before = absl::Now(); ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)(); @@ -141,33 +145,30 @@ absl::Duration MeasureTimeToYield() { } const MutexGlobals& GetMutexGlobals() { - ABSL_CONST_INIT static MutexGlobals data; - absl::base_internal::LowLevelCallOnce(&data.once, [&]() { + absl::base_internal::LowLevelCallOnce(&globals.once, [&]() { if (absl::base_internal::NumCPUs() > 1) { - // If this is multiprocessor, allow spinning. If the mode is - // aggressive then spin many times before yielding. If the mode is - // gentle then spin only a few times before yielding. Aggressive spinning - // is used to ensure that an Unlock() call, which must get the spin lock - // for any thread to make progress gets it without undue delay. - data.spinloop_iterations = 1500; - data.mutex_sleep_spins[AGGRESSIVE] = 5000; - data.mutex_sleep_spins[GENTLE] = 250; - data.mutex_sleep_time = absl::Microseconds(10); + // If the mode is aggressive then spin many times before yielding. + // If the mode is gentle then spin only a few times before yielding. + // Aggressive spinning is used to ensure that an Unlock() call, + // which must get the spin lock for any thread to make progress gets it + // without undue delay. + globals.mutex_sleep_spins[AGGRESSIVE] = 5000; + globals.mutex_sleep_spins[GENTLE] = 250; + globals.mutex_sleep_time = absl::Microseconds(10); } else { // If this a uniprocessor, only yield/sleep. Real-time threads are often // unable to yield, so the sleep time needs to be long enough to keep // the calling thread asleep until scheduling happens. - data.spinloop_iterations = 0; - data.mutex_sleep_spins[AGGRESSIVE] = 0; - data.mutex_sleep_spins[GENTLE] = 0; - data.mutex_sleep_time = MeasureTimeToYield() * 5; - data.mutex_sleep_time = - std::min(data.mutex_sleep_time, absl::Milliseconds(1)); - data.mutex_sleep_time = - std::max(data.mutex_sleep_time, absl::Microseconds(10)); + globals.mutex_sleep_spins[AGGRESSIVE] = 0; + globals.mutex_sleep_spins[GENTLE] = 0; + globals.mutex_sleep_time = MeasureTimeToYield() * 5; + globals.mutex_sleep_time = + std::min(globals.mutex_sleep_time, absl::Milliseconds(1)); + globals.mutex_sleep_time = + std::max(globals.mutex_sleep_time, absl::Microseconds(10)); } }); - return data; + return globals; } } // namespace @@ -202,31 +203,23 @@ int MutexDelay(int32_t c, int mode) { // Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to // "*pv | bits" if necessary. Wait until (*pv & wait_until_clear)==0 // before making any change. +// Returns true if bits were previously unset and set by the call. // This is used to set flags in mutex and condition variable words. -static void AtomicSetBits(std::atomic<intptr_t>* pv, intptr_t bits, +static bool AtomicSetBits(std::atomic<intptr_t>* pv, intptr_t bits, intptr_t wait_until_clear) { - intptr_t v; - do { - v = pv->load(std::memory_order_relaxed); - } while ((v & bits) != bits && - ((v & wait_until_clear) != 0 || - !pv->compare_exchange_weak(v, v | bits, std::memory_order_release, - std::memory_order_relaxed))); -} - -// Ensure that "(*pv & bits) == 0" by doing an atomic update of "*pv" to -// "*pv & ~bits" if necessary. Wait until (*pv & wait_until_clear)==0 -// before making any change. -// This is used to unset flags in mutex and condition variable words. -static void AtomicClearBits(std::atomic<intptr_t>* pv, intptr_t bits, - intptr_t wait_until_clear) { - intptr_t v; - do { - v = pv->load(std::memory_order_relaxed); - } while ((v & bits) != 0 && - ((v & wait_until_clear) != 0 || - !pv->compare_exchange_weak(v, v & ~bits, std::memory_order_release, - std::memory_order_relaxed))); + for (;;) { + intptr_t v = pv->load(std::memory_order_relaxed); + if ((v & bits) == bits) { + return false; + } + if ((v & wait_until_clear) != 0) { + continue; + } + if (pv->compare_exchange_weak(v, v | bits, std::memory_order_release, + std::memory_order_relaxed)) { + return true; + } + } } //------------------------------------------------------------------ @@ -337,12 +330,49 @@ static SynchEvent* EnsureSynchEvent(std::atomic<intptr_t>* addr, const char* name, intptr_t bits, intptr_t lockbit) { uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent; - SynchEvent* e; - // first look for existing SynchEvent struct.. synch_event_mu.Lock(); - for (e = synch_event[h]; - e != nullptr && e->masked_addr != base_internal::HidePtr(addr); - e = e->next) { + // When a Mutex/CondVar is destroyed, we don't remove the associated + // SynchEvent to keep destructors empty in release builds for performance + // reasons. If the current call is the first to set bits (kMuEvent/kCVEvent), + // we don't look up the existing even because (if it exists, it must be for + // the previous Mutex/CondVar that existed at the same address). + // The leaking events must not be a problem for tests, which should create + // bounded amount of events. And debug logging is not supposed to be enabled + // in production. However, if it's accidentally enabled, or briefly enabled + // for some debugging, we don't want to crash the program. Instead we drop + // all events, if we accumulated too many of them. Size of a single event + // is ~48 bytes, so 100K events is ~5 MB. + // Additionally we could delete the old event for the same address, + // but it would require a better hashmap (if we accumulate too many events, + // linked lists will grow and traversing them will be very slow). + constexpr size_t kMaxSynchEventCount = 100 << 10; + // Total number of live synch events. + static size_t synch_event_count ABSL_GUARDED_BY(synch_event_mu); + if (++synch_event_count > kMaxSynchEventCount) { + synch_event_count = 0; + ABSL_RAW_LOG(ERROR, + "Accumulated %zu Mutex debug objects. If you see this" + " in production, it may mean that the production code" + " accidentally calls " + "Mutex/CondVar::EnableDebugLog/EnableInvariantDebugging.", + kMaxSynchEventCount); + for (auto*& head : synch_event) { + for (auto* e = head; e != nullptr;) { + SynchEvent* next = e->next; + if (--(e->refcount) == 0) { + base_internal::LowLevelAlloc::Free(e); + } + e = next; + } + head = nullptr; + } + } + SynchEvent* e = nullptr; + if (!AtomicSetBits(addr, bits, lockbit)) { + for (e = synch_event[h]; + e != nullptr && e->masked_addr != base_internal::HidePtr(addr); + e = e->next) { + } } if (e == nullptr) { // no SynchEvent struct found; make one. if (name == nullptr) { @@ -358,7 +388,6 @@ static SynchEvent* EnsureSynchEvent(std::atomic<intptr_t>* addr, e->log = false; strcpy(e->name, name); // NOLINT(runtime/printf) e->next = synch_event[h]; - AtomicSetBits(addr, bits, lockbit); synch_event[h] = e; } else { e->refcount++; // for return value @@ -367,11 +396,6 @@ static SynchEvent* EnsureSynchEvent(std::atomic<intptr_t>* addr, return e; } -// Deallocate the SynchEvent *e, whose refcount has fallen to zero. -static void DeleteSynchEvent(SynchEvent* e) { - base_internal::LowLevelAlloc::Free(e); -} - // Decrement the reference count of *e, or do nothing if e==null. static void UnrefSynchEvent(SynchEvent* e) { if (e != nullptr) { @@ -379,36 +403,11 @@ static void UnrefSynchEvent(SynchEvent* e) { bool del = (--(e->refcount) == 0); synch_event_mu.Unlock(); if (del) { - DeleteSynchEvent(e); + base_internal::LowLevelAlloc::Free(e); } } } -// Forget the mapping from the object (Mutex or CondVar) at address addr -// to SynchEvent object, and clear "bits" in its word (waiting until lockbit -// is clear before doing so). -static void ForgetSynchEvent(std::atomic<intptr_t>* addr, intptr_t bits, - intptr_t lockbit) { - uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent; - SynchEvent** pe; - SynchEvent* e; - synch_event_mu.Lock(); - for (pe = &synch_event[h]; - (e = *pe) != nullptr && e->masked_addr != base_internal::HidePtr(addr); - pe = &e->next) { - } - bool del = false; - if (e != nullptr) { - *pe = e->next; - del = (--(e->refcount) == 0); - } - AtomicClearBits(addr, bits, lockbit); - synch_event_mu.Unlock(); - if (del) { - DeleteSynchEvent(e); - } -} - // Return a refcounted reference to the SynchEvent of the object at address // "addr", if any. The pointer returned is valid until the UnrefSynchEvent() is // called. @@ -579,31 +578,25 @@ static SynchLocksHeld* Synch_GetAllLocks() { // Post on "w"'s associated PerThreadSem. void Mutex::IncrementSynchSem(Mutex* mu, PerThreadSynch* w) { - if (mu) { - ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); - // We miss synchronization around passing PerThreadSynch between threads - // since it happens inside of the Mutex code, so we need to ignore all - // accesses to the object. - ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); - PerThreadSem::Post(w->thread_identity()); - ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); - ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); - } else { - PerThreadSem::Post(w->thread_identity()); - } + static_cast<void>(mu); // Prevent unused param warning in non-TSAN builds. + ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); + // We miss synchronization around passing PerThreadSynch between threads + // since it happens inside of the Mutex code, so we need to ignore all + // accesses to the object. + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); + PerThreadSem::Post(w->thread_identity()); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); + ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); } // Wait on "w"'s associated PerThreadSem; returns false if timeout expired. bool Mutex::DecrementSynchSem(Mutex* mu, PerThreadSynch* w, KernelTimeout t) { - if (mu) { - ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); - } + static_cast<void>(mu); // Prevent unused param warning in non-TSAN builds. + ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); assert(w == Synch_GetPerThread()); static_cast<void>(w); bool res = PerThreadSem::Wait(t); - if (mu) { - ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); - } + ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); return res; } @@ -682,6 +675,7 @@ static const intptr_t kMuOne = 0x0100; // a count of one reader // flags passed to Enqueue and LockSlow{,WithTimeout,Loop} static const int kMuHasBlocked = 0x01; // already blocked (MUST == 1) static const int kMuIsCond = 0x02; // conditional waiter (CV or Condition) +static const int kMuIsFer = 0x04; // wait morphing from a CondVar static_assert(PerThreadSynch::kAlignment > kMuLow, "PerThreadSynch::kAlignment must be greater than kMuLow"); @@ -737,25 +731,43 @@ static unsigned TsanFlags(Mutex::MuHow how) { } #endif -static bool DebugOnlyIsExiting() { - return false; -} +#if defined(__APPLE__) || defined(ABSL_BUILD_DLL) +// When building a dll symbol export lists may reference the destructor +// and want it to be an exported symbol rather than an inline function. +// Some apple builds also do dynamic library build but don't say it explicitly. +Mutex::~Mutex() { Dtor(); } +#endif -Mutex::~Mutex() { - intptr_t v = mu_.load(std::memory_order_relaxed); - if ((v & kMuEvent) != 0 && !DebugOnlyIsExiting()) { - ForgetSynchEvent(&this->mu_, kMuEvent, kMuSpin); - } +#if !defined(NDEBUG) || defined(ABSL_HAVE_THREAD_SANITIZER) +void Mutex::Dtor() { if (kDebugMode) { this->ForgetDeadlockInfo(); } ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); } +#endif void Mutex::EnableDebugLog(const char* name) { + // Need to disable writes here and in EnableInvariantDebugging to prevent + // false race reports on SynchEvent objects. TSan ignores synchronization + // on synch_event_mu in Lock/Unlock/etc methods due to mutex annotations, + // but it sees few accesses to SynchEvent in EvalConditionAnnotated. + // If we don't ignore accesses here, it can result in false races + // between EvalConditionAnnotated and SynchEvent reuse in EnsureSynchEvent. + ABSL_ANNOTATE_IGNORE_WRITES_BEGIN(); SynchEvent* e = EnsureSynchEvent(&this->mu_, name, kMuEvent, kMuSpin); e->log = true; UnrefSynchEvent(e); + // This prevents "error: undefined symbol: absl::Mutex::~Mutex()" + // in a release build (NDEBUG defined) when a test does "#undef NDEBUG" + // to use assert macro. In such case, the test does not get the dtor + // definition because it's supposed to be outline when NDEBUG is not defined, + // and this source file does not define one either because NDEBUG is defined. + // Since it's not possible to take address of a destructor, we move the + // actual destructor code into the separate Dtor function and force the + // compiler to emit this function even if it's inline by taking its address. + ABSL_ATTRIBUTE_UNUSED volatile auto dtor = &Mutex::Dtor; + ABSL_ANNOTATE_IGNORE_WRITES_END(); } void EnableMutexInvariantDebugging(bool enabled) { @@ -763,6 +775,7 @@ void EnableMutexInvariantDebugging(bool enabled) { } void Mutex::EnableInvariantDebugging(void (*invariant)(void*), void* arg) { + ABSL_ANNOTATE_IGNORE_WRITES_BEGIN(); if (synch_check_invariants.load(std::memory_order_acquire) && invariant != nullptr) { SynchEvent* e = EnsureSynchEvent(&this->mu_, nullptr, kMuEvent, kMuSpin); @@ -770,6 +783,7 @@ void Mutex::EnableInvariantDebugging(void (*invariant)(void*), void* arg) { e->arg = arg; UnrefSynchEvent(e); } + ABSL_ANNOTATE_IGNORE_WRITES_END(); } void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode) { @@ -920,20 +934,23 @@ static PerThreadSynch* Enqueue(PerThreadSynch* head, SynchWaitParams* waitp, s->wake = false; // not being woken s->cond_waiter = ((flags & kMuIsCond) != 0); #ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM - int64_t now_cycles = CycleClock::Now(); - if (s->next_priority_read_cycles < now_cycles) { - // Every so often, update our idea of the thread's priority. - // pthread_getschedparam() is 5% of the block/wakeup time; - // CycleClock::Now() is 0.5%. - int policy; - struct sched_param param; - const int err = pthread_getschedparam(pthread_self(), &policy, ¶m); - if (err != 0) { - ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err); - } else { - s->priority = param.sched_priority; - s->next_priority_read_cycles = - now_cycles + static_cast<int64_t>(CycleClock::Frequency()); + if ((flags & kMuIsFer) == 0) { + assert(s == Synch_GetPerThread()); + int64_t now_cycles = CycleClock::Now(); + if (s->next_priority_read_cycles < now_cycles) { + // Every so often, update our idea of the thread's priority. + // pthread_getschedparam() is 5% of the block/wakeup time; + // CycleClock::Now() is 0.5%. + int policy; + struct sched_param param; + const int err = pthread_getschedparam(pthread_self(), &policy, ¶m); + if (err != 0) { + ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err); + } else { + s->priority = param.sched_priority; + s->next_priority_read_cycles = + now_cycles + static_cast<int64_t>(CycleClock::Frequency()); + } } } #endif @@ -962,8 +979,7 @@ static PerThreadSynch* Enqueue(PerThreadSynch* head, SynchWaitParams* waitp, } while (s->priority <= advance_to->priority); // termination guaranteed because s->priority > head->priority // and head is the end of a skip chain - } else if (waitp->how == kExclusive && - Condition::GuaranteedEqual(waitp->cond, nullptr)) { + } else if (waitp->how == kExclusive && waitp->cond == nullptr) { // An unlocker could be scanning the queue, but we know it will recheck // the queue front for writers that have no condition, which is what s // is, so an insert at front is safe. @@ -994,6 +1010,24 @@ static PerThreadSynch* Enqueue(PerThreadSynch* head, SynchWaitParams* waitp, if (MuEquivalentWaiter(s, s->next)) { // s->may_skip is known to be true s->skip = s->next; // s may skip to its successor } + } else if ((flags & kMuHasBlocked) && + (s->priority >= head->next->priority) && + (!head->maybe_unlocking || + (waitp->how == kExclusive && + Condition::GuaranteedEqual(waitp->cond, nullptr)))) { + // This thread has already waited, then was woken, then failed to acquire + // the mutex and now tries to requeue. Try to requeue it at head, + // otherwise it can suffer bad latency (wait whole queue several times). + // However, we need to be conservative. First, we need to ensure that we + // respect priorities. Then, we need to be careful to not break wait + // queue invariants: we require either that unlocker is not scanning + // the queue or that the current thread is a writer with no condition + // (unlocker will recheck the queue for such waiters). + s->next = head->next; + head->next = s; + if (MuEquivalentWaiter(s, s->next)) { // s->may_skip is known to be true + s->skip = s->next; // s may skip to its successor + } } else { // enqueue not done any other way, so // we're inserting s at the back // s will become new head; copy data from head into it @@ -1472,7 +1506,7 @@ void Mutex::AssertNotHeld() const { // Attempt to acquire *mu, and return whether successful. The implementation // may spin for a short while if the lock cannot be acquired immediately. static bool TryAcquireWithSpinning(std::atomic<intptr_t>* mu) { - int c = GetMutexGlobals().spinloop_iterations; + int c = globals.spinloop_iterations.load(std::memory_order_relaxed); do { // do/while somewhat faster on AMD intptr_t v = mu->load(std::memory_order_relaxed); if ((v & (kMuReader | kMuEvent)) != 0) { @@ -1492,11 +1526,12 @@ void Mutex::Lock() { GraphId id = DebugOnlyDeadlockCheck(this); intptr_t v = mu_.load(std::memory_order_relaxed); // try fast acquire, then spin loop - if ((v & (kMuWriter | kMuReader | kMuEvent)) != 0 || - !mu_.compare_exchange_strong(v, kMuWriter | v, std::memory_order_acquire, - std::memory_order_relaxed)) { + if (ABSL_PREDICT_FALSE((v & (kMuWriter | kMuReader | kMuEvent)) != 0) || + ABSL_PREDICT_FALSE(!mu_.compare_exchange_strong( + v, kMuWriter | v, std::memory_order_acquire, + std::memory_order_relaxed))) { // try spin acquire, then slow loop - if (!TryAcquireWithSpinning(&this->mu_)) { + if (ABSL_PREDICT_FALSE(!TryAcquireWithSpinning(&this->mu_))) { this->LockSlow(kExclusive, nullptr, 0); } } @@ -1508,159 +1543,95 @@ void Mutex::ReaderLock() { ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); GraphId id = DebugOnlyDeadlockCheck(this); intptr_t v = mu_.load(std::memory_order_relaxed); - // try fast acquire, then slow loop - if ((v & (kMuWriter | kMuWait | kMuEvent)) != 0 || - !mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne, - std::memory_order_acquire, - std::memory_order_relaxed)) { - this->LockSlow(kShared, nullptr, 0); + for (;;) { + // If there are non-readers holding the lock, use the slow loop. + if (ABSL_PREDICT_FALSE(v & (kMuWriter | kMuWait | kMuEvent)) != 0) { + this->LockSlow(kShared, nullptr, 0); + break; + } + // We can avoid the loop and only use the CAS when the lock is free or + // only held by readers. + if (ABSL_PREDICT_TRUE(mu_.compare_exchange_weak( + v, (kMuReader | v) + kMuOne, std::memory_order_acquire, + std::memory_order_relaxed))) { + break; + } } DebugOnlyLockEnter(this, id); ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0); } -void Mutex::LockWhen(const Condition& cond) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); - GraphId id = DebugOnlyDeadlockCheck(this); - this->LockSlow(kExclusive, &cond, 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); -} - -bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); - GraphId id = DebugOnlyDeadlockCheck(this); - bool res = LockSlowWithDeadline(kExclusive, &cond, KernelTimeout(timeout), 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); - return res; -} - -bool Mutex::LockWhenWithDeadline(const Condition& cond, absl::Time deadline) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, 0); - GraphId id = DebugOnlyDeadlockCheck(this); - bool res = - LockSlowWithDeadline(kExclusive, &cond, KernelTimeout(deadline), 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0); - return res; -} - -void Mutex::ReaderLockWhen(const Condition& cond) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); - GraphId id = DebugOnlyDeadlockCheck(this); - this->LockSlow(kShared, &cond, 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0); -} - -bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond, - absl::Duration timeout) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); - GraphId id = DebugOnlyDeadlockCheck(this); - bool res = LockSlowWithDeadline(kShared, &cond, KernelTimeout(timeout), 0); - DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0); - return res; -} - -bool Mutex::ReaderLockWhenWithDeadline(const Condition& cond, - absl::Time deadline) { - ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock); +bool Mutex::LockWhenCommon(const Condition& cond, + synchronization_internal::KernelTimeout t, + bool write) { + MuHow how = write ? kExclusive : kShared; + ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how)); GraphId id = DebugOnlyDeadlockCheck(this); - bool res = LockSlowWithDeadline(kShared, &cond, KernelTimeout(deadline), 0); + bool res = LockSlowWithDeadline(how, &cond, t, 0); DebugOnlyLockEnter(this, id); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0); + ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0); return res; } -void Mutex::Await(const Condition& cond) { - if (cond.Eval()) { // condition already true; nothing to do - if (kDebugMode) { - this->AssertReaderHeld(); - } - } else { // normal case - ABSL_RAW_CHECK(this->AwaitCommon(cond, KernelTimeout::Never()), - "condition untrue on return from Await"); - } -} - -bool Mutex::AwaitWithTimeout(const Condition& cond, absl::Duration timeout) { - if (cond.Eval()) { // condition already true; nothing to do - if (kDebugMode) { - this->AssertReaderHeld(); - } - return true; +bool Mutex::AwaitCommon(const Condition& cond, KernelTimeout t) { + if (kDebugMode) { + this->AssertReaderHeld(); } - - KernelTimeout t{timeout}; - bool res = this->AwaitCommon(cond, t); - ABSL_RAW_CHECK(res || t.has_timeout(), - "condition untrue on return from Await"); - return res; -} - -bool Mutex::AwaitWithDeadline(const Condition& cond, absl::Time deadline) { if (cond.Eval()) { // condition already true; nothing to do - if (kDebugMode) { - this->AssertReaderHeld(); - } return true; } - - KernelTimeout t{deadline}; - bool res = this->AwaitCommon(cond, t); - ABSL_RAW_CHECK(res || t.has_timeout(), - "condition untrue on return from Await"); - return res; -} - -bool Mutex::AwaitCommon(const Condition& cond, KernelTimeout t) { - this->AssertReaderHeld(); MuHow how = (mu_.load(std::memory_order_relaxed) & kMuWriter) ? kExclusive : kShared; ABSL_TSAN_MUTEX_PRE_UNLOCK(this, TsanFlags(how)); SynchWaitParams waitp(how, &cond, t, nullptr /*no cvmu*/, Synch_GetPerThreadAnnotated(this), nullptr /*no cv_word*/); - int flags = kMuHasBlocked; - if (!Condition::GuaranteedEqual(&cond, nullptr)) { - flags |= kMuIsCond; - } this->UnlockSlow(&waitp); this->Block(waitp.thread); ABSL_TSAN_MUTEX_POST_UNLOCK(this, TsanFlags(how)); ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how)); - this->LockSlowLoop(&waitp, flags); + this->LockSlowLoop(&waitp, kMuHasBlocked | kMuIsCond); bool res = waitp.cond != nullptr || // => cond known true from LockSlowLoop EvalConditionAnnotated(&cond, this, true, false, how == kShared); ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0); + ABSL_RAW_CHECK(res || t.has_timeout(), + "condition untrue on return from Await"); return res; } bool Mutex::TryLock() { ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock); intptr_t v = mu_.load(std::memory_order_relaxed); - if ((v & (kMuWriter | kMuReader | kMuEvent)) == 0 && // try fast acquire - mu_.compare_exchange_strong(v, kMuWriter | v, std::memory_order_acquire, - std::memory_order_relaxed)) { - DebugOnlyLockEnter(this); - ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0); - return true; - } - if ((v & kMuEvent) != 0) { // we're recording events - if ((v & kExclusive->slow_need_zero) == 0 && // try fast acquire - mu_.compare_exchange_strong( - v, (kExclusive->fast_or | v) + kExclusive->fast_add, - std::memory_order_acquire, std::memory_order_relaxed)) { + // Try fast acquire. + if (ABSL_PREDICT_TRUE((v & (kMuWriter | kMuReader | kMuEvent)) == 0)) { + if (ABSL_PREDICT_TRUE(mu_.compare_exchange_strong( + v, kMuWriter | v, std::memory_order_acquire, + std::memory_order_relaxed))) { DebugOnlyLockEnter(this); - PostSynchEvent(this, SYNCH_EV_TRYLOCK_SUCCESS); ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0); return true; - } else { - PostSynchEvent(this, SYNCH_EV_TRYLOCK_FAILED); } + } else if (ABSL_PREDICT_FALSE((v & kMuEvent) != 0)) { + // We're recording events. + return TryLockSlow(); + } + ABSL_TSAN_MUTEX_POST_LOCK( + this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0); + return false; +} + +ABSL_ATTRIBUTE_NOINLINE bool Mutex::TryLockSlow() { + intptr_t v = mu_.load(std::memory_order_relaxed); + if ((v & kExclusive->slow_need_zero) == 0 && // try fast acquire + mu_.compare_exchange_strong( + v, (kExclusive->fast_or | v) + kExclusive->fast_add, + std::memory_order_acquire, std::memory_order_relaxed)) { + DebugOnlyLockEnter(this); + PostSynchEvent(this, SYNCH_EV_TRYLOCK_SUCCESS); + ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0); + return true; } + PostSynchEvent(this, SYNCH_EV_TRYLOCK_FAILED); ABSL_TSAN_MUTEX_POST_LOCK( this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0); return false; @@ -1670,41 +1641,57 @@ bool Mutex::ReaderTryLock() { ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock | __tsan_mutex_try_lock); intptr_t v = mu_.load(std::memory_order_relaxed); + // Clang tends to unroll the loop when compiling with optimization. + // But in this case it just unnecessary increases code size. + // If CAS is failing due to contention, the jump cost is negligible. +#if defined(__clang__) +#pragma nounroll +#endif // The while-loops (here and below) iterate only if the mutex word keeps - // changing (typically because the reader count changes) under the CAS. We - // limit the number of attempts to avoid having to think about livelock. - int loop_limit = 5; - while ((v & (kMuWriter | kMuWait | kMuEvent)) == 0 && loop_limit != 0) { - if (mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne, - std::memory_order_acquire, - std::memory_order_relaxed)) { + // changing (typically because the reader count changes) under the CAS. + // We limit the number of attempts to avoid having to think about livelock. + for (int loop_limit = 5; loop_limit != 0; loop_limit--) { + if (ABSL_PREDICT_FALSE((v & (kMuWriter | kMuWait | kMuEvent)) != 0)) { + break; + } + if (ABSL_PREDICT_TRUE(mu_.compare_exchange_strong( + v, (kMuReader | v) + kMuOne, std::memory_order_acquire, + std::memory_order_relaxed))) { DebugOnlyLockEnter(this); ABSL_TSAN_MUTEX_POST_LOCK( this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0); return true; } - loop_limit--; - v = mu_.load(std::memory_order_relaxed); } - if ((v & kMuEvent) != 0) { // we're recording events - loop_limit = 5; - while ((v & kShared->slow_need_zero) == 0 && loop_limit != 0) { - if (mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne, - std::memory_order_acquire, - std::memory_order_relaxed)) { - DebugOnlyLockEnter(this); - PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_SUCCESS); - ABSL_TSAN_MUTEX_POST_LOCK( - this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0); - return true; - } - loop_limit--; - v = mu_.load(std::memory_order_relaxed); - } - if ((v & kMuEvent) != 0) { - PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_FAILED); + if (ABSL_PREDICT_TRUE((v & kMuEvent) == 0)) { + ABSL_TSAN_MUTEX_POST_LOCK(this, + __tsan_mutex_read_lock | __tsan_mutex_try_lock | + __tsan_mutex_try_lock_failed, + 0); + return false; + } + // we're recording events + return ReaderTryLockSlow(); +} + +ABSL_ATTRIBUTE_NOINLINE bool Mutex::ReaderTryLockSlow() { + intptr_t v = mu_.load(std::memory_order_relaxed); +#if defined(__clang__) +#pragma nounroll +#endif + for (int loop_limit = 5; loop_limit != 0; loop_limit--) { + if ((v & kShared->slow_need_zero) == 0 && + mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne, + std::memory_order_acquire, + std::memory_order_relaxed)) { + DebugOnlyLockEnter(this); + PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_SUCCESS); + ABSL_TSAN_MUTEX_POST_LOCK( + this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0); + return true; } } + PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_FAILED); ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock | __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, @@ -1768,16 +1755,20 @@ void Mutex::ReaderUnlock() { DebugOnlyLockLeave(this); intptr_t v = mu_.load(std::memory_order_relaxed); assert((v & (kMuWriter | kMuReader)) == kMuReader); - if ((v & (kMuReader | kMuWait | kMuEvent)) == kMuReader) { + for (;;) { + if (ABSL_PREDICT_FALSE((v & (kMuReader | kMuWait | kMuEvent)) != + kMuReader)) { + this->UnlockSlow(nullptr /*no waitp*/); // take slow path + break; + } // fast reader release (reader with no waiters) intptr_t clear = ExactlyOneReader(v) ? kMuReader | kMuOne : kMuOne; - if (mu_.compare_exchange_strong(v, v - clear, std::memory_order_release, - std::memory_order_relaxed)) { - ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock); - return; + if (ABSL_PREDICT_TRUE( + mu_.compare_exchange_strong(v, v - clear, std::memory_order_release, + std::memory_order_relaxed))) { + break; } } - this->UnlockSlow(nullptr /*no waitp*/); // take slow path ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock); } @@ -1812,6 +1803,22 @@ static intptr_t IgnoreWaitingWritersMask(int flag) { // Internal version of LockWhen(). See LockSlowWithDeadline() ABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition* cond, int flags) { + // Note: we specifically initialize spinloop_iterations after the first use + // in TryAcquireWithSpinning so that Lock function does not have any non-tail + // calls and consequently a stack frame. It's fine to have spinloop_iterations + // uninitialized (meaning no spinning) in all initial uncontended Lock calls + // and in the first contended call. After that we will have + // spinloop_iterations properly initialized. + if (ABSL_PREDICT_FALSE( + globals.spinloop_iterations.load(std::memory_order_relaxed) == 0)) { + if (absl::base_internal::NumCPUs() > 1) { + // If this is multiprocessor, allow spinning. + globals.spinloop_iterations.store(1500, std::memory_order_relaxed); + } else { + // If this a uniprocessor, only yield/sleep. + globals.spinloop_iterations.store(-1, std::memory_order_relaxed); + } + } ABSL_RAW_CHECK( this->LockSlowWithDeadline(how, cond, KernelTimeout::Never(), flags), "condition untrue on return from LockSlow"); @@ -1913,7 +1920,7 @@ bool Mutex::LockSlowWithDeadline(MuHow how, const Condition* cond, SynchWaitParams waitp(how, cond, t, nullptr /*no cvmu*/, Synch_GetPerThreadAnnotated(this), nullptr /*no cv_word*/); - if (!Condition::GuaranteedEqual(cond, nullptr)) { + if (cond != nullptr) { flags |= kMuIsCond; } if (unlock) { @@ -2103,7 +2110,6 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) { // head of the list searched previously, or zero PerThreadSynch* old_h = nullptr; // a condition that's known to be false. - const Condition* known_false = nullptr; PerThreadSynch* wake_list = kPerThreadSynchNull; // list of threads to wake intptr_t wr_wait = 0; // set to kMuWrWait if we wake a reader and a // later writer could have acquired the lock @@ -2207,7 +2213,7 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) { } } if (h->next->waitp->how == kExclusive && - Condition::GuaranteedEqual(h->next->waitp->cond, nullptr)) { + h->next->waitp->cond == nullptr) { // easy case: writer with no condition; no need to search pw = h; // wake w, the successor of h (=pw) w = h->next; @@ -2290,10 +2296,8 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) { w_walk->wake = false; if (w_walk->waitp->cond == nullptr || // no condition => vacuously true OR - (w_walk->waitp->cond != known_false && - // this thread's condition is not known false, AND - // is in fact true - EvalConditionIgnored(this, w_walk->waitp->cond))) { + // this thread's condition is true + EvalConditionIgnored(this, w_walk->waitp->cond)) { if (w == nullptr) { w_walk->wake = true; // can wake this waiter w = w_walk; @@ -2307,8 +2311,6 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) { } else { // writer with true condition wr_wait = kMuWrWait; } - } else { // can't wake; condition false - known_false = w_walk->waitp->cond; // remember last false condition } if (w_walk->wake) { // we're waking reader w_walk pw_walk = w_walk; // don't skip similar waiters @@ -2414,10 +2416,10 @@ void Mutex::Fer(PerThreadSynch* w) { int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); - ABSL_RAW_CHECK(!w->waitp->timeout.has_timeout(), - "Mutex::Fer while in timed wait"); ABSL_RAW_CHECK(w->waitp->cv_word == nullptr, "Mutex::Fer with pending CondVar queueing"); + // The CondVar timeout is not relevant for the Mutex wait. + w->waitp->timeout = {}; for (;;) { intptr_t v = mu_.load(std::memory_order_relaxed); // Note: must not queue if the mutex is unlocked (nobody will wake it). @@ -2436,7 +2438,8 @@ void Mutex::Fer(PerThreadSynch* w) { } else { if ((v & (kMuSpin | kMuWait)) == 0) { // no waiters // This thread tries to become the one and only waiter. - PerThreadSynch* new_h = Enqueue(nullptr, w->waitp, v, kMuIsCond); + PerThreadSynch* new_h = + Enqueue(nullptr, w->waitp, v, kMuIsCond | kMuIsFer); ABSL_RAW_CHECK(new_h != nullptr, "Enqueue failed"); // we must queue ourselves if (mu_.compare_exchange_strong( @@ -2447,7 +2450,7 @@ void Mutex::Fer(PerThreadSynch* w) { } else if ((v & kMuSpin) == 0 && mu_.compare_exchange_strong(v, v | kMuSpin | kMuWait)) { PerThreadSynch* h = GetPerThreadSynch(v); - PerThreadSynch* new_h = Enqueue(h, w->waitp, v, kMuIsCond); + PerThreadSynch* new_h = Enqueue(h, w->waitp, v, kMuIsCond | kMuIsFer); ABSL_RAW_CHECK(new_h != nullptr, "Enqueue failed"); // we must queue ourselves do { @@ -2503,12 +2506,6 @@ void CondVar::EnableDebugLog(const char* name) { UnrefSynchEvent(e); } -CondVar::~CondVar() { - if ((cv_.load(std::memory_order_relaxed) & kCvEvent) != 0) { - ForgetSynchEvent(&this->cv_, kCvEvent, kCvSpin); - } -} - // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch* s) { SchedulingGuard::ScopedDisable disable_rescheduling; @@ -2659,33 +2656,6 @@ bool CondVar::WaitCommon(Mutex* mutex, KernelTimeout t) { return rc; } -bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) { - return WaitCommon(mu, KernelTimeout(timeout)); -} - -bool CondVar::WaitWithDeadline(Mutex* mu, absl::Time deadline) { - return WaitCommon(mu, KernelTimeout(deadline)); -} - -void CondVar::Wait(Mutex* mu) { WaitCommon(mu, KernelTimeout::Never()); } - -// Wake thread w -// If it was a timed wait, w will be waiting on w->cv -// Otherwise, if it was not a Mutex mutex, w will be waiting on w->sem -// Otherwise, w is transferred to the Mutex mutex via Mutex::Fer(). -void CondVar::Wakeup(PerThreadSynch* w) { - if (w->waitp->timeout.has_timeout() || w->waitp->cvmu == nullptr) { - // The waiting thread only needs to observe "w->state == kAvailable" to be - // released, we must cache "cvmu" before clearing "next". - Mutex* mu = w->waitp->cvmu; - w->next = nullptr; - w->state.store(PerThreadSynch::kAvailable, std::memory_order_release); - Mutex::IncrementSynchSem(mu, w); - } else { - w->waitp->cvmu->Fer(w); - } -} - void CondVar::Signal() { SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); @@ -2710,7 +2680,7 @@ void CondVar::Signal() { cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h), std::memory_order_release); if (w != nullptr) { - CondVar::Wakeup(w); // wake waiter, if there was one + w->waitp->cvmu->Fer(w); // wake waiter, if there was one cond_var_tracer("Signal wakeup", this); } if ((v & kCvEvent) != 0) { @@ -2746,7 +2716,7 @@ void CondVar::SignalAll() { do { // for every thread, wake it up w = n; n = n->next; - CondVar::Wakeup(w); + w->waitp->cvmu->Fer(w); } while (w != h); cond_var_tracer("SignalAll wakeup", this); } @@ -2810,17 +2780,11 @@ Condition::Condition(const bool* cond) StoreCallback(dereference); } -bool Condition::Eval() const { - // eval_ == null for kTrue - return (this->eval_ == nullptr) || (*this->eval_)(this); -} +bool Condition::Eval() const { return (*this->eval_)(this); } bool Condition::GuaranteedEqual(const Condition* a, const Condition* b) { - // kTrue logic. - if (a == nullptr || a->eval_ == nullptr) { - return b == nullptr || b->eval_ == nullptr; - } else if (b == nullptr || b->eval_ == nullptr) { - return false; + if (a == nullptr || b == nullptr) { + return a == b; } // Check equality of the representative fields. return a->eval_ == b->eval_ && a->arg_ == b->arg_ && diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h index 645c26d9c3..d53a22bbd9 100644 --- a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h +++ b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h @@ -64,6 +64,7 @@ #include <iterator> #include <string> +#include "absl/base/attributes.h" #include "absl/base/const_init.h" #include "absl/base/internal/identity.h" #include "absl/base/internal/low_level_alloc.h" @@ -324,7 +325,9 @@ class ABSL_LOCKABLE Mutex { // `true`, `Await()` *may* skip the release/re-acquire step. // // `Await()` requires that this thread holds this `Mutex` in some mode. - void Await(const Condition& cond); + void Await(const Condition& cond) { + AwaitCommon(cond, synchronization_internal::KernelTimeout::Never()); + } // Mutex::LockWhen() // Mutex::ReaderLockWhen() @@ -334,9 +337,15 @@ class ABSL_LOCKABLE Mutex { // be acquired, then atomically acquires this `Mutex`. `LockWhen()` is // logically equivalent to `*Lock(); Await();` though they may have different // performance characteristics. - void LockWhen(const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION(); + void LockWhen(const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() { + LockWhenCommon(cond, synchronization_internal::KernelTimeout::Never(), + true); + } - void ReaderLockWhen(const Condition& cond) ABSL_SHARED_LOCK_FUNCTION(); + void ReaderLockWhen(const Condition& cond) ABSL_SHARED_LOCK_FUNCTION() { + LockWhenCommon(cond, synchronization_internal::KernelTimeout::Never(), + false); + } void WriterLockWhen(const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() { this->LockWhen(cond); @@ -363,9 +372,13 @@ class ABSL_LOCKABLE Mutex { // Negative timeouts are equivalent to a zero timeout. // // This method requires that this thread holds this `Mutex` in some mode. - bool AwaitWithTimeout(const Condition& cond, absl::Duration timeout); + bool AwaitWithTimeout(const Condition& cond, absl::Duration timeout) { + return AwaitCommon(cond, synchronization_internal::KernelTimeout{timeout}); + } - bool AwaitWithDeadline(const Condition& cond, absl::Time deadline); + bool AwaitWithDeadline(const Condition& cond, absl::Time deadline) { + return AwaitCommon(cond, synchronization_internal::KernelTimeout{deadline}); + } // Mutex::LockWhenWithTimeout() // Mutex::ReaderLockWhenWithTimeout() @@ -379,9 +392,15 @@ class ABSL_LOCKABLE Mutex { // // Negative timeouts are equivalent to a zero timeout. bool LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) - ABSL_EXCLUSIVE_LOCK_FUNCTION(); + ABSL_EXCLUSIVE_LOCK_FUNCTION() { + return LockWhenCommon( + cond, synchronization_internal::KernelTimeout{timeout}, true); + } bool ReaderLockWhenWithTimeout(const Condition& cond, absl::Duration timeout) - ABSL_SHARED_LOCK_FUNCTION(); + ABSL_SHARED_LOCK_FUNCTION() { + return LockWhenCommon( + cond, synchronization_internal::KernelTimeout{timeout}, false); + } bool WriterLockWhenWithTimeout(const Condition& cond, absl::Duration timeout) ABSL_EXCLUSIVE_LOCK_FUNCTION() { return this->LockWhenWithTimeout(cond, timeout); @@ -399,9 +418,15 @@ class ABSL_LOCKABLE Mutex { // // Deadlines in the past are equivalent to an immediate deadline. bool LockWhenWithDeadline(const Condition& cond, absl::Time deadline) - ABSL_EXCLUSIVE_LOCK_FUNCTION(); + ABSL_EXCLUSIVE_LOCK_FUNCTION() { + return LockWhenCommon( + cond, synchronization_internal::KernelTimeout{deadline}, true); + } bool ReaderLockWhenWithDeadline(const Condition& cond, absl::Time deadline) - ABSL_SHARED_LOCK_FUNCTION(); + ABSL_SHARED_LOCK_FUNCTION() { + return LockWhenCommon( + cond, synchronization_internal::KernelTimeout{deadline}, false); + } bool WriterLockWhenWithDeadline(const Condition& cond, absl::Time deadline) ABSL_EXCLUSIVE_LOCK_FUNCTION() { return this->LockWhenWithDeadline(cond, deadline); @@ -497,15 +522,22 @@ class ABSL_LOCKABLE Mutex { int flags) ABSL_ATTRIBUTE_COLD; // slow path release void UnlockSlow(SynchWaitParams* waitp) ABSL_ATTRIBUTE_COLD; + // TryLock slow path. + bool TryLockSlow(); + // ReaderTryLock slow path. + bool ReaderTryLockSlow(); // Common code between Await() and AwaitWithTimeout/Deadline() bool AwaitCommon(const Condition& cond, synchronization_internal::KernelTimeout t); + bool LockWhenCommon(const Condition& cond, + synchronization_internal::KernelTimeout t, bool write); // Attempt to remove thread s from queue. void TryRemove(base_internal::PerThreadSynch* s); // Block a thread on mutex. void Block(base_internal::PerThreadSynch* s); // Wake a thread; return successor. base_internal::PerThreadSynch* Wakeup(base_internal::PerThreadSynch* w); + void Dtor(); friend class CondVar; // for access to Trans()/Fer(). void Trans(MuHow how); // used for CondVar->Mutex transfer @@ -708,23 +740,25 @@ class Condition { // a function template is passed as `func`. Also, the dummy `typename = void` // template parameter exists just to work around a MSVC mangling bug. template <typename T, typename = void> - Condition(bool (*func)(T*), typename absl::internal::identity<T>::type* arg); + Condition(bool (*func)(T*), + typename absl::internal::type_identity<T>::type* arg); // Templated version for invoking a method that returns a `bool`. // // `Condition(object, &Class::Method)` constructs a `Condition` that evaluates // `object->Method()`. // - // Implementation Note: `absl::internal::identity` is used to allow methods to - // come from base classes. A simpler signature like + // Implementation Note: `absl::internal::type_identity` is used to allow + // methods to come from base classes. A simpler signature like // `Condition(T*, bool (T::*)())` does not suffice. template <typename T> - Condition(T* object, bool (absl::internal::identity<T>::type::*method)()); + Condition(T* object, + bool (absl::internal::type_identity<T>::type::*method)()); // Same as above, for const members template <typename T> Condition(const T* object, - bool (absl::internal::identity<T>::type::*method)() const); + bool (absl::internal::type_identity<T>::type::*method)() const); // A Condition that returns the value of `*cond` explicit Condition(const bool* cond); @@ -816,7 +850,7 @@ class Condition { static bool CallVoidPtrFunction(const Condition*); template <typename T> static bool CastAndCallFunction(const Condition* c); - template <typename T> + template <typename T, typename ConditionMethodPtr> static bool CastAndCallMethod(const Condition* c); // Helper methods for storing, validating, and reading callback arguments. @@ -833,8 +867,10 @@ class Condition { std::memcpy(callback, callback_, sizeof(*callback)); } + static bool AlwaysTrue(const Condition*) { return true; } + // Used only to create kTrue. - constexpr Condition() = default; + constexpr Condition() : eval_(AlwaysTrue), arg_(nullptr) {} }; // ----------------------------------------------------------------------------- @@ -877,7 +913,6 @@ class CondVar { // A `CondVar` allocated on the heap or on the stack can use the this // constructor. CondVar(); - ~CondVar(); // CondVar::Wait() // @@ -886,7 +921,9 @@ class CondVar { // spurious wakeup), then reacquires the `Mutex` and returns. // // Requires and ensures that the current thread holds the `Mutex`. - void Wait(Mutex* mu); + void Wait(Mutex* mu) { + WaitCommon(mu, synchronization_internal::KernelTimeout::Never()); + } // CondVar::WaitWithTimeout() // @@ -901,7 +938,9 @@ class CondVar { // to return `true` or `false`. // // Requires and ensures that the current thread holds the `Mutex`. - bool WaitWithTimeout(Mutex* mu, absl::Duration timeout); + bool WaitWithTimeout(Mutex* mu, absl::Duration timeout) { + return WaitCommon(mu, synchronization_internal::KernelTimeout(timeout)); + } // CondVar::WaitWithDeadline() // @@ -918,7 +957,9 @@ class CondVar { // to return `true` or `false`. // // Requires and ensures that the current thread holds the `Mutex`. - bool WaitWithDeadline(Mutex* mu, absl::Time deadline); + bool WaitWithDeadline(Mutex* mu, absl::Time deadline) { + return WaitCommon(mu, synchronization_internal::KernelTimeout(deadline)); + } // CondVar::Signal() // @@ -940,7 +981,6 @@ class CondVar { private: bool WaitCommon(Mutex* mutex, synchronization_internal::KernelTimeout t); void Remove(base_internal::PerThreadSynch* s); - void Wakeup(base_internal::PerThreadSynch* w); std::atomic<intptr_t> cv_; // Condition variable state. CondVar(const CondVar&) = delete; CondVar& operator=(const CondVar&) = delete; @@ -1024,15 +1064,30 @@ inline Mutex::Mutex() : mu_(0) { inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {} +#if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL) +ABSL_ATTRIBUTE_ALWAYS_INLINE +inline Mutex::~Mutex() { Dtor(); } +#endif + +#if defined(NDEBUG) && !defined(ABSL_HAVE_THREAD_SANITIZER) +// Use default (empty) destructor in release build for performance reasons. +// We need to mark both Dtor and ~Mutex as always inline for inconsistent +// builds that use both NDEBUG and !NDEBUG with dynamic libraries. In these +// cases we want the empty functions to dissolve entirely rather than being +// exported from dynamic libraries and potentially override the non-empty ones. +ABSL_ATTRIBUTE_ALWAYS_INLINE +inline void Mutex::Dtor() {} +#endif + inline CondVar::CondVar() : cv_(0) {} // static -template <typename T> +template <typename T, typename ConditionMethodPtr> bool Condition::CastAndCallMethod(const Condition* c) { T* object = static_cast<T*>(c->arg_); - bool (T::*method_pointer)(); - c->ReadCallback(&method_pointer); - return (object->*method_pointer)(); + ConditionMethodPtr condition_method_pointer; + c->ReadCallback(&condition_method_pointer); + return (object->*condition_method_pointer)(); } // static @@ -1054,25 +1109,25 @@ inline Condition::Condition(bool (*func)(T*), T* arg) } template <typename T, typename> -inline Condition::Condition(bool (*func)(T*), - typename absl::internal::identity<T>::type* arg) +inline Condition::Condition( + bool (*func)(T*), typename absl::internal::type_identity<T>::type* arg) // Just delegate to the overload above. : Condition(func, arg) {} template <typename T> -inline Condition::Condition(T* object, - bool (absl::internal::identity<T>::type::*method)()) - : eval_(&CastAndCallMethod<T>), arg_(object) { +inline Condition::Condition( + T* object, bool (absl::internal::type_identity<T>::type::*method)()) + : eval_(&CastAndCallMethod<T, decltype(method)>), arg_(object) { static_assert(sizeof(&method) <= sizeof(callback_), "An overlarge method pointer was passed to Condition."); StoreCallback(method); } template <typename T> -inline Condition::Condition(const T* object, - bool (absl::internal::identity<T>::type::*method)() - const) - : eval_(&CastAndCallMethod<T>), +inline Condition::Condition( + const T* object, + bool (absl::internal::type_identity<T>::type::*method)() const) + : eval_(&CastAndCallMethod<const T, decltype(method)>), arg_(reinterpret_cast<void*>(const_cast<T*>(object))) { StoreCallback(method); } diff --git a/contrib/restricted/abseil-cpp/absl/time/civil_time.h b/contrib/restricted/abseil-cpp/absl/time/civil_time.h index 5855bc73a1..3e904a113d 100644 --- a/contrib/restricted/abseil-cpp/absl/time/civil_time.h +++ b/contrib/restricted/abseil-cpp/absl/time/civil_time.h @@ -462,6 +462,32 @@ std::string FormatCivilTime(CivilDay c); std::string FormatCivilTime(CivilMonth c); std::string FormatCivilTime(CivilYear c); +// Support for StrFormat(), StrCat(), etc +template <typename Sink> +void AbslStringify(Sink& sink, CivilSecond c) { + sink.Append(FormatCivilTime(c)); +} +template <typename Sink> +void AbslStringify(Sink& sink, CivilMinute c) { + sink.Append(FormatCivilTime(c)); +} +template <typename Sink> +void AbslStringify(Sink& sink, CivilHour c) { + sink.Append(FormatCivilTime(c)); +} +template <typename Sink> +void AbslStringify(Sink& sink, CivilDay c) { + sink.Append(FormatCivilTime(c)); +} +template <typename Sink> +void AbslStringify(Sink& sink, CivilMonth c) { + sink.Append(FormatCivilTime(c)); +} +template <typename Sink> +void AbslStringify(Sink& sink, CivilYear c) { + sink.Append(FormatCivilTime(c)); +} + // absl::ParseCivilTime() // // Parses a civil-time value from the specified `absl::string_view` into the diff --git a/contrib/restricted/abseil-cpp/absl/time/clock.h b/contrib/restricted/abseil-cpp/absl/time/clock.h index 5fe244d638..41d2cf2770 100644 --- a/contrib/restricted/abseil-cpp/absl/time/clock.h +++ b/contrib/restricted/abseil-cpp/absl/time/clock.h @@ -22,6 +22,9 @@ #ifndef ABSL_TIME_CLOCK_H_ #define ABSL_TIME_CLOCK_H_ +#include <cstdint> + +#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/time/time.h" @@ -64,7 +67,8 @@ ABSL_NAMESPACE_END // By changing our extension points to be extern "C", we dodge this // check. extern "C" { -void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(absl::Duration duration); +ABSL_DLL void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)( + absl::Duration duration); } // extern "C" inline void absl::SleepFor(absl::Duration duration) { diff --git a/contrib/restricted/abseil-cpp/absl/time/duration.cc b/contrib/restricted/abseil-cpp/absl/time/duration.cc index 634e5d5845..bdb16e2109 100644 --- a/contrib/restricted/abseil-cpp/absl/time/duration.cc +++ b/contrib/restricted/abseil-cpp/absl/time/duration.cc @@ -55,8 +55,7 @@ #include <algorithm> #include <cassert> -#include <cctype> -#include <cerrno> +#include <chrono> // NOLINT(build/c++11) #include <cmath> #include <cstdint> #include <cstdlib> @@ -66,8 +65,9 @@ #include <limits> #include <string> +#include "absl/base/attributes.h" #include "absl/base/casts.h" -#include "absl/base/macros.h" +#include "absl/base/config.h" #include "absl/numeric/int128.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h index a5b084e6be..2b0aed56c3 100644 --- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h +++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h @@ -401,11 +401,11 @@ class civil_time { : civil_time(ct.f_) {} // Factories for the maximum/minimum representable civil_time. - static CONSTEXPR_F civil_time(max)() { + static CONSTEXPR_F auto(max)() -> civil_time { const auto max_year = (std::numeric_limits<std::int_least64_t>::max)(); return civil_time(max_year, 12, 31, 23, 59, 59); } - static CONSTEXPR_F civil_time(min)() { + static CONSTEXPR_F auto(min)() -> civil_time { const auto min_year = (std::numeric_limits<std::int_least64_t>::min)(); return civil_time(min_year, 1, 1, 0, 0, 0); } 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 9b91f61cf0..e7e30a2fb7 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 @@ -19,7 +19,7 @@ #endif #if defined(HAS_STRPTIME) && HAS_STRPTIME -#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__) +#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #define _XOPEN_SOURCE 500 // Exposes definitions for SUSv2 (UNIX 98). #endif #endif 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 f46198ffaa..b7178a6b67 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 @@ -474,7 +474,8 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open( const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; // See Android's libc/tzcode/bionic.cpp for additional information. - for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata", + for (const char* tzdata : {"/apex/com.android.tzdata/etc/tz/tzdata", + "/data/misc/zoneinfo/current/tzdata", "/system/usr/share/zoneinfo/tzdata"}) { auto fp = FOpen(tzdata, "rb"); if (fp == nullptr) continue; @@ -539,9 +540,16 @@ std::unique_ptr<ZoneInfoSource> FuchsiaZoneInfoSource::Open( // Prefixes where a Fuchsia component might find zoneinfo files, // in descending order of preference. const auto kTzdataPrefixes = { + // The tzdata from `config-data`. "/config/data/tzdata/", + // The tzdata bundled in the component's package. "/pkg/data/tzdata/", + // General data storage. "/data/tzdata/", + // The recommended path for routed-in tzdata files. + // See for details: + // https://fuchsia.dev/fuchsia-src/concepts/process/namespaces?hl=en#typical_directory_structure + "/config/tzdata/", }; const auto kEmptyPrefix = {""}; const bool name_absolute = (pos != name.size() && name[pos] == '/'); @@ -744,19 +752,6 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) { version_ = zip->Version(); } - // Trim redundant transitions. zic may have added these to work around - // differences between the glibc and reference implementations (see - // zic.c:dontmerge) or to avoid bugs in old readers. For us, they just - // get in the way when we do future_spec_ extension. - while (hdr.timecnt > 1) { - if (!EquivTransitions(transitions_[hdr.timecnt - 1].type_index, - transitions_[hdr.timecnt - 2].type_index)) { - break; - } - hdr.timecnt -= 1; - } - transitions_.resize(hdr.timecnt); - // Ensure that there is always a transition in the first half of the // time line (the second half is handled below) so that the signed // difference between a civil_second and the civil_second of its 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 9613055db7..114026d066 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 @@ -21,14 +21,6 @@ ** Information about time zone files. */ -#ifndef TZDIR -#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ -#endif /* !defined TZDIR */ - -#ifndef TZDEFAULT -#define TZDEFAULT "/etc/localtime" -#endif /* !defined TZDEFAULT */ - #ifndef TZDEFRULES #define TZDEFRULES "posixrules" #endif /* !defined TZDEFRULES */ diff --git a/contrib/restricted/abseil-cpp/absl/types/bad_any_cast.cc b/contrib/restricted/abseil-cpp/absl/types/bad_any_cast.cc index b0592cc9bc..22558b48c2 100644 --- a/contrib/restricted/abseil-cpp/absl/types/bad_any_cast.cc +++ b/contrib/restricted/abseil-cpp/absl/types/bad_any_cast.cc @@ -43,4 +43,22 @@ void ThrowBadAnyCast() { ABSL_NAMESPACE_END } // namespace absl +#else + +// https://github.com/abseil/abseil-cpp/issues/1465 +// CMake builds on Apple platforms error when libraries are empty. +// Our CMake configuration can avoid this error on header-only libraries, +// but since this library is conditionally empty, including a single +// variable is an easy workaround. +#ifdef __APPLE__ +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace types_internal { +extern const char kAvoidEmptyBadAnyCastLibraryWarning; +const char kAvoidEmptyBadAnyCastLibraryWarning = 0; +} // namespace types_internal +ABSL_NAMESPACE_END +} // namespace absl +#endif // __APPLE__ + #endif // ABSL_USES_STD_ANY diff --git a/contrib/restricted/abseil-cpp/absl/types/bad_optional_access.cc b/contrib/restricted/abseil-cpp/absl/types/bad_optional_access.cc index 26aca70d9c..2552cc853a 100644 --- a/contrib/restricted/abseil-cpp/absl/types/bad_optional_access.cc +++ b/contrib/restricted/abseil-cpp/absl/types/bad_optional_access.cc @@ -45,4 +45,22 @@ void throw_bad_optional_access() { ABSL_NAMESPACE_END } // namespace absl +#else + +// https://github.com/abseil/abseil-cpp/issues/1465 +// CMake builds on Apple platforms error when libraries are empty. +// Our CMake configuration can avoid this error on header-only libraries, +// but since this library is conditionally empty, including a single +// variable is an easy workaround. +#ifdef __APPLE__ +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace types_internal { +extern const char kAvoidEmptyBadOptionalAccessLibraryWarning; +const char kAvoidEmptyBadOptionalAccessLibraryWarning = 0; +} // namespace types_internal +ABSL_NAMESPACE_END +} // namespace absl +#endif // __APPLE__ + #endif // ABSL_USES_STD_OPTIONAL diff --git a/contrib/restricted/abseil-cpp/absl/types/bad_variant_access.cc b/contrib/restricted/abseil-cpp/absl/types/bad_variant_access.cc index 3dc88cc09f..a76aa80dfa 100644 --- a/contrib/restricted/abseil-cpp/absl/types/bad_variant_access.cc +++ b/contrib/restricted/abseil-cpp/absl/types/bad_variant_access.cc @@ -61,4 +61,22 @@ void Rethrow() { ABSL_NAMESPACE_END } // namespace absl +#else + +// https://github.com/abseil/abseil-cpp/issues/1465 +// CMake builds on Apple platforms error when libraries are empty. +// Our CMake configuration can avoid this error on header-only libraries, +// but since this library is conditionally empty, including a single +// variable is an easy workaround. +#ifdef __APPLE__ +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace types_internal { +extern const char kAvoidEmptyBadVariantAccessLibraryWarning; +const char kAvoidEmptyBadVariantAccessLibraryWarning = 0; +} // namespace types_internal +ABSL_NAMESPACE_END +} // namespace absl +#endif // __APPLE__ + #endif // ABSL_USES_STD_VARIANT diff --git a/contrib/restricted/abseil-cpp/absl/types/internal/variant.h b/contrib/restricted/abseil-cpp/absl/types/internal/variant.h index fc8829e5d8..263d7b0947 100644 --- a/contrib/restricted/abseil-cpp/absl/types/internal/variant.h +++ b/contrib/restricted/abseil-cpp/absl/types/internal/variant.h @@ -1047,11 +1047,11 @@ class VariantStateBase { std::size_t index_; }; -using absl::internal::identity; +using absl::internal::type_identity; // OverloadSet::Overload() is a unary function which is overloaded to // take any of the element types of the variant, by reference-to-const. -// The return type of the overload on T is identity<T>, so that you +// The return type of the overload on T is type_identity<T>, so that you // can statically determine which overload was called. // // Overload() is not defined, so it can only be called in unevaluated @@ -1062,7 +1062,7 @@ struct OverloadSet; template <typename T, typename... Ts> struct OverloadSet<T, Ts...> : OverloadSet<Ts...> { using Base = OverloadSet<Ts...>; - static identity<T> Overload(const T&); + static type_identity<T> Overload(const T&); using Base::Overload; }; diff --git a/contrib/restricted/abseil-cpp/absl/types/optional.h b/contrib/restricted/abseil-cpp/absl/types/optional.h index 0a8080dc1a..395fe62f29 100644 --- a/contrib/restricted/abseil-cpp/absl/types/optional.h +++ b/contrib/restricted/abseil-cpp/absl/types/optional.h @@ -61,6 +61,7 @@ ABSL_NAMESPACE_END #include <utility> #include "absl/base/attributes.h" +#include "absl/base/nullability.h" #include "absl/base/internal/inline_variable.h" #include "absl/meta/type_traits.h" #include "absl/types/bad_optional_access.h" @@ -415,11 +416,11 @@ class optional : private optional_internal::optional_data<T>, // `optional` is empty, behavior is undefined. // // If you need myOpt->foo in constexpr, use (*myOpt).foo instead. - const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + absl::Nonnull<const T*> operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_HARDENING_ASSERT(this->engaged_); return std::addressof(this->data_); } - T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND { + absl::Nonnull<T*> operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_HARDENING_ASSERT(this->engaged_); return std::addressof(this->data_); } diff --git a/contrib/restricted/abseil-cpp/absl/types/span.h b/contrib/restricted/abseil-cpp/absl/types/span.h index 70ed8eb6fa..88cd759540 100644 --- a/contrib/restricted/abseil-cpp/absl/types/span.h +++ b/contrib/restricted/abseil-cpp/absl/types/span.h @@ -63,6 +63,7 @@ #include "absl/base/attributes.h" #include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" +#include "absl/base/nullability.h" #include "absl/base/optimization.h" #include "absl/base/port.h" // TODO(strel): remove this include #include "absl/meta/type_traits.h" @@ -172,6 +173,8 @@ class Span { public: using element_type = T; using value_type = absl::remove_cv_t<T>; + // TODO(b/316099902) - pointer should be Nullable<T*>, but this makes it hard + // to recognize foreach loops as safe. using pointer = T*; using const_pointer = const T*; using reference = T&; @@ -679,12 +682,12 @@ bool operator>=(Span<T> a, const U& b) { // } // template <int&... ExplicitArgumentBarrier, typename T> -constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept { +constexpr Span<T> MakeSpan(absl::Nullable<T*> ptr, size_t size) noexcept { return Span<T>(ptr, size); } template <int&... ExplicitArgumentBarrier, typename T> -Span<T> MakeSpan(T* begin, T* end) noexcept { +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)); } @@ -725,12 +728,14 @@ constexpr Span<T> MakeSpan(T (&array)[N]) noexcept { // ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 })); // template <int&... ExplicitArgumentBarrier, typename T> -constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept { +constexpr Span<const T> MakeConstSpan(absl::Nullable<T*> ptr, + size_t size) noexcept { return Span<const T>(ptr, size); } template <int&... ExplicitArgumentBarrier, typename T> -Span<const T> MakeConstSpan(T* begin, T* end) noexcept { +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); } diff --git a/contrib/restricted/abseil-cpp/absl/utility/utility.h b/contrib/restricted/abseil-cpp/absl/utility/utility.h index bf9232209a..fc0d1f6551 100644 --- a/contrib/restricted/abseil-cpp/absl/utility/utility.h +++ b/contrib/restricted/abseil-cpp/absl/utility/utility.h @@ -12,17 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// This header file contains C++11 versions of standard <utility> header -// abstractions available within C++14 and C++17, and are designed to be drop-in +// This header file contains C++14 versions of standard <utility> header +// abstractions available within C++17, and are designed to be drop-in // replacement for code compliant with C++14 and C++17. // // The following abstractions are defined: // -// * integer_sequence<T, Ints...> == std::integer_sequence<T, Ints...> -// * index_sequence<Ints...> == std::index_sequence<Ints...> -// * make_integer_sequence<T, N> == std::make_integer_sequence<T, N> -// * make_index_sequence<N> == std::make_index_sequence<N> -// * index_sequence_for<Ts...> == std::index_sequence_for<Ts...> // * apply<Functor, Tuple> == std::apply<Functor, Tuple> // * exchange<T> == std::exchange<T> // * make_from_tuple<T> == std::make_from_tuple<T> @@ -33,7 +28,6 @@ // // References: // -// https://en.cppreference.com/w/cpp/utility/integer_sequence // https://en.cppreference.com/w/cpp/utility/apply // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html @@ -53,68 +47,18 @@ namespace absl { ABSL_NAMESPACE_BEGIN -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence<T, Ints...>); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence<int, 5>()); -// } -template <typename T, T... Ints> -struct integer_sequence { - using value_type = T; - static constexpr size_t size() noexcept { return sizeof...(Ints); } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template <size_t... Ints> -using index_sequence = integer_sequence<size_t, Ints...>; +// Historical note: Abseil once provided implementations of these +// abstractions for platforms that had not yet provided them. Those +// platforms are no longer supported. New code should simply use the +// the ones from std directly. +using std::index_sequence; +using std::index_sequence_for; +using std::integer_sequence; +using std::make_index_sequence; +using std::make_integer_sequence; namespace utility_internal { -template <typename Seq, size_t SeqSize, size_t Rem> -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template <typename T, T... Ints, size_t SeqSize> -struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> { - using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>; -}; - -template <typename T, T... Ints, size_t SeqSize> -struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> { - using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>; -}; - -// Recursion helper for 'make_integer_sequence<T, N>'. -// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. -template <typename T, size_t N> -struct Gen { - using type = - typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type; -}; - -template <typename T> -struct Gen<T, 0> { - using type = integer_sequence<T>; -}; - template <typename T> struct InPlaceTypeTag { explicit InPlaceTypeTag() = delete; @@ -131,32 +75,6 @@ struct InPlaceIndexTag { } // namespace utility_internal -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template <typename T, T N> -using make_integer_sequence = typename utility_internal::Gen<T, N>::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template <size_t N> -using make_index_sequence = make_integer_sequence<size_t, N>; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template <typename... Ts> -using index_sequence_for = make_index_sequence<sizeof...(Ts)>; - // Tag types #ifdef ABSL_USES_STD_OPTIONAL diff --git a/contrib/restricted/abseil-cpp/absl/utility/ya.make b/contrib/restricted/abseil-cpp/absl/utility/ya.make index 3b66e3e400..3f9af85fe6 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(20230802.1) +VERSION(20240116.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240116.0.tar.gz) NO_RUNTIME() diff --git a/contrib/restricted/abseil-cpp/ya.make b/contrib/restricted/abseil-cpp/ya.make index c89fe4570a..36452ac10e 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(20230802.1) +VERSION(20240116.0) -ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/abseil/abseil-cpp/archive/20240116.0.tar.gz) PEERDIR( contrib/restricted/abseil-cpp/absl/algorithm diff --git a/contrib/restricted/boost/assert/include/boost/assert/source_location.hpp b/contrib/restricted/boost/assert/include/boost/assert/source_location.hpp index 82e2d37854..2349ed8a2f 100644 --- a/contrib/restricted/boost/assert/include/boost/assert/source_location.hpp +++ b/contrib/restricted/boost/assert/include/boost/assert/source_location.hpp @@ -15,7 +15,7 @@ #include <cstring> #if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L -# error #include <source_location> +#include <source_location> #endif namespace boost diff --git a/library/cpp/lcs/lcs_via_lis_ut.cpp b/library/cpp/lcs/lcs_via_lis_ut.cpp index f6ad5152b6..0029a7c5b9 100644 --- a/library/cpp/lcs/lcs_via_lis_ut.cpp +++ b/library/cpp/lcs/lcs_via_lis_ut.cpp @@ -39,7 +39,7 @@ private: void CheckLCSString(TStringBuf s1, TStringBuf s2, TStringBuf reflcs) { TString lcs; size_t len = NLCS::MakeLCS<char>(s1, s2, &lcs); - const char* comment = Sprintf("%s & %s = %s", s1.data(), s2.data(), reflcs.data()).c_str(); + const TString comment = Sprintf("%s & %s = %s", s1.data(), s2.data(), reflcs.data()); UNIT_ASSERT_VALUES_EQUAL_C(Length(s1, s2), len, comment); UNIT_ASSERT_VALUES_EQUAL_C(lcs.size(), len, comment); diff --git a/library/cpp/tld/tlds-alpha-by-domain.txt b/library/cpp/tld/tlds-alpha-by-domain.txt index a85eba8c8b..76fbd16e7b 100644 --- a/library/cpp/tld/tlds-alpha-by-domain.txt +++ b/library/cpp/tld/tlds-alpha-by-domain.txt @@ -1,4 +1,4 @@ -# Version 2024012300, Last Updated Tue Jan 23 07:07:01 2024 UTC +# Version 2024012400, Last Updated Wed Jan 24 07:07:01 2024 UTC AAA AARP ABB diff --git a/library/cpp/yt/misc/enum.h b/library/cpp/yt/misc/enum.h index 1494ca7907..9da79b9fd3 100644 --- a/library/cpp/yt/misc/enum.h +++ b/library/cpp/yt/misc/enum.h @@ -185,6 +185,7 @@ struct TEnumTraits<T, true> //////////////////////////////////////////////////////////////////////////////// +// TODO(babenko): drop in favor of TEnumIndexedArray //! A statically sized vector with elements of type |T| indexed by //! the items of enumeration type |E|. /*! diff --git a/library/cpp/yt/misc/enum_indexed_array-inl.h b/library/cpp/yt/misc/enum_indexed_array-inl.h new file mode 100644 index 0000000000..edda891683 --- /dev/null +++ b/library/cpp/yt/misc/enum_indexed_array-inl.h @@ -0,0 +1,73 @@ +#pragma once +#ifndef ENUM_INDEXED_ARRAY_INL_H_ +#error "Direct inclusion of this file is not allowed, include enum.h" +// For the sake of sane code completion. +#include "enum_indexed_array.h" +#endif + +#include <library/cpp/yt/assert/assert.h> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +template <class E, class T, E Min, E Max> +TEnumIndexedArray<E, T, Min, Max>::TEnumIndexedArray(std::initializer_list<std::pair<E, T>> elements) +{ + for (const auto& [index, value] : elements) { + (*this)[index] = value; + } +} + +template <class E, class T, E Min, E Max> +T& TEnumIndexedArray<E, T, Min, Max>::operator[] (E index) +{ + YT_ASSERT(IsValidIndex(index)); + return Items_[ToUnderlying(index) - ToUnderlying(Min)]; +} + +template <class E, class T, E Min, E Max> +const T& TEnumIndexedArray<E, T, Min, Max>::operator[] (E index) const +{ + return const_cast<TEnumIndexedArray&>(*this)[index]; +} + +template <class E, class T, E Min, E Max> +T* TEnumIndexedArray<E, T, Min, Max>::begin() +{ + return Items_.data(); +} + +template <class E, class T, E Min, E Max> +const T* TEnumIndexedArray<E, T, Min, Max>::begin() const +{ + return Items_.data(); +} + +template <class E, class T, E Min, E Max> +T* TEnumIndexedArray<E, T, Min, Max>::end() +{ + return begin() + Size; +} + +template <class E, class T, E Min, E Max> +const T* TEnumIndexedArray<E, T, Min, Max>::end() const +{ + return begin() + Size; +} + +template <class E, class T, E Min, E Max> +constexpr size_t TEnumIndexedArray<E, T, Min, Max>::size() const +{ + return Size; +} + +template <class E, class T, E Min, E Max> +bool TEnumIndexedArray<E, T, Min, Max>::IsValidIndex(E index) +{ + return index >= Min && index <= Max; +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT diff --git a/library/cpp/yt/misc/enum_indexed_array.h b/library/cpp/yt/misc/enum_indexed_array.h new file mode 100644 index 0000000000..8992456277 --- /dev/null +++ b/library/cpp/yt/misc/enum_indexed_array.h @@ -0,0 +1,64 @@ +#pragma once + +#include "enum.h" + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +//! A statically sized vector with elements of type |T| indexed by +//! the items of enumeration type |E|. +/*! + * By default, valid indexes are in range from the minimum declared value of |E| + * to the maximum declared value of |E|. + * + * Items are value-initialized on construction. + */ +template < + class E, + class T, + E Min = TEnumTraits<E>::GetMinValue(), + E Max = TEnumTraits<E>::GetMaxValue() +> +class TEnumIndexedArray +{ +public: + static_assert(Min <= Max); + + using TIndex = E; + using TValue = T; + + constexpr TEnumIndexedArray() = default; + TEnumIndexedArray(std::initializer_list<std::pair<E, T>> elements); + + constexpr TEnumIndexedArray(const TEnumIndexedArray&) = default; + constexpr TEnumIndexedArray(TEnumIndexedArray&&) = default; + + constexpr TEnumIndexedArray& operator=(const TEnumIndexedArray&) = default; + constexpr TEnumIndexedArray& operator=(TEnumIndexedArray&&) = default; + + T& operator[] (E index); + const T& operator[] (E index) const; + + // STL interop. + T* begin(); + const T* begin() const; + T* end(); + const T* end() const; + + constexpr size_t size() const; + + static bool IsValidIndex(E index); + +private: + static constexpr size_t Size = static_cast<size_t>(Max) - static_cast<size_t>(Min) + 1; + std::array<T, Size> Items_{}; +}; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT + +#define ENUM_INDEXED_ARRAY_INL_H_ +#include "enum_indexed_array-inl.h" +#undef ENUM_INDEXED_ARRAY_INL_H_ diff --git a/library/cpp/yt/misc/unittests/enum_indexed_array_ut.cpp b/library/cpp/yt/misc/unittests/enum_indexed_array_ut.cpp new file mode 100644 index 0000000000..4111c6f4fe --- /dev/null +++ b/library/cpp/yt/misc/unittests/enum_indexed_array_ut.cpp @@ -0,0 +1,45 @@ +#include <library/cpp/testing/gtest/gtest.h> + +#include <library/cpp/yt/misc/enum_indexed_array.h> + +namespace NYT { +namespace { + +//////////////////////////////////////////////////////////////////////////////// + +DEFINE_ENUM(EColor, + ((Red) (10)) + ((Green)(20)) + ((Blue) (30)) +); + +TEST(TEnumIndexedArrayTest, Size) +{ + TEnumIndexedArray<EColor, int> arr; + EXPECT_EQ(std::ssize(arr), 21); +} + +TEST(TEnumIndexedArrayTest, IsValidIndex) +{ + TEnumIndexedArray<EColor, int> arr; + EXPECT_TRUE(arr.IsValidIndex(EColor::Red)); + EXPECT_TRUE(arr.IsValidIndex(EColor::Green)); + EXPECT_TRUE(arr.IsValidIndex(EColor::Blue)); + EXPECT_TRUE(arr.IsValidIndex(static_cast<EColor>(11))); + EXPECT_FALSE(arr.IsValidIndex(static_cast<EColor>(9))); +} + +TEST(TEnumIndexedArrayTest, Simple) +{ + TEnumIndexedArray<EColor, int> arr; + EXPECT_EQ(arr[EColor::Red], 0); + arr[EColor::Red] = 1; + EXPECT_EQ(arr[EColor::Red], 1); + EXPECT_EQ(arr[EColor::Blue], 0); +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace +} // namespace NYT + diff --git a/library/cpp/yt/misc/unittests/ya.make b/library/cpp/yt/misc/unittests/ya.make index 611edd7217..43e9f9b9ff 100644 --- a/library/cpp/yt/misc/unittests/ya.make +++ b/library/cpp/yt/misc/unittests/ya.make @@ -4,6 +4,7 @@ INCLUDE(${ARCADIA_ROOT}/library/cpp/yt/ya_cpp.make.inc) SRCS( enum_ut.cpp + enum_indexed_array_ut.cpp guid_ut.cpp preprocessor_ut.cpp strong_typedef_ut.cpp diff --git a/library/cpp/yt/string/format-inl.h b/library/cpp/yt/string/format-inl.h index c379af712a..c198fdcd65 100644 --- a/library/cpp/yt/string/format-inl.h +++ b/library/cpp/yt/string/format-inl.h @@ -12,6 +12,7 @@ #include <library/cpp/yt/small_containers/compact_vector.h> #include <library/cpp/yt/misc/enum.h> +#include <library/cpp/yt/misc/enum_indexed_array.h> #include <util/system/platform.h> @@ -393,6 +394,27 @@ struct TValueFormatter<THashMultiMap<K, V>> } }; +// TEnumIndexedArray +template <class E, class T> +struct TValueFormatter<TEnumIndexedArray<E, T>> +{ + static void Do(TStringBuilderBase* builder, const TEnumIndexedArray<E, T>& collection, TStringBuf format) + { + builder->AppendChar('{'); + bool firstItem = true; + for (const auto& index : TEnumTraits<E>::GetDomainValues()) { + if (!firstItem) { + builder->AppendString(DefaultJoinToStringDelimiter); + } + FormatValue(builder, index, format); + builder->AppendString(": "); + FormatValue(builder, collection[index], format); + firstItem = false; + } + builder->AppendChar('}'); + } +}; + // TEnumIndexedVector template <class E, class T> struct TValueFormatter<TEnumIndexedVector<E, T>> diff --git a/library/cpp/yt/string/unittests/enum_ut.cpp b/library/cpp/yt/string/unittests/enum_ut.cpp index 4059b3d2e6..91a8b04500 100644 --- a/library/cpp/yt/string/unittests/enum_ut.cpp +++ b/library/cpp/yt/string/unittests/enum_ut.cpp @@ -13,6 +13,7 @@ namespace { // Some compile-time sanity checks. DEFINE_ENUM(ESample, (One)(Two)); static_assert(TFormatTraits<ESample>::HasCustomFormatValue); +static_assert(TFormatTraits<TEnumIndexedArray<ESample, int>>::HasCustomFormatValue); static_assert(TFormatTraits<TEnumIndexedVector<ESample, int>>::HasCustomFormatValue); DEFINE_ENUM(EColor, diff --git a/library/cpp/ytalloc/api/fallback.cpp b/library/cpp/ytalloc/api/fallback.cpp index d094cf2e93..d7dca33f88 100644 --- a/library/cpp/ytalloc/api/fallback.cpp +++ b/library/cpp/ytalloc/api/fallback.cpp @@ -144,47 +144,47 @@ Y_WEAK void SetEnableMadvisePopulate(bool /*value*/) //////////////////////////////////////////////////////////////////////////////// -Y_WEAK TEnumIndexedVector<ETotalCounter, ssize_t> GetTotalAllocationCounters() +Y_WEAK TEnumIndexedArray<ETotalCounter, ssize_t> GetTotalAllocationCounters() { return {}; } -Y_WEAK TEnumIndexedVector<ESmallCounter, ssize_t> GetSmallAllocationCounters() +Y_WEAK TEnumIndexedArray<ESmallCounter, ssize_t> GetSmallAllocationCounters() { return {}; } -Y_WEAK TEnumIndexedVector<ELargeCounter, ssize_t> GetLargeAllocationCounters() +Y_WEAK TEnumIndexedArray<ELargeCounter, ssize_t> GetLargeAllocationCounters() { return {}; } -Y_WEAK std::array<TEnumIndexedVector<ESmallArenaCounter, ssize_t>, SmallRankCount> GetSmallArenaAllocationCounters() +Y_WEAK std::array<TEnumIndexedArray<ESmallArenaCounter, ssize_t>, SmallRankCount> GetSmallArenaAllocationCounters() { return {}; } -Y_WEAK std::array<TEnumIndexedVector<ELargeArenaCounter, ssize_t>, LargeRankCount> GetLargeArenaAllocationCounters() +Y_WEAK std::array<TEnumIndexedArray<ELargeArenaCounter, ssize_t>, LargeRankCount> GetLargeArenaAllocationCounters() { return {}; } -Y_WEAK TEnumIndexedVector<EHugeCounter, ssize_t> GetHugeAllocationCounters() +Y_WEAK TEnumIndexedArray<EHugeCounter, ssize_t> GetHugeAllocationCounters() { return {}; } -Y_WEAK TEnumIndexedVector<ESystemCounter, ssize_t> GetSystemAllocationCounters() +Y_WEAK TEnumIndexedArray<ESystemCounter, ssize_t> GetSystemAllocationCounters() { return {}; } -Y_WEAK TEnumIndexedVector<EUndumpableCounter, ssize_t> GetUndumpableAllocationCounters() +Y_WEAK TEnumIndexedArray<EUndumpableCounter, ssize_t> GetUndumpableAllocationCounters() { return {}; } -Y_WEAK TEnumIndexedVector<ETimingEventType, TTimingEventCounters> GetTimingEventCounters() +Y_WEAK TEnumIndexedArray<ETimingEventType, TTimingEventCounters> GetTimingEventCounters() { return {}; } diff --git a/library/cpp/ytalloc/api/ytalloc.h b/library/cpp/ytalloc/api/ytalloc.h index 219814def2..43ba48852d 100644 --- a/library/cpp/ytalloc/api/ytalloc.h +++ b/library/cpp/ytalloc/api/ytalloc.h @@ -3,6 +3,7 @@ #include <stddef.h> #include <library/cpp/yt/misc/enum.h> +#include <library/cpp/yt/misc/enum_indexed_array.h> #include <util/system/types.h> @@ -289,28 +290,28 @@ DEFINE_ENUM(ETotalCounter, ); // Returns statistics for all user allocations. -TEnumIndexedVector<ETotalCounter, ssize_t> GetTotalAllocationCounters(); +TEnumIndexedArray<ETotalCounter, ssize_t> GetTotalAllocationCounters(); // Returns statistics for small allocations; these are included into total statistics. -TEnumIndexedVector<ESmallCounter, ssize_t> GetSmallAllocationCounters(); +TEnumIndexedArray<ESmallCounter, ssize_t> GetSmallAllocationCounters(); // Returns statistics for large allocations; these are included into total statistics. -TEnumIndexedVector<ELargeCounter, ssize_t> GetLargeAllocationCounters(); +TEnumIndexedArray<ELargeCounter, ssize_t> GetLargeAllocationCounters(); // Returns per-arena statistics for small allocations; these are included into total statistics. -std::array<TEnumIndexedVector<ESmallArenaCounter, ssize_t>, SmallRankCount> GetSmallArenaAllocationCounters(); +std::array<TEnumIndexedArray<ESmallArenaCounter, ssize_t>, SmallRankCount> GetSmallArenaAllocationCounters(); // Returns per-arena statistics for large allocations; these are included into total statistics. -std::array<TEnumIndexedVector<ELargeArenaCounter, ssize_t>, LargeRankCount> GetLargeArenaAllocationCounters(); +std::array<TEnumIndexedArray<ELargeArenaCounter, ssize_t>, LargeRankCount> GetLargeArenaAllocationCounters(); // Returns statistics for huge allocations; these are included into total statistics. -TEnumIndexedVector<EHugeCounter, ssize_t> GetHugeAllocationCounters(); +TEnumIndexedArray<EHugeCounter, ssize_t> GetHugeAllocationCounters(); // Returns statistics for all system allocations; these are not included into total statistics. -TEnumIndexedVector<ESystemCounter, ssize_t> GetSystemAllocationCounters(); +TEnumIndexedArray<ESystemCounter, ssize_t> GetSystemAllocationCounters(); // Returns statistics for undumpable allocations. -TEnumIndexedVector<EUndumpableCounter, ssize_t> GetUndumpableAllocationCounters(); +TEnumIndexedArray<EUndumpableCounter, ssize_t> GetUndumpableAllocationCounters(); DEFINE_ENUM(ETimingEventType, (Mmap) @@ -333,7 +334,7 @@ struct TTimingEventCounters // Returns statistics for timing events happened since start. // See SetTimingEventThreshold. -TEnumIndexedVector<ETimingEventType, TTimingEventCounters> GetTimingEventCounters(); +TEnumIndexedArray<ETimingEventType, TTimingEventCounters> GetTimingEventCounters(); //////////////////////////////////////////////////////////////////////////////// @@ -349,7 +350,7 @@ struct TBacktrace struct TProfiledAllocation { TBacktrace Backtrace; - TEnumIndexedVector<EBasicCounter, ssize_t> Counters; + TEnumIndexedArray<EBasicCounter, ssize_t> Counters; }; // Returns statistics for profiled allocations (available when allocation diff --git a/library/cpp/ytalloc/impl/core-inl.h b/library/cpp/ytalloc/impl/core-inl.h index 64e95188f4..ba5128bd8d 100644 --- a/library/cpp/ytalloc/impl/core-inl.h +++ b/library/cpp/ytalloc/impl/core-inl.h @@ -940,14 +940,14 @@ class TTimingManager : public TEventLogManagerBase<TTimingEvent, TTimingManager> { public: - TEnumIndexedVector<ETimingEventType, TTimingEventCounters> GetTimingEventCounters() + TEnumIndexedArray<ETimingEventType, TTimingEventCounters> GetTimingEventCounters() { auto guard = Guard(EventLock_); return EventCounters_; } private: - TEnumIndexedVector<ETimingEventType, TTimingEventCounters> EventCounters_; + TEnumIndexedArray<ETimingEventType, TTimingEventCounters> EventCounters_; Y_POD_STATIC_THREAD(bool) DisabledForCurrentThread_; @@ -1523,13 +1523,13 @@ static_assert( "Wrong MaxMemoryTag"); template <class TCounter> -using TUntaggedTotalCounters = TEnumIndexedVector<EBasicCounter, TCounter>; +using TUntaggedTotalCounters = TEnumIndexedArray<EBasicCounter, TCounter>; template <class TCounter> struct TTaggedTotalCounterSet : public TSystemAllocatable { - std::array<TEnumIndexedVector<EBasicCounter, TCounter>, TaggedCounterSetSize> Counters; + std::array<TEnumIndexedArray<EBasicCounter, TCounter>, TaggedCounterSetSize> Counters; }; using TLocalTaggedBasicCounterSet = TTaggedTotalCounterSet<ssize_t>; @@ -1577,20 +1577,20 @@ struct TTotalCounters } }; -using TLocalSystemCounters = TEnumIndexedVector<ESystemCounter, ssize_t>; -using TGlobalSystemCounters = TEnumIndexedVector<ESystemCounter, std::atomic<ssize_t>>; +using TLocalSystemCounters = TEnumIndexedArray<ESystemCounter, ssize_t>; +using TGlobalSystemCounters = TEnumIndexedArray<ESystemCounter, std::atomic<ssize_t>>; -using TLocalSmallCounters = TEnumIndexedVector<ESmallArenaCounter, ssize_t>; -using TGlobalSmallCounters = TEnumIndexedVector<ESmallArenaCounter, std::atomic<ssize_t>>; +using TLocalSmallCounters = TEnumIndexedArray<ESmallArenaCounter, ssize_t>; +using TGlobalSmallCounters = TEnumIndexedArray<ESmallArenaCounter, std::atomic<ssize_t>>; -using TLocalLargeCounters = TEnumIndexedVector<ELargeArenaCounter, ssize_t>; -using TGlobalLargeCounters = TEnumIndexedVector<ELargeArenaCounter, std::atomic<ssize_t>>; +using TLocalLargeCounters = TEnumIndexedArray<ELargeArenaCounter, ssize_t>; +using TGlobalLargeCounters = TEnumIndexedArray<ELargeArenaCounter, std::atomic<ssize_t>>; -using TLocalHugeCounters = TEnumIndexedVector<EHugeCounter, ssize_t>; -using TGlobalHugeCounters = TEnumIndexedVector<EHugeCounter, std::atomic<ssize_t>>; +using TLocalHugeCounters = TEnumIndexedArray<EHugeCounter, ssize_t>; +using TGlobalHugeCounters = TEnumIndexedArray<EHugeCounter, std::atomic<ssize_t>>; -using TLocalUndumpableCounters = TEnumIndexedVector<EUndumpableCounter, ssize_t>; -using TGlobalUndumpableCounters = TEnumIndexedVector<EUndumpableCounter, std::atomic<ssize_t>>; +using TLocalUndumpableCounters = TEnumIndexedArray<EUndumpableCounter, ssize_t>; +using TGlobalUndumpableCounters = TEnumIndexedArray<EUndumpableCounter, std::atomic<ssize_t>>; Y_FORCE_INLINE ssize_t LoadCounter(ssize_t counter) { @@ -1750,7 +1750,7 @@ struct TThreadState std::array<bool, SmallRankCount> CachedChunkFull{}; #endif }; - TEnumIndexedVector<EAllocationKind, TSmallBlobCache> SmallBlobCache; + TEnumIndexedArray<EAllocationKind, TSmallBlobCache> SmallBlobCache; }; struct TThreadStateToRegistryNode @@ -2227,7 +2227,7 @@ public: } // Computes memory usage for a list of tags by aggregating counters across threads. - void GetTaggedMemoryCounters(const TMemoryTag* tags, size_t count, TEnumIndexedVector<EBasicCounter, ssize_t>* counters) + void GetTaggedMemoryCounters(const TMemoryTag* tags, size_t count, TEnumIndexedArray<EBasicCounter, ssize_t>* counters) { TMemoryTagGuard guard(NullMemoryTag); @@ -2260,7 +2260,7 @@ public: { TMemoryTagGuard guard(NullMemoryTag); - std::vector<TEnumIndexedVector<EBasicCounter, ssize_t>> counters; + std::vector<TEnumIndexedArray<EBasicCounter, ssize_t>> counters; counters.resize(count); GetTaggedMemoryCounters(tags, count, counters.data()); @@ -2269,9 +2269,9 @@ public: } } - TEnumIndexedVector<ETotalCounter, ssize_t> GetTotalAllocationCounters() + TEnumIndexedArray<ETotalCounter, ssize_t> GetTotalAllocationCounters() { - TEnumIndexedVector<ETotalCounter, ssize_t> result; + TEnumIndexedArray<ETotalCounter, ssize_t> result; auto accumulate = [&] (const auto& counters) { result[ETotalCounter::BytesAllocated] += LoadCounter(counters[EBasicCounter::BytesAllocated]); @@ -2312,9 +2312,9 @@ public: return result; } - TEnumIndexedVector<ESmallCounter, ssize_t> GetSmallAllocationCounters() + TEnumIndexedArray<ESmallCounter, ssize_t> GetSmallAllocationCounters() { - TEnumIndexedVector<ESmallCounter, ssize_t> result; + TEnumIndexedArray<ESmallCounter, ssize_t> result; auto totalCounters = GetTotalAllocationCounters(); result[ESmallCounter::BytesAllocated] = totalCounters[ETotalCounter::BytesAllocated]; @@ -2347,9 +2347,9 @@ public: return result; } - TEnumIndexedVector<ELargeCounter, ssize_t> GetLargeAllocationCounters() + TEnumIndexedArray<ELargeCounter, ssize_t> GetLargeAllocationCounters() { - TEnumIndexedVector<ELargeCounter, ssize_t> result; + TEnumIndexedArray<ELargeCounter, ssize_t> result; auto largeArenaCounters = GetLargeArenaAllocationCounters(); for (size_t rank = 0; rank < LargeRankCount; ++rank) { result[ESmallCounter::BytesAllocated] += largeArenaCounters[rank][ELargeArenaCounter::BytesAllocated]; @@ -2826,7 +2826,7 @@ private: } }; -TExplicitlyConstructableSingleton<TEnumIndexedVector<EAllocationKind, std::array<TExplicitlyConstructableSingleton<TSmallArenaAllocator>, SmallRankCount>>> SmallArenaAllocators; +TExplicitlyConstructableSingleton<TEnumIndexedArray<EAllocationKind, std::array<TExplicitlyConstructableSingleton<TSmallArenaAllocator>, SmallRankCount>>> SmallArenaAllocators; //////////////////////////////////////////////////////////////////////////////// @@ -3023,7 +3023,7 @@ private: std::array<TShardedFreeList<TChunkGroup>, SmallRankCount> RankToChunkGroups_; }; -TExplicitlyConstructableSingleton<TEnumIndexedVector<EAllocationKind, TExplicitlyConstructableSingleton<TGlobalSmallChunkCache>>> GlobalSmallChunkCaches; +TExplicitlyConstructableSingleton<TEnumIndexedArray<EAllocationKind, TExplicitlyConstructableSingleton<TGlobalSmallChunkCache>>> GlobalSmallChunkCaches; //////////////////////////////////////////////////////////////////////////////// @@ -4750,49 +4750,49 @@ void SetEnableMadvisePopulate(bool value) ConfigurationManager->SetEnableMadvisePopulate(value); } -TEnumIndexedVector<ETotalCounter, ssize_t> GetTotalAllocationCounters() +TEnumIndexedArray<ETotalCounter, ssize_t> GetTotalAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetTotalAllocationCounters(); } -TEnumIndexedVector<ESystemCounter, ssize_t> GetSystemAllocationCounters() +TEnumIndexedArray<ESystemCounter, ssize_t> GetSystemAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetSystemAllocationCounters(); } -TEnumIndexedVector<ESystemCounter, ssize_t> GetUndumpableAllocationCounters() +TEnumIndexedArray<ESystemCounter, ssize_t> GetUndumpableAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetUndumpableAllocationCounters(); } -TEnumIndexedVector<ESmallCounter, ssize_t> GetSmallAllocationCounters() +TEnumIndexedArray<ESmallCounter, ssize_t> GetSmallAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetSmallAllocationCounters(); } -TEnumIndexedVector<ESmallCounter, ssize_t> GetLargeAllocationCounters() +TEnumIndexedArray<ESmallCounter, ssize_t> GetLargeAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetLargeAllocationCounters(); } -std::array<TEnumIndexedVector<ESmallArenaCounter, ssize_t>, SmallRankCount> GetSmallArenaAllocationCounters() +std::array<TEnumIndexedArray<ESmallArenaCounter, ssize_t>, SmallRankCount> GetSmallArenaAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetSmallArenaAllocationCounters(); } -std::array<TEnumIndexedVector<ELargeArenaCounter, ssize_t>, LargeRankCount> GetLargeArenaAllocationCounters() +std::array<TEnumIndexedArray<ELargeArenaCounter, ssize_t>, LargeRankCount> GetLargeArenaAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetLargeArenaAllocationCounters(); } -TEnumIndexedVector<EHugeCounter, ssize_t> GetHugeAllocationCounters() +TEnumIndexedArray<EHugeCounter, ssize_t> GetHugeAllocationCounters() { InitializeGlobals(); return StatisticsManager->GetHugeAllocationCounters(); @@ -4816,7 +4816,7 @@ std::vector<TProfiledAllocation> GetProfiledAllocationStatistics() } tags.push_back(AllocationProfilingUnknownMemoryTag); - std::vector<TEnumIndexedVector<EBasicCounter, ssize_t>> counters; + std::vector<TEnumIndexedArray<EBasicCounter, ssize_t>> counters; counters.resize(tags.size()); StatisticsManager->GetTaggedMemoryCounters(tags.data(), tags.size(), counters.data()); @@ -4838,7 +4838,7 @@ std::vector<TProfiledAllocation> GetProfiledAllocationStatistics() return statistics; } -TEnumIndexedVector<ETimingEventType, TTimingEventCounters> GetTimingEventCounters() +TEnumIndexedArray<ETimingEventType, TTimingEventCounters> GetTimingEventCounters() { InitializeGlobals(); return TimingManager->GetTimingEventCounters(); diff --git a/library/rightlib_sha.txt b/library/rightlib_sha.txt index d4f5181850..5bfd2b763b 100644 --- a/library/rightlib_sha.txt +++ b/library/rightlib_sha.txt @@ -1 +1 @@ -5987d9abc62382b1434059ccdf127fdafaf79578 +f6d7ec162ce757a854f4a619d6b0c7084ad48f3e diff --git a/util/generic/yexception.cpp b/util/generic/yexception.cpp index ac62a8f4d2..6b067e90bb 100644 --- a/util/generic/yexception.cpp +++ b/util/generic/yexception.cpp @@ -119,9 +119,11 @@ std::string CurrentExceptionTypeName() { void TSystemError::Init() { yexception& exc = *this; - exc << TStringBuf("("); - exc << TStringBuf(LastSystemErrorText(Status_)); - exc << TStringBuf(") "); + exc << "(Error "sv + << Status_ + << ": "sv + << TStringBuf(LastSystemErrorText(Status_)) + << ") "sv; } NPrivateException::yexception::yexception() { @@ -34,33 +34,33 @@ REGISTRY_ENDPOINT = os.environ.get("YA_REGISTRY_ENDPOINT", "https://devtools-reg PLATFORM_MAP = { "data": { "darwin": { - "md5": "aac10b71b364633a551e2aee7d74125c", + "md5": "35469cf30e4da49d46e77aafe344796c", "urls": [ - f"{REGISTRY_ENDPOINT}/5707413774" + f"{REGISTRY_ENDPOINT}/5720350130" ] }, "darwin-arm64": { - "md5": "13edc8d010203aa1ca401c4adef46c8a", + "md5": "e1b24bcbf0c53e169ebab09b8a4ce96a", "urls": [ - f"{REGISTRY_ENDPOINT}/5707412857" + f"{REGISTRY_ENDPOINT}/5720349611" ] }, "linux-aarch64": { - "md5": "968f03070c7c9759ba95c551e031a00d", + "md5": "e4eb5f2fc68e31109760933a99125430", "urls": [ - f"{REGISTRY_ENDPOINT}/5707412269" + f"{REGISTRY_ENDPOINT}/5720349159" ] }, "win32-clang-cl": { - "md5": "c61932f2818c1fcb6d1586aed6beecf3", + "md5": "5e78baa59b32e4c66d1da363f37a05e1", "urls": [ - f"{REGISTRY_ENDPOINT}/5707414392" + f"{REGISTRY_ENDPOINT}/5720350841" ] }, "linux": { - "md5": "3d86cc42b38043923c02680bc71fd39d", + "md5": "e8c956d24922f1b713533e311a050d3e", "urls": [ - f"{REGISTRY_ENDPOINT}/5707415175" + f"{REGISTRY_ENDPOINT}/5720351345" ] } } diff --git a/yt/cpp/mapreduce/client/file_writer.cpp b/yt/cpp/mapreduce/client/file_writer.cpp index 5a9b9a1f58..d273731e1d 100644 --- a/yt/cpp/mapreduce/client/file_writer.cpp +++ b/yt/cpp/mapreduce/client/file_writer.cpp @@ -16,7 +16,8 @@ TFileWriter::TFileWriter( const TClientContext& context, const TTransactionId& transactionId, const TFileWriterOptions& options) - : RetryfulWriter_( + : AutoFinish_(options.AutoFinish_) + , RetryfulWriter_( std::move(clientRetryPolicy), std::move(transactionPinger), context, @@ -29,7 +30,7 @@ TFileWriter::TFileWriter( TFileWriter::~TFileWriter() { - NDetail::FinishOrDie(this, "TFileWriter"); + NDetail::FinishOrDie(this, AutoFinish_, "TFileWriter"); } void TFileWriter::DoWrite(const void* buf, size_t len) diff --git a/yt/cpp/mapreduce/client/file_writer.h b/yt/cpp/mapreduce/client/file_writer.h index 259f778ea7..ae143a75be 100644 --- a/yt/cpp/mapreduce/client/file_writer.h +++ b/yt/cpp/mapreduce/client/file_writer.h @@ -30,6 +30,7 @@ protected: size_t GetBufferMemoryUsage() const override; private: + const bool AutoFinish_; TRetryfulWriter RetryfulWriter_; static const size_t BUFFER_SIZE = 64 << 20; }; diff --git a/yt/cpp/mapreduce/client/retryful_writer.cpp b/yt/cpp/mapreduce/client/retryful_writer.cpp index 057fb5e7f0..55165b17ff 100644 --- a/yt/cpp/mapreduce/client/retryful_writer.cpp +++ b/yt/cpp/mapreduce/client/retryful_writer.cpp @@ -17,7 +17,7 @@ namespace NYT { TRetryfulWriter::~TRetryfulWriter() { - NDetail::FinishOrDie(this, "TRetryfulWriter"); + NDetail::FinishOrDie(this, AutoFinish_, "TRetryfulWriter"); } void TRetryfulWriter::CheckWriterState() diff --git a/yt/cpp/mapreduce/client/retryful_writer.h b/yt/cpp/mapreduce/client/retryful_writer.h index 0b345daabf..c2de332bff 100644 --- a/yt/cpp/mapreduce/client/retryful_writer.h +++ b/yt/cpp/mapreduce/client/retryful_writer.h @@ -39,6 +39,7 @@ public: : ClientRetryPolicy_(std::move(clientRetryPolicy)) , TransactionPinger_(std::move(transactionPinger)) , Context_(context) + , AutoFinish_(options.AutoFinish_) , Command_(command) , Format_(format) , BufferSize_(GetBufferSize(options.WriterOptions_)) @@ -91,6 +92,7 @@ private: const IClientRetryPolicyPtr ClientRetryPolicy_; const ITransactionPingerPtr TransactionPinger_; const TClientContext Context_; + const bool AutoFinish_; TString Command_; TMaybe<TFormat> Format_; const size_t BufferSize_; diff --git a/yt/cpp/mapreduce/client/retryless_writer.cpp b/yt/cpp/mapreduce/client/retryless_writer.cpp index e3cf7cba06..dcda69bce4 100644 --- a/yt/cpp/mapreduce/client/retryless_writer.cpp +++ b/yt/cpp/mapreduce/client/retryless_writer.cpp @@ -8,7 +8,7 @@ namespace NYT { TRetrylessWriter::~TRetrylessWriter() { - NDetail::FinishOrDie(this, "TRetrylessWriter"); + NDetail::FinishOrDie(this, AutoFinish_, "TRetrylessWriter"); } void TRetrylessWriter::DoFinish() diff --git a/yt/cpp/mapreduce/client/retryless_writer.h b/yt/cpp/mapreduce/client/retryless_writer.h index 0a1b3865ee..6916cddbf6 100644 --- a/yt/cpp/mapreduce/client/retryless_writer.h +++ b/yt/cpp/mapreduce/client/retryless_writer.h @@ -1,7 +1,5 @@ #pragma once -#include "transaction.h" - #include <yt/cpp/mapreduce/http/helpers.h> #include <yt/cpp/mapreduce/http/http.h> #include <yt/cpp/mapreduce/http/http_client.h> @@ -36,6 +34,7 @@ public: size_t bufferSize, const TWriterOptions& options) : BufferSize_(bufferSize) + , AutoFinish_(options.AutoFinish_) { THttpHeader header("PUT", command); header.SetInputFormat(format); @@ -72,6 +71,7 @@ protected: private: const size_t BufferSize_ = 0; + const bool AutoFinish_; bool Running_ = true; NHttpClient::IHttpRequestPtr Request_; diff --git a/yt/cpp/mapreduce/client/ya.make b/yt/cpp/mapreduce/client/ya.make index c159492808..3696a9ba8f 100644 --- a/yt/cpp/mapreduce/client/ya.make +++ b/yt/cpp/mapreduce/client/ya.make @@ -46,17 +46,10 @@ PEERDIR( yt/cpp/mapreduce/raw_client ) -IF (ARCH_X86_64 OR OS_DARWIN) - PEERDIR( - yt/yt/core - yt/yt/core/http - ) -ELSE() - # Suppress yamaker's WBadIncl error on exotic platforms - PEERDIR( - yt/yt_proto/yt/core - ) -ENDIF() +PEERDIR( + yt/yt/core + yt/yt/core/http +) IF (BUILD_TYPE == "PROFILE") PEERDIR( diff --git a/yt/cpp/mapreduce/interface/client_method_options.h b/yt/cpp/mapreduce/interface/client_method_options.h index b5f0f1e34e..24607de424 100644 --- a/yt/cpp/mapreduce/interface/client_method_options.h +++ b/yt/cpp/mapreduce/interface/client_method_options.h @@ -538,6 +538,16 @@ struct TFileWriterOptions FLUENT_FIELD_OPTION(bool, ComputeMD5); /// + /// @brief Wheter to call Finish automatically in writer destructor. + /// + /// If set to true (default) Finish() is called automatically in the destructor of writer. + /// It is convenient for simple usecases but might be error-prone if writing exception safe code + /// (In case of exceptions it's common to abort writer and not commit partial data). + /// + /// If set to false Finish() has to be called explicitly. + FLUENT_FIELD_DEFAULT(bool, AutoFinish, true); + + /// /// @brief Options to control how YT server side writes data. /// /// @see NYT::TWriterOptions @@ -689,6 +699,16 @@ struct TTableWriterOptions FLUENT_FIELD_OPTION(bool, InferSchema); /// + /// @brief Wheter to call Finish automatically in writer destructor. + /// + /// If set to true (default) Finish() is called automatically in the destructor of writer. + /// It is convenient for simple usecases but might be error-prone if writing exception safe code + /// (In case of exceptions it's common to abort writer and not commit partial data). + /// + /// If set to false Finish() has to be called explicitly. + FLUENT_FIELD_DEFAULT(bool, AutoFinish, true); + + /// /// @brief Options to control how YT server side writes data. /// /// @see NYT::TWriterOptions diff --git a/yt/cpp/mapreduce/interface/finish_or_die.h b/yt/cpp/mapreduce/interface/finish_or_die.h index cb8d96c454..a6e190328f 100644 --- a/yt/cpp/mapreduce/interface/finish_or_die.h +++ b/yt/cpp/mapreduce/interface/finish_or_die.h @@ -10,8 +10,12 @@ namespace NYT::NDetail { //////////////////////////////////////////////////////////////////////////////// template <typename T> -void FinishOrDie(T* pThis, const char* className) noexcept +void FinishOrDie(T* pThis, bool autoFinish, const char* className) noexcept { + if (!autoFinish) { + return; + } + auto fail = [&] (const char* what) { Y_ABORT( "\n\n" diff --git a/yt/cpp/mapreduce/interface/io-inl.h b/yt/cpp/mapreduce/interface/io-inl.h index fee7ba20ff..7324eaca20 100644 --- a/yt/cpp/mapreduce/interface/io-inl.h +++ b/yt/cpp/mapreduce/interface/io-inl.h @@ -784,7 +784,7 @@ public: ~TTableWriterBase() override { if (Locks_.RefCount() == 1) { - NDetail::FinishOrDie(this, "TTableWriterBase"); + NDetail::FinishOrDie(this, /*autoFinish*/ true, "TTableWriterBase"); } } diff --git a/yt/cpp/mapreduce/interface/operation.h b/yt/cpp/mapreduce/interface/operation.h index 31252c2737..69c873090d 100644 --- a/yt/cpp/mapreduce/interface/operation.h +++ b/yt/cpp/mapreduce/interface/operation.h @@ -1990,6 +1990,19 @@ public: virtual void Load(IInputStream& stream) override { Load(&stream); } \ Y_PASS_VA_ARGS(Y_SAVELOAD_DEFINE(__VA_ARGS__)) +/// +/// @brief Same as the macro above, but also calls Base class's SaveLoad methods. +#define Y_SAVELOAD_JOB_DERIVED(Base, ...) \ + virtual void Save(IOutputStream& stream) const override { \ + Base::Save(stream); \ + Save(&stream); \ + } \ + virtual void Load(IInputStream& stream) override { \ + Base::Load(stream); \ + Load(&stream); \ + } \ + Y_PASS_VA_ARGS(Y_SAVELOAD_DEFINE(__VA_ARGS__)) + //////////////////////////////////////////////////////////////////////////////// /// diff --git a/yt/yt/client/api/client_common.h b/yt/yt/client/api/client_common.h index 8cbb77be07..3cc8fe461f 100644 --- a/yt/yt/client/api/client_common.h +++ b/yt/yt/client/api/client_common.h @@ -153,6 +153,8 @@ struct TSelectRowsOptionsBase bool NewRangeInference = true; //! Enables canonical SQL behaviour for relational operators, i.e. null </=/> value -> null. bool UseCanonicalNullRelations = false; + //! Merge versioned rows from different stores when reading. + bool MergeVersionedRows = true; }; struct TSelectRowsOptions diff --git a/yt/yt/client/api/config.cpp b/yt/yt/client/api/config.cpp index 404dd8ce95..525819bc07 100644 --- a/yt/yt/client/api/config.cpp +++ b/yt/yt/client/api/config.cpp @@ -1,6 +1,6 @@ #include "config.h" -#include <yt/yt/core/misc/backoff_strategy_config.h> +#include <yt/yt/core/misc/config.h> namespace NYT::NApi { diff --git a/yt/yt/client/api/operation_client.h b/yt/yt/client/api/operation_client.h index 35d62da527..0d0ac82c0c 100644 --- a/yt/yt/client/api/operation_client.h +++ b/yt/yt/client/api/operation_client.h @@ -292,8 +292,8 @@ struct TListOperationsResult std::optional<THashMap<TString, i64>> PoolTreeCounts; std::optional<THashMap<TString, i64>> PoolCounts; std::optional<THashMap<TString, i64>> UserCounts; - std::optional<TEnumIndexedVector<NScheduler::EOperationState, i64>> StateCounts; - std::optional<TEnumIndexedVector<NScheduler::EOperationType, i64>> TypeCounts; + std::optional<TEnumIndexedArray<NScheduler::EOperationState, i64>> StateCounts; + std::optional<TEnumIndexedArray<NScheduler::EOperationType, i64>> TypeCounts; std::optional<i64> FailedJobsCount; bool Incomplete = false; }; @@ -338,8 +338,8 @@ void Serialize(const TJob& job, NYson::IYsonConsumer* consumer, TStringBuf idKey struct TListJobsStatistics { - TEnumIndexedVector<NJobTrackerClient::EJobState, i64> StateCounts; - TEnumIndexedVector<NJobTrackerClient::EJobType, i64> TypeCounts; + TEnumIndexedArray<NJobTrackerClient::EJobState, i64> StateCounts; + TEnumIndexedArray<NJobTrackerClient::EJobType, i64> TypeCounts; }; struct TListJobsResult diff --git a/yt/yt/client/api/public.h b/yt/yt/client/api/public.h index 7e6c250481..55a72dd3c5 100644 --- a/yt/yt/client/api/public.h +++ b/yt/yt/client/api/public.h @@ -14,6 +14,8 @@ #include <yt/yt/core/rpc/public.h> +#include <library/cpp/yt/misc/enum_indexed_array.h> + namespace NYT::NApi { //////////////////////////////////////////////////////////////////////////////// @@ -217,7 +219,7 @@ DEFINE_ENUM(EMaintenanceComponent, ); using TMaintenanceId = TGuid; -using TMaintenanceCounts = TEnumIndexedVector<EMaintenanceType, int>; +using TMaintenanceCounts = TEnumIndexedArray<EMaintenanceType, int>; //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/client/api/rpc_proxy/client_base.cpp b/yt/yt/client/api/rpc_proxy/client_base.cpp index 64fbb0de05..6f0961d58b 100644 --- a/yt/yt/client/api/rpc_proxy/client_base.cpp +++ b/yt/yt/client/api/rpc_proxy/client_base.cpp @@ -1003,6 +1003,7 @@ TFuture<TSelectRowsResult> TClientBase::SelectRows( ToProto(req->mutable_suppressable_access_tracking_options(), options); req->set_replica_consistency(static_cast<NProto::EReplicaConsistency>(options.ReplicaConsistency)); req->set_use_canonical_null_relations(options.UseCanonicalNullRelations); + req->set_merge_versioned_rows(options.MergeVersionedRows); return req->Invoke().Apply(BIND([] (const TApiServiceProxy::TRspSelectRowsPtr& rsp) { TSelectRowsResult result; diff --git a/yt/yt/client/api/rpc_proxy/helpers.cpp b/yt/yt/client/api/rpc_proxy/helpers.cpp index 9562053d10..819a478b41 100644 --- a/yt/yt/client/api/rpc_proxy/helpers.cpp +++ b/yt/yt/client/api/rpc_proxy/helpers.cpp @@ -349,7 +349,7 @@ void FromProto( std::fill(result->StateCounts->begin(), result->StateCounts->end(), 0); for (const auto& stateCount: proto.state_counts().entries()) { auto state = ConvertOperationStateFromProto(stateCount.state()); - YT_VERIFY(result->StateCounts->IsDomainValue(state)); + YT_VERIFY(result->StateCounts->IsValidIndex(state)); YT_VERIFY((*result->StateCounts)[state] == 0); (*result->StateCounts)[state] = stateCount.count(); } @@ -361,7 +361,7 @@ void FromProto( std::fill(result->TypeCounts->begin(), result->TypeCounts->end(), 0); for (const auto& typeCount: proto.type_counts().entries()) { auto type = ConvertOperationTypeFromProto(typeCount.type()); - YT_VERIFY(result->TypeCounts->IsDomainValue(type)); + YT_VERIFY(result->TypeCounts->IsValidIndex(type)); YT_VERIFY((*result->TypeCounts)[type] == 0); (*result->TypeCounts)[type] = typeCount.count(); } @@ -1113,7 +1113,7 @@ void FromProto( std::fill(statistics->StateCounts.begin(), statistics->StateCounts.end(), 0); for (const auto& stateCount: protoStatistics.state_counts().entries()) { auto state = ConvertJobStateFromProto(stateCount.state()); - YT_VERIFY(statistics->StateCounts.IsDomainValue(state)); + YT_VERIFY(statistics->StateCounts.IsValidIndex(state)); YT_VERIFY(statistics->StateCounts[state] == 0); statistics->StateCounts[state] = stateCount.count(); } @@ -1121,7 +1121,7 @@ void FromProto( std::fill(statistics->TypeCounts.begin(), statistics->TypeCounts.end(), 0); for (const auto& typeCount: protoStatistics.type_counts().entries()) { auto type = ConvertJobTypeFromProto(typeCount.type()); - YT_VERIFY(statistics->TypeCounts.IsDomainValue(type)); + YT_VERIFY(statistics->TypeCounts.IsValidIndex(type)); YT_VERIFY(statistics->TypeCounts[type] == 0); statistics->TypeCounts[type] = typeCount.count(); } diff --git a/yt/yt/client/api/security_client.h b/yt/yt/client/api/security_client.h index 87ceab45f3..39e752799c 100644 --- a/yt/yt/client/api/security_client.h +++ b/yt/yt/client/api/security_client.h @@ -70,7 +70,9 @@ struct TCheckPermissionByAclResult struct TSetUserPasswordOptions : public TTimeoutOptions -{ }; +{ + bool PasswordIsTemporary = false; +}; struct TIssueTokenOptions : public TTimeoutOptions diff --git a/yt/yt/client/driver/authentication_commands.cpp b/yt/yt/client/driver/authentication_commands.cpp index 60546f842c..eeadbbbbc2 100644 --- a/yt/yt/client/driver/authentication_commands.cpp +++ b/yt/yt/client/driver/authentication_commands.cpp @@ -16,6 +16,12 @@ void TSetUserPasswordCommand::Register(TRegistrar registrar) registrar.Parameter("current_password_sha256", &TThis::CurrentPasswordSha256_) .Default(); registrar.Parameter("new_password_sha256", &TThis::NewPasswordSha256_); + registrar.ParameterWithUniversalAccessor<bool>( + "password_is_temporary", + [] (TThis* command) -> bool& { + return command->Options.PasswordIsTemporary; + }) + .Default(false); } void TSetUserPasswordCommand::DoExecute(ICommandContextPtr context) diff --git a/yt/yt/client/driver/command-inl.h b/yt/yt/client/driver/command-inl.h index 6cd7d52810..d30876cacf 100644 --- a/yt/yt/client/driver/command-inl.h +++ b/yt/yt/client/driver/command-inl.h @@ -419,6 +419,13 @@ void TSelectRowsCommandBase< return command->Options.UseCanonicalNullRelations; }) .Optional(/*init*/ false); + + registrar.template ParameterWithUniversalAccessor<bool>( + "merge_versioned_rows", + [] (TThis* command) -> auto& { + return command->Options.MergeVersionedRows; + }) + .Optional(/*init*/ false); } //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/client/driver/command.cpp b/yt/yt/client/driver/command.cpp index 8a94593e8c..cd9cf53ad7 100644 --- a/yt/yt/client/driver/command.cpp +++ b/yt/yt/client/driver/command.cpp @@ -16,7 +16,6 @@ using namespace NConcurrency; //////////////////////////////////////////////////////////////////////////////// - void ProduceOutput( ICommandContextPtr context, const std::function<void(IYsonConsumer*)>& producer) diff --git a/yt/yt/client/driver/driver.cpp b/yt/yt/client/driver/driver.cpp index a9a8bd685e..b68aff58e7 100644 --- a/yt/yt/client/driver/driver.cpp +++ b/yt/yt/client/driver/driver.cpp @@ -362,9 +362,15 @@ public: REGISTER_ALL(TGetBundleConfigCommand, "get_bundle_config", Null, Structured, false, false); REGISTER_ALL(TSetBundleConfigCommand, "set_bundle_config", Structured, Null, false, false); - REGISTER_ALL(TStartPipelineCommand, "start_pipeline", Null, Structured, false, false); - REGISTER_ALL(TStopPipelineCommand, "stop_pipeline", Null, Structured, false, false); - REGISTER_ALL(TPausePipelineCommand, "pause_pipeline", Null, Structured, false, false); + REGISTER (TGetPipelineSpecCommand, "get_pipeline_spec", Null, Structured, true, false, ApiVersion4); + REGISTER (TSetPipelineSpecCommand, "set_pipeline_spec", Structured, Null, true, false, ApiVersion4); + REGISTER (TRemovePipelineDynamicSpecCommand, "remove_pipeline_spec", Null, Null, true, false, ApiVersion4); + REGISTER (TGetPipelineDynamicSpecCommand, "get_pipeline_dynamic_spec", Null, Structured, true, false, ApiVersion4); + REGISTER (TSetPipelineDynamicSpecCommand, "set_pipeline_dynamic_spec", Structured, Null, true, false, ApiVersion4); + REGISTER (TRemovePipelineDynamicSpecCommand, "remove_pipeline_dynamic_spec", Null, Null, true, false, ApiVersion4); + REGISTER (TStartPipelineCommand, "start_pipeline", Null, Structured, false, false, ApiVersion4); + REGISTER (TStopPipelineCommand, "stop_pipeline", Null, Structured, false, false, ApiVersion4); + REGISTER (TPausePipelineCommand, "pause_pipeline", Null, Structured, false, false, ApiVersion4); if (Config_->EnableInternalCommands) { REGISTER_ALL(TReadHunksCommand, "read_hunks", Null, Structured, false, true ); diff --git a/yt/yt/client/driver/flow_commands.cpp b/yt/yt/client/driver/flow_commands.cpp index c0543f4ad2..4b5d84bfd5 100644 --- a/yt/yt/client/driver/flow_commands.cpp +++ b/yt/yt/client/driver/flow_commands.cpp @@ -1,36 +1,286 @@ #include "flow_commands.h" +#include <yt/yt/core/ytree/fluent.h> +#include <yt/yt/core/ytree/ypath_client.h> + namespace NYT::NDriver { using namespace NConcurrency; +using namespace NYTree; +using namespace NYPath; +using namespace NYson; +using namespace NApi; //////////////////////////////////////////////////////////////////////////////// -void TStartPipelineCommand::Register(TRegistrar registrar) +namespace { + +void ExecuteGetPipelineSpecCommand( + const ICommandContextPtr& context, + const TYPath& specPath, + const auto& specGetterOptions, + auto specGetter) { - registrar.Parameter("pipeline_path", &TThis::PipelinePath); + auto client = context->GetClient(); + auto result = WaitFor(specGetter(client, specGetterOptions)) + .ValueOrThrow(); + + auto spec = SyncYPathGet(ConvertToNode(result.Spec), specPath); + + ProduceOutput(context, [&] (NYson::IYsonConsumer* consumer) { + BuildYsonFluently(consumer) + .BeginMap() + .Item("spec").Value(spec) + .Item("version").Value(result.Version) + .EndMap(); + }); } -void TStartPipelineCommand::DoExecute(ICommandContextPtr context) +void ExecuteSetPipelineSpecCommand( + const ICommandContextPtr& context, + const TYPath& specPath, + const auto& specGetterOptions, + auto specGetter, + const auto& specSetterOptions, + auto specSetter) { auto client = context->GetClient(); - WaitFor(client->StartPipeline(PipelinePath)) - .ThrowOnError(); + auto spec = context->ConsumeInputValue(); - ProduceEmptyOutput(context); + auto setResult = [&] { + if (specPath.empty()) { + return WaitFor(specSetter(client, spec, specSetterOptions)) + .ValueOrThrow(); + } else { + auto getResult = WaitFor(specGetter(client, specGetterOptions)) + .ValueOrThrow(); + + if (specSetterOptions.ExpectedVersion && getResult.Version != *specSetterOptions.ExpectedVersion) { + THROW_ERROR_EXCEPTION( + NFlow::EErrorCode::SpecVersionMismatch, + "Spec version mismatch: expected %v, got %v", + *specSetterOptions.ExpectedVersion, + getResult.Version); + } + + auto fullSpec = ConvertToNode(getResult.Spec); + SyncYPathSet(fullSpec, specPath, spec); + + auto adjustedOptions = specSetterOptions; + adjustedOptions.ExpectedVersion = getResult.Version; + return WaitFor(specSetter(client, ConvertToYsonString(fullSpec), adjustedOptions)) + .ValueOrThrow(); + } + }(); + + ProduceOutput(context, [&] (NYson::IYsonConsumer* consumer) { + BuildYsonFluently(consumer) + .BeginMap() + .Item("version").Value(setResult.Version) + .EndMap(); + }); +} + +void ExecuteRemovePipelineSpecCommand( + const ICommandContextPtr& context, + const TYPath& specPath, + const auto& specGetterOptions, + auto specGetter, + const auto& specSetterOptions, + auto specSetter) +{ + auto client = context->GetClient(); + auto spec = context->ConsumeInputValue(); + + auto getResult = WaitFor(specGetter(client, specGetterOptions)) + .ValueOrThrow(); + + if (specSetterOptions.ExpectedVersion && getResult.Version != *specSetterOptions.ExpectedVersion) { + THROW_ERROR_EXCEPTION( + NFlow::EErrorCode::SpecVersionMismatch, + "Spec version mismatch: expected %v, got %v", + *specSetterOptions.ExpectedVersion, + getResult.Version); + } + + auto fullSpec = ConvertToNode(getResult.Spec); + SyncYPathRemove(fullSpec, specPath); + + auto adjustedOptions = specSetterOptions; + adjustedOptions.ExpectedVersion = getResult.Version; + auto setResult = WaitFor(specSetter(client, ConvertToYsonString(fullSpec), adjustedOptions)) + .ValueOrThrow(); + + ProduceOutput(context, [&] (NYson::IYsonConsumer* consumer) { + BuildYsonFluently(consumer) + .BeginMap() + .Item("version").Value(setResult.Version) + .EndMap(); + }); } +} // namespace + //////////////////////////////////////////////////////////////////////////////// -void TStopPipelineCommand::Register(TRegistrar registrar) +void TPipelineCommandBase::Register(TRegistrar registrar) { registrar.Parameter("pipeline_path", &TThis::PipelinePath); } -void TStopPipelineCommand::DoExecute(ICommandContextPtr context) +//////////////////////////////////////////////////////////////////////////////// + +void TGetPipelineSpecCommand::Register(TRegistrar registrar) +{ + registrar.Parameter("spec_path", &TThis::SpecPath) + .Default(); +} + +void TGetPipelineSpecCommand::DoExecute(ICommandContextPtr context) +{ + ExecuteGetPipelineSpecCommand( + context, + SpecPath, + Options, + [&] (const auto& client, const auto& options) { return client->GetPipelineSpec(PipelinePath, options); }); +} + +//////////////////////////////////////////////////////////////////////////////// + +void TSetPipelineSpecCommand::Register(TRegistrar registrar) +{ + registrar.Parameter("spec_path", &TThis::SpecPath) + .Default(); + registrar.ParameterWithUniversalAccessor<bool>( + "force", + [] (TThis* command) -> auto& { + return command->Options.Force; + }) + .Optional(/*init*/ false); + registrar.ParameterWithUniversalAccessor<std::optional<NFlow::TVersion>>( + "expected_version", + [] (TThis* command) -> auto& { + return command->Options.ExpectedVersion; + }) + .Optional(/*init*/ false); +} + +void TSetPipelineSpecCommand::DoExecute(ICommandContextPtr context) +{ + ExecuteSetPipelineSpecCommand( + context, + SpecPath, + TGetPipelineSpecOptions(), + [&] (const auto& client, const auto& options) { return client->GetPipelineSpec(PipelinePath, options); }, + Options, + [&] (const auto& client, const auto& spec, const auto& options) { return client->SetPipelineSpec(PipelinePath, spec, options); }); +} + +//////////////////////////////////////////////////////////////////////////////// + +void TRemovePipelineSpecCommand::Register(TRegistrar registrar) +{ + registrar.Parameter("spec_path", &TThis::SpecPath); + registrar.ParameterWithUniversalAccessor<bool>( + "force", + [] (TThis* command) -> auto& { + return command->Options.Force; + }) + .Optional(/*init*/ false); + registrar.ParameterWithUniversalAccessor<std::optional<NFlow::TVersion>>( + "expected_version", + [] (TThis* command) -> auto& { + return command->Options.ExpectedVersion; + }) + .Optional(/*init*/ false); +} + +void TRemovePipelineSpecCommand::DoExecute(ICommandContextPtr context) +{ + ExecuteRemovePipelineSpecCommand( + context, + SpecPath, + TGetPipelineSpecOptions(), + [&] (const auto& client, const auto& options) { return client->GetPipelineSpec(PipelinePath, options); }, + Options, + [&] (const auto& client, const auto& spec, const auto& options) { return client->SetPipelineSpec(PipelinePath, spec, options); }); +} + +//////////////////////////////////////////////////////////////////////////////// + +void TGetPipelineDynamicSpecCommand::Register(TRegistrar registrar) +{ + registrar.Parameter("spec_path", &TThis::SpecPath) + .Default(); +} + +void TGetPipelineDynamicSpecCommand::DoExecute(ICommandContextPtr context) +{ + ExecuteGetPipelineSpecCommand( + context, + SpecPath, + Options, + [&] (const auto& client, const auto& options) { return client->GetPipelineDynamicSpec(PipelinePath, options); }); +} + +//////////////////////////////////////////////////////////////////////////////// + +void TSetPipelineDynamicSpecCommand::Register(TRegistrar registrar) +{ + registrar.Parameter("spec_path", &TThis::SpecPath) + .Default(); + registrar.ParameterWithUniversalAccessor<std::optional<NFlow::TVersion>>( + "expected_version", + [] (TThis* command) -> auto& { + return command->Options.ExpectedVersion; + }) + .Optional(/*init*/ false); +} + +void TSetPipelineDynamicSpecCommand::DoExecute(ICommandContextPtr context) +{ + ExecuteSetPipelineSpecCommand( + context, + SpecPath, + TGetPipelineDynamicSpecOptions(), + [&] (const auto& client, const auto& options) { return client->GetPipelineDynamicSpec(PipelinePath, options); }, + Options, + [&] (const auto& client, const auto& spec, const auto& options) { return client->SetPipelineDynamicSpec(PipelinePath, spec, options); }); +} + +//////////////////////////////////////////////////////////////////////////////// + +void TRemovePipelineDynamicSpecCommand::Register(TRegistrar registrar) +{ + registrar.Parameter("spec_path", &TThis::SpecPath); + registrar.ParameterWithUniversalAccessor<std::optional<NFlow::TVersion>>( + "expected_version", + [] (TThis* command) -> auto& { + return command->Options.ExpectedVersion; + }) + .Optional(/*init*/ false); +} + +void TRemovePipelineDynamicSpecCommand::DoExecute(ICommandContextPtr context) +{ + ExecuteRemovePipelineSpecCommand( + context, + SpecPath, + TGetPipelineDynamicSpecOptions(), + [&] (const auto& client, const auto& options) { return client->GetPipelineDynamicSpec(PipelinePath, options); }, + Options, + [&] (const auto& client, const auto& spec, const auto& options) { return client->SetPipelineDynamicSpec(PipelinePath, spec, options); }); +} + +//////////////////////////////////////////////////////////////////////////////// + +void TStartPipelineCommand::Register(TRegistrar /*registrar*/) +{ } + +void TStartPipelineCommand::DoExecute(ICommandContextPtr context) { auto client = context->GetClient(); - WaitFor(client->StopPipeline(PipelinePath)) + WaitFor(client->StartPipeline(PipelinePath, Options)) .ThrowOnError(); ProduceEmptyOutput(context); @@ -38,15 +288,27 @@ void TStopPipelineCommand::DoExecute(ICommandContextPtr context) //////////////////////////////////////////////////////////////////////////////// -void TPausePipelineCommand::Register(TRegistrar registrar) +void TStopPipelineCommand::Register(TRegistrar /*registrar*/) +{ } + +void TStopPipelineCommand::DoExecute(ICommandContextPtr context) { - registrar.Parameter("pipeline_path", &TThis::PipelinePath); + auto client = context->GetClient(); + WaitFor(client->StopPipeline(PipelinePath, Options)) + .ThrowOnError(); + + ProduceEmptyOutput(context); } +//////////////////////////////////////////////////////////////////////////////// + +void TPausePipelineCommand::Register(TRegistrar /*registrar*/) +{ } + void TPausePipelineCommand::DoExecute(ICommandContextPtr context) { auto client = context->GetClient(); - WaitFor(client->PausePipeline(PipelinePath)) + WaitFor(client->PausePipeline(PipelinePath, Options)) .ThrowOnError(); ProduceEmptyOutput(context); diff --git a/yt/yt/client/driver/flow_commands.h b/yt/yt/client/driver/flow_commands.h index c6beb43dda..dd798adfcb 100644 --- a/yt/yt/client/driver/flow_commands.h +++ b/yt/yt/client/driver/flow_commands.h @@ -8,8 +8,125 @@ namespace NYT::NDriver { //////////////////////////////////////////////////////////////////////////////// +class TPipelineCommandBase + : public virtual NYTree::TYsonStructLite +{ +public: + REGISTER_YSON_STRUCT_LITE(TPipelineCommandBase); + + static void Register(TRegistrar registrar); + +protected: + NYPath::TYPath PipelinePath; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TGetPipelineSpecCommand + : public TTypedCommand<NApi::TGetPipelineSpecOptions> + , public TPipelineCommandBase +{ +public: + REGISTER_YSON_STRUCT_LITE(TGetPipelineSpecCommand); + + static void Register(TRegistrar registrar); + +private: + NYPath::TYPath SpecPath; + + void DoExecute(ICommandContextPtr context) override; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TSetPipelineSpecCommand + : public TTypedCommand<NApi::TSetPipelineSpecOptions> + , public TPipelineCommandBase +{ +public: + REGISTER_YSON_STRUCT_LITE(TSetPipelineSpecCommand); + + static void Register(TRegistrar registrar); + +private: + NYPath::TYPath SpecPath; + + void DoExecute(ICommandContextPtr context) override; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TRemovePipelineSpecCommand + : public TTypedCommand<NApi::TSetPipelineSpecOptions> + , public TPipelineCommandBase +{ +public: + REGISTER_YSON_STRUCT_LITE(TRemovePipelineSpecCommand); + + static void Register(TRegistrar registrar); + +private: + NYPath::TYPath SpecPath; + + void DoExecute(ICommandContextPtr context) override; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TGetPipelineDynamicSpecCommand + : public TTypedCommand<NApi::TGetPipelineDynamicSpecOptions> + , public TPipelineCommandBase +{ +public: + REGISTER_YSON_STRUCT_LITE(TGetPipelineDynamicSpecCommand); + + static void Register(TRegistrar registrar); + +private: + NYPath::TYPath SpecPath; + + void DoExecute(ICommandContextPtr context) override; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TSetPipelineDynamicSpecCommand + : public TTypedCommand<NApi::TSetPipelineDynamicSpecOptions> + , public TPipelineCommandBase +{ +public: + REGISTER_YSON_STRUCT_LITE(TSetPipelineDynamicSpecCommand); + + static void Register(TRegistrar registrar); + +private: + NYPath::TYPath SpecPath; + + void DoExecute(ICommandContextPtr context) override; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TRemovePipelineDynamicSpecCommand + : public TTypedCommand<NApi::TSetPipelineDynamicSpecOptions> + , public TPipelineCommandBase +{ +public: + REGISTER_YSON_STRUCT_LITE(TRemovePipelineDynamicSpecCommand); + + static void Register(TRegistrar registrar); + +private: + NYPath::TYPath SpecPath; + + void DoExecute(ICommandContextPtr context) override; +}; + +//////////////////////////////////////////////////////////////////////////////// + class TStartPipelineCommand : public TTypedCommand<NApi::TStartPipelineOptions> + , public TPipelineCommandBase { public: REGISTER_YSON_STRUCT_LITE(TStartPipelineCommand); @@ -17,8 +134,6 @@ public: static void Register(TRegistrar registrar); private: - NYPath::TYPath PipelinePath; - void DoExecute(ICommandContextPtr context) override; }; @@ -26,6 +141,7 @@ private: class TStopPipelineCommand : public TTypedCommand<NApi::TStopPipelineOptions> + , public TPipelineCommandBase { public: REGISTER_YSON_STRUCT_LITE(TStopPipelineCommand); @@ -33,15 +149,14 @@ public: static void Register(TRegistrar registrar); private: - NYPath::TYPath PipelinePath; - void DoExecute(ICommandContextPtr context) override; }; //////////////////////////////////////////////////////////////////////////////// class TPausePipelineCommand - : public TTypedCommand<NApi::TStopPipelineOptions> + : public TTypedCommand<NApi::TPausePipelineOptions> + , public TPipelineCommandBase { public: REGISTER_YSON_STRUCT_LITE(TPausePipelineCommand); @@ -49,8 +164,6 @@ public: static void Register(TRegistrar registrar); private: - NYPath::TYPath PipelinePath; - void DoExecute(ICommandContextPtr context) override; }; @@ -58,6 +171,7 @@ private: class TGetPipelineStatusCommand : public TTypedCommand<NApi::TGetPipelineStatusOptions> + , public TPipelineCommandBase { public: REGISTER_YSON_STRUCT_LITE(TGetPipelineStatusCommand); @@ -65,8 +179,6 @@ public: static void Register(TRegistrar registrar); private: - NYPath::TYPath PipelinePath; - void DoExecute(ICommandContextPtr context) override; }; diff --git a/yt/yt/client/federated/client.cpp b/yt/yt/client/federated/client.cpp index cd3e0dd5c9..a90d324510 100644 --- a/yt/yt/client/federated/client.cpp +++ b/yt/yt/client/federated/client.cpp @@ -286,6 +286,8 @@ public: TFuture<NYson::TYsonString> ListNode(const NYPath::TYPath&, const TListNodeOptions&) override; TFuture<bool> NodeExists(const NYPath::TYPath&, const TNodeExistsOptions&) override; + TFuture<std::vector<TListQueueConsumerRegistrationsResult>> ListQueueConsumerRegistrations(const std::optional<NYPath::TRichYPath>&, const std::optional<NYPath::TRichYPath>&, const TListQueueConsumerRegistrationsOptions&) override; + const NTabletClient::ITableMountCachePtr& GetTableMountCache() override; TFuture<std::vector<TTabletInfo>> GetTabletInfos(const NYPath::TYPath&, const std::vector<int>&, const TGetTabletInfosOptions&) override; @@ -329,7 +331,6 @@ public: // IClient unsupported methods. UNIMPLEMENTED_METHOD(TFuture<void>, RegisterQueueConsumer, (const NYPath::TRichYPath&, const NYPath::TRichYPath&, bool, const TRegisterQueueConsumerOptions&)); UNIMPLEMENTED_METHOD(TFuture<void>, UnregisterQueueConsumer, (const NYPath::TRichYPath&, const NYPath::TRichYPath&, const TUnregisterQueueConsumerOptions&)); - UNIMPLEMENTED_METHOD(TFuture<std::vector<TListQueueConsumerRegistrationsResult>>, ListQueueConsumerRegistrations, (const std::optional<NYPath::TRichYPath>&, const std::optional<NYPath::TRichYPath>&, const TListQueueConsumerRegistrationsOptions&)); UNIMPLEMENTED_METHOD(const NChaosClient::IReplicationCardCachePtr&, GetReplicationCardCache, ()); UNIMPLEMENTED_METHOD(TFuture<void>, MountTable, (const NYPath::TYPath&, const TMountTableOptions&)); UNIMPLEMENTED_METHOD(TFuture<void>, UnmountTable, (const NYPath::TYPath&, const TUnmountTableOptions&)); @@ -667,6 +668,7 @@ CLIENT_METHOD_IMPL(NYson::TYsonString, ListNode, (const NYPath::TYPath&, const T CLIENT_METHOD_IMPL(bool, NodeExists, (const NYPath::TYPath&, const TNodeExistsOptions&)); CLIENT_METHOD_IMPL(std::vector<TTabletInfo>, GetTabletInfos, (const NYPath::TYPath&, const std::vector<int>&, const TGetTabletInfosOptions&)); CLIENT_METHOD_IMPL(NChaosClient::TReplicationCardPtr, GetReplicationCard, (NChaosClient::TReplicationCardId, const TGetReplicationCardOptions&)); +CLIENT_METHOD_IMPL(std::vector<TListQueueConsumerRegistrationsResult>, ListQueueConsumerRegistrations, (const std::optional<NYPath::TRichYPath>&, const std::optional<NYPath::TRichYPath>&, const TListQueueConsumerRegistrationsOptions&)); const NTabletClient::ITableMountCachePtr& TClient::GetTableMountCache() { diff --git a/yt/yt/client/job_tracker_client/public.h b/yt/yt/client/job_tracker_client/public.h index 5e1886f458..d67e273715 100644 --- a/yt/yt/client/job_tracker_client/public.h +++ b/yt/yt/client/job_tracker_client/public.h @@ -19,7 +19,7 @@ extern const TOperationId NullOperationId; //////////////////////////////////////////////////////////////////////////////// // NB: Please keep the range of values small as this type -// is used as a key of TEnumIndexedVector. +// is used as a key of TEnumIndexedArray. DEFINE_ENUM(EJobType, // Scheduler jobs ((Map) ( 1)) @@ -58,7 +58,7 @@ constexpr auto FirstMasterJobType = EJobType::ReplicateChunk; constexpr auto LastMasterJobType = EJobType::ReincarnateChunk; // NB: Please keep the range of values small as this type -// is used as a key of TEnumIndexedVector. +// is used as a key of TEnumIndexedArray. DEFINE_ENUM(EJobState, ((Waiting) (0)) ((Running) (1)) diff --git a/yt/yt/client/table_client/blob_reader.cpp b/yt/yt/client/table_client/blob_reader.cpp index f40e28f031..551878b805 100644 --- a/yt/yt/client/table_client/blob_reader.cpp +++ b/yt/yt/client/table_client/blob_reader.cpp @@ -100,7 +100,7 @@ private: i64 Index_ = 0; i64 NextPartIndex_; - TEnumIndexedVector<EColumnType, std::optional<size_t>> ColumnIndex_; + TEnumIndexedArray<EColumnType, std::optional<size_t>> ColumnIndex_; TSharedRef ProcessRow() { diff --git a/yt/yt/client/table_client/helpers.cpp b/yt/yt/client/table_client/helpers.cpp index 9e33a43949..c19e217ad9 100644 --- a/yt/yt/client/table_client/helpers.cpp +++ b/yt/yt/client/table_client/helpers.cpp @@ -562,7 +562,7 @@ void ToUnversionedValue( void FromUnversionedValue(NYson::TYsonStringBuf* value, TUnversionedValue unversionedValue) { - if (unversionedValue.Type != EValueType::Any) { + if (!IsAnyOrComposite(unversionedValue.Type)) { THROW_ERROR_EXCEPTION("Cannot parse YSON string from %Qlv", unversionedValue.Type); } diff --git a/yt/yt/client/tablet_client/table_mount_cache.h b/yt/yt/client/tablet_client/table_mount_cache.h index bba0a1e0c0..773f641aae 100644 --- a/yt/yt/client/tablet_client/table_mount_cache.h +++ b/yt/yt/client/tablet_client/table_mount_cache.h @@ -96,7 +96,7 @@ struct TTableMountInfo { NYPath::TYPath Path; NObjectClient::TObjectId TableId; - TEnumIndexedVector<ETableSchemaKind, NTableClient::TTableSchemaPtr> Schemas; + TEnumIndexedArray<ETableSchemaKind, NTableClient::TTableSchemaPtr> Schemas; // PhysicalPath points to a physical object, if current object is linked to some other object, then this field will point to the source. // When this field is not supported on the server-side, this path will be equal to object path. diff --git a/yt/yt/core/bus/tcp/config.h b/yt/yt/core/bus/tcp/config.h index 54020c6b08..3695a42093 100644 --- a/yt/yt/core/bus/tcp/config.h +++ b/yt/yt/core/bus/tcp/config.h @@ -40,7 +40,7 @@ public: THashMap<TString, std::vector<NNet::TIP6Network>> Networks; - TEnumIndexedVector<EMultiplexingBand, TMultiplexingBandConfigPtr> MultiplexingBands; + TEnumIndexedArray<EMultiplexingBand, TMultiplexingBandConfigPtr> MultiplexingBands; TTcpDispatcherConfigPtr ApplyDynamic(const TTcpDispatcherDynamicConfigPtr& dynamicConfig) const; @@ -66,7 +66,7 @@ public: std::optional<THashMap<TString, std::vector<NNet::TIP6Network>>> Networks; - std::optional<TEnumIndexedVector<EMultiplexingBand, TMultiplexingBandConfigPtr>> MultiplexingBands; + std::optional<TEnumIndexedArray<EMultiplexingBand, TMultiplexingBandConfigPtr>> MultiplexingBands; //! Used to store TLS/SSL certificate files. std::optional<TString> BusCertsDirectoryPath; diff --git a/yt/yt/core/bus/tcp/dispatcher.h b/yt/yt/core/bus/tcp/dispatcher.h index b4a4a61580..8a64a6af1d 100644 --- a/yt/yt/core/bus/tcp/dispatcher.h +++ b/yt/yt/core/bus/tcp/dispatcher.h @@ -12,6 +12,8 @@ #include <yt/yt/core/ytree/public.h> +#include <library/cpp/yt/misc/enum_indexed_array.h> + namespace NYT::NBus { //////////////////////////////////////////////////////////////////////////////// @@ -27,7 +29,7 @@ struct TBusNetworkCounters final { static constexpr bool EnableHazard = true; - TEnumIndexedVector<EMultiplexingBand, TBusNetworkBandCounters> PerBandCounters; + TEnumIndexedArray<EMultiplexingBand, TBusNetworkBandCounters> PerBandCounters; TBusNetworkStatistics ToStatistics() const; }; diff --git a/yt/yt/core/bus/tcp/dispatcher_impl.h b/yt/yt/core/bus/tcp/dispatcher_impl.h index 80495eaa65..76b01356c7 100644 --- a/yt/yt/core/bus/tcp/dispatcher_impl.h +++ b/yt/yt/core/bus/tcp/dispatcher_impl.h @@ -101,7 +101,7 @@ private: std::atomic<TTosLevel> TosLevel = DefaultTosLevel; }; - TEnumIndexedVector<EMultiplexingBand, TBandDescriptor> BandToDescriptor_; + TEnumIndexedArray<EMultiplexingBand, TBandDescriptor> BandToDescriptor_; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/concurrency/config.cpp b/yt/yt/core/concurrency/config.cpp index c54512e56e..acd8194e2f 100644 --- a/yt/yt/core/concurrency/config.cpp +++ b/yt/yt/core/concurrency/config.cpp @@ -32,10 +32,22 @@ void TPeriodicExecutorOptionsSerializer::Register(TRegistrar registrar) void TRetryingPeriodicExecutorOptionsSerializer::Register(TRegistrar registrar) { - registrar.ExternalClassParameter("periodic", &TThat::Periodic) - .Default(); - registrar.ExternalClassParameter("backoff_strategy", &TThat::BackoffStrategy) - .Default(); + //! NB(arkady-e1ppa): Defaults and preprocessors of derived class + //! override defaults and overrides of base class and base class fields + registrar.ExternalPreprocessor([] (TThat* options) { + *options = TRetryingPeriodicExecutorOptions{ + { + .Period = TDuration::Seconds(5), + .Splay = TDuration::Seconds(1), + .Jitter = 0.0, + }, + { + .MinBackoff = TDuration::Seconds(5), + .MaxBackoff = TDuration::Seconds(60), + .BackoffMultiplier = 2.0, + }, + }; + }); } //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/concurrency/config.h b/yt/yt/core/concurrency/config.h index 24d5383e60..3777d7a8d4 100644 --- a/yt/yt/core/concurrency/config.h +++ b/yt/yt/core/concurrency/config.h @@ -2,8 +2,7 @@ #include "public.h" -// TODO(arkady-e1ppa): Move backoff config+serialization into core/misc/config.h. -#include <yt/yt/core/misc/backoff_strategy_config.h> +#include <yt/yt/core/misc/config.h> #include <yt/yt/core/ytree/yson_struct.h> @@ -28,10 +27,9 @@ struct TPeriodicExecutorOptions //////////////////////////////////////////////////////////////////////////////// struct TRetryingPeriodicExecutorOptions -{ - TPeriodicExecutorOptions Periodic; - TExponentialBackoffOptions BackoffStrategy; -}; + : public TPeriodicExecutorOptions + , public TExponentialBackoffOptions +{ }; //////////////////////////////////////////////////////////////////////////////// @@ -40,7 +38,7 @@ namespace NDetail { //////////////////////////////////////////////////////////////////////////////// class TPeriodicExecutorOptionsSerializer - : public NYTree::TExternalizedYsonStruct + : public virtual NYTree::TExternalizedYsonStruct { public: REGISTER_EXTERNALIZED_YSON_STRUCT(TPeriodicExecutorOptions, TPeriodicExecutorOptionsSerializer); @@ -51,10 +49,15 @@ public: //////////////////////////////////////////////////////////////////////////////// class TRetryingPeriodicExecutorOptionsSerializer - : public NYTree::TExternalizedYsonStruct + : public TPeriodicExecutorOptionsSerializer + , public ::NYT::NDetail::TExponentialBackoffOptionsSerializer { public: - REGISTER_EXTERNALIZED_YSON_STRUCT(TRetryingPeriodicExecutorOptions, TRetryingPeriodicExecutorOptionsSerializer); + REGISTER_DERIVED_EXTERNALIZED_YSON_STRUCT( + TRetryingPeriodicExecutorOptions, + TRetryingPeriodicExecutorOptionsSerializer, + (TPeriodicExecutorOptionsSerializer) + (::NYT::NDetail::TExponentialBackoffOptionsSerializer)); static void Register(TRegistrar registrar); }; diff --git a/yt/yt/core/concurrency/retrying_periodic_executor.cpp b/yt/yt/core/concurrency/retrying_periodic_executor.cpp index f8df164712..3be49c6001 100644 --- a/yt/yt/core/concurrency/retrying_periodic_executor.cpp +++ b/yt/yt/core/concurrency/retrying_periodic_executor.cpp @@ -21,8 +21,8 @@ namespace NDetail { TRetryingInvocationTimePolicy::TRetryingInvocationTimePolicy( const TOptions& options) - : TDefaultInvocationTimePolicy(options.Periodic) - , Backoff_(options.BackoffStrategy) + : TDefaultInvocationTimePolicy(options) + , Backoff_(options) { } void TRetryingInvocationTimePolicy::ProcessResult(TError result) @@ -40,7 +40,7 @@ void TRetryingInvocationTimePolicy::ProcessResult(TError result) bool TRetryingInvocationTimePolicy::ShouldKickstart(const TOptions& newOptions) { - return ShouldKickstart(newOptions.Periodic, std::nullopt); + return ShouldKickstart(newOptions, std::nullopt); } bool TRetryingInvocationTimePolicy::ShouldKickstart( @@ -54,7 +54,7 @@ bool TRetryingInvocationTimePolicy::ShouldKickstart( void TRetryingInvocationTimePolicy::SetOptions(TOptions newOptions) { - SetOptions(newOptions.Periodic, newOptions.BackoffStrategy); + SetOptions(newOptions, newOptions); } void TRetryingInvocationTimePolicy::SetOptions( @@ -69,6 +69,9 @@ void TRetryingInvocationTimePolicy::SetOptions( CachedBackoffMultiplier_.store( backoffOptions->BackoffMultiplier, std::memory_order::relaxed); + CachedBackoffJitter_.store( + backoffOptions->BackoffJitter, + std::memory_order::relaxed); Backoff_.UpdateOptions(*backoffOptions); } @@ -93,11 +96,15 @@ void TRetryingInvocationTimePolicy::Reset() Backoff_.Restart(); } -TDuration TRetryingInvocationTimePolicy::GetBackoffTimeEstimate() const +std::tuple<TDuration, TDuration> TRetryingInvocationTimePolicy::GetBackoffInterval() const { - return + auto backoffMedian = CachedBackoffDuration_.load(std::memory_order::relaxed) * CachedBackoffMultiplier_.load(std::memory_order::relaxed); + + auto backoffJitter = CachedBackoffJitter_.load(std::memory_order::relaxed); + + return std::tuple(backoffMedian * (1 - backoffJitter), backoffMedian * (1 + backoffJitter)); } bool TRetryingInvocationTimePolicy::IsInBackoffMode() const @@ -149,9 +156,9 @@ TRetryingPeriodicExecutor::TRetryingPeriodicExecutor( backoffOptions) { } -TDuration TRetryingPeriodicExecutor::GetBackoffTimeEstimate() const +std::tuple<TDuration, TDuration> TRetryingPeriodicExecutor::GetBackoffInterval() const { - return TBase::GetBackoffTimeEstimate(); + return TBase::GetBackoffInterval(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/concurrency/retrying_periodic_executor.h b/yt/yt/core/concurrency/retrying_periodic_executor.h index 2bc1b2f3bf..6cb6d36a3e 100644 --- a/yt/yt/core/concurrency/retrying_periodic_executor.h +++ b/yt/yt/core/concurrency/retrying_periodic_executor.h @@ -6,7 +6,7 @@ #include <yt/yt/core/actions/callback.h> #include <yt/yt/core/actions/future.h> -#include <yt/yt/core/misc/backoff_strategy_config.h> +#include <yt/yt/core/misc/config.h> namespace NYT::NConcurrency { @@ -47,12 +47,13 @@ public: void Reset(); - TDuration GetBackoffTimeEstimate() const; + std::tuple<TDuration, TDuration> GetBackoffInterval() const; private: //! Used for backoff time estimation std::atomic<TDuration> CachedBackoffDuration_; std::atomic<double> CachedBackoffMultiplier_; + std::atomic<double> CachedBackoffJitter_; TBackoffStrategy Backoff_; @@ -86,7 +87,7 @@ public: TExponentialBackoffOptions backoffOptions, std::optional<TDuration> period = {}); - TDuration GetBackoffTimeEstimate() const; + std::tuple<TDuration, TDuration> GetBackoffInterval() const; private: using TBase = NDetail::TPeriodicExecutorBase<NDetail::TRetryingInvocationTimePolicy>; diff --git a/yt/yt/core/misc/backoff_strategy.cpp b/yt/yt/core/misc/backoff_strategy.cpp index 0bb28fdfa4..678a782a4b 100644 --- a/yt/yt/core/misc/backoff_strategy.cpp +++ b/yt/yt/core/misc/backoff_strategy.cpp @@ -20,19 +20,6 @@ double BackoffStrategyDefaultRandomGenerator() //////////////////////////////////////////////////////////////////////////////// -TConstantBackoffOptions::operator TExponentialBackoffOptions() const -{ - return TExponentialBackoffOptions{ - .InvocationCount = InvocationCount, - .MinBackoff = Backoff, - .MaxBackoff = Backoff, - .BackoffMultiplier = 1.0, - .BackoffJitter = BackoffJitter - }; -} - -//////////////////////////////////////////////////////////////////////////////// - TBackoffStrategy::TBackoffStrategy(const TExponentialBackoffOptions& options) : Options_(options) { diff --git a/yt/yt/core/misc/backoff_strategy.h b/yt/yt/core/misc/backoff_strategy.h index 3a05d09354..d8549de65c 100644 --- a/yt/yt/core/misc/backoff_strategy.h +++ b/yt/yt/core/misc/backoff_strategy.h @@ -1,44 +1,12 @@ #pragma once -#include "jitter.h" +#include "config.h" #include "public.h" namespace NYT { //////////////////////////////////////////////////////////////////////////////// -struct TExponentialBackoffOptions -{ - static constexpr int DefaultInvocationCount = 10; - static constexpr auto DefaultMinBackoff = TDuration::Seconds(1); - static constexpr auto DefaultMaxBackoff = TDuration::Seconds(5); - static constexpr double DefaultBackoffMultiplier = 1.5; - static constexpr double DefaultBackoffJitter = 0.1; - - int InvocationCount = DefaultInvocationCount; - TDuration MinBackoff = DefaultMinBackoff; - TDuration MaxBackoff = DefaultMaxBackoff; - double BackoffMultiplier = DefaultBackoffMultiplier; - double BackoffJitter = DefaultBackoffJitter; -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct TConstantBackoffOptions -{ - static constexpr int DefaultInvocationCount = 10; - static constexpr auto DefaultBackoff = TDuration::Seconds(3); - static constexpr double DefaultBackoffJitter = 0.1; - - int InvocationCount = DefaultInvocationCount; - TDuration Backoff = DefaultBackoff; - double BackoffJitter = DefaultBackoffJitter; - - operator TExponentialBackoffOptions() const; -}; - -//////////////////////////////////////////////////////////////////////////////// - //! Implements exponential backoffs with jitter. //! Expected use after restart is Next() -> GetBackoff() (not the other way around). class TBackoffStrategy diff --git a/yt/yt/core/misc/backoff_strategy_config.cpp b/yt/yt/core/misc/backoff_strategy_config.cpp deleted file mode 100644 index 7f02bb9f62..0000000000 --- a/yt/yt/core/misc/backoff_strategy_config.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "backoff_strategy_config.h" - -namespace NYT { - -//////////////////////////////////////////////////////////////////////////////// - -void TExponentialBackoffOptionsSerializer::Register(TRegistrar registrar) -{ - registrar.ExternalClassParameter("invocation_count", &TThat::InvocationCount) - .Alias("retry_count") - .Default(TThat::DefaultInvocationCount); - - registrar.ExternalClassParameter("min_backoff", &TThat::MinBackoff) - .Default(TThat::DefaultMinBackoff); - - registrar.ExternalClassParameter("max_backoff", &TThat::MaxBackoff) - .Default(TThat::DefaultMaxBackoff); - - registrar.ExternalClassParameter("backoff_multiplier", &TThat::BackoffMultiplier) - .Default(TThat::DefaultBackoffMultiplier) - .GreaterThanOrEqual(1.0); - - registrar.ExternalClassParameter("backoff_jitter", &TThat::BackoffJitter) - .Default(TThat::DefaultBackoffJitter); -} - -//////////////////////////////////////////////////////////////////////////////// - -void TConstantBackoffOptionsSerializer::Register(TRegistrar registrar) -{ - registrar.ExternalClassParameter("invocation_count", &TThat::InvocationCount) - .Alias("retry_count") - .Default(TThat::DefaultInvocationCount); - - registrar.ExternalClassParameter("backoff", &TThat::Backoff) - .Default(TThat::DefaultBackoff); - - registrar.ExternalClassParameter("backoff_jitter", &TThat::BackoffJitter) - .Default(TThat::DefaultBackoffJitter); -} - -//////////////////////////////////////////////////////////////////////////////// - -} // namespace NYT diff --git a/yt/yt/core/misc/backoff_strategy_config.h b/yt/yt/core/misc/backoff_strategy_config.h deleted file mode 100644 index 47038589ff..0000000000 --- a/yt/yt/core/misc/backoff_strategy_config.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "backoff_strategy.h" - -#include <yt/yt/core/ytree/yson_struct.h> - -namespace NYT { - -//////////////////////////////////////////////////////////////////////////////// - -class TExponentialBackoffOptionsSerializer - : public NYTree::TExternalizedYsonStruct -{ -public: - REGISTER_EXTERNALIZED_YSON_STRUCT(TExponentialBackoffOptions, TExponentialBackoffOptionsSerializer); - - static void Register(TRegistrar registrar); -}; - -ASSIGN_EXTERNAL_YSON_SERIALIZER(TExponentialBackoffOptions, TExponentialBackoffOptionsSerializer); - -//////////////////////////////////////////////////////////////////////////////// - -class TConstantBackoffOptionsSerializer - : public NYTree::TExternalizedYsonStruct -{ -public: - REGISTER_EXTERNALIZED_YSON_STRUCT(TConstantBackoffOptions, TConstantBackoffOptionsSerializer); - - static void Register(TRegistrar registrar); -}; - -ASSIGN_EXTERNAL_YSON_SERIALIZER(TConstantBackoffOptions, TConstantBackoffOptionsSerializer); - -//////////////////////////////////////////////////////////////////////////////// - -} // namespace NYT diff --git a/yt/yt/core/misc/config.cpp b/yt/yt/core/misc/config.cpp index a33279b9b0..c888012afe 100644 --- a/yt/yt/core/misc/config.cpp +++ b/yt/yt/core/misc/config.cpp @@ -4,6 +4,19 @@ namespace NYT { //////////////////////////////////////////////////////////////////////////////// +TConstantBackoffOptions::operator TExponentialBackoffOptions() const +{ + return TExponentialBackoffOptions{ + .InvocationCount = InvocationCount, + .MinBackoff = Backoff, + .MaxBackoff = Backoff, + .BackoffMultiplier = 1.0, + .BackoffJitter = BackoffJitter + }; +} + +//////////////////////////////////////////////////////////////////////////////// + void TLogDigestConfig::Register(TRegistrar registrar) { registrar.Parameter("relative_precision", &TThis::RelativePrecision) @@ -128,4 +141,45 @@ void TAdaptiveHedgingManagerConfig::Register(TRegistrar registrar) //////////////////////////////////////////////////////////////////////////////// +namespace NDetail { + +void TExponentialBackoffOptionsSerializer::Register(TRegistrar registrar) +{ + registrar.ExternalClassParameter("invocation_count", &TThat::InvocationCount) + .Alias("retry_count") + .Default(TThat::DefaultInvocationCount); + + registrar.ExternalClassParameter("min_backoff", &TThat::MinBackoff) + .Default(TThat::DefaultMinBackoff); + + registrar.ExternalClassParameter("max_backoff", &TThat::MaxBackoff) + .Default(TThat::DefaultMaxBackoff); + + registrar.ExternalClassParameter("backoff_multiplier", &TThat::BackoffMultiplier) + .Default(TThat::DefaultBackoffMultiplier) + .GreaterThanOrEqual(1.0); + + registrar.ExternalClassParameter("backoff_jitter", &TThat::BackoffJitter) + .Default(TThat::DefaultBackoffJitter); +} + +//////////////////////////////////////////////////////////////////////////////// + +void TConstantBackoffOptionsSerializer::Register(TRegistrar registrar) +{ + registrar.ExternalClassParameter("invocation_count", &TThat::InvocationCount) + .Alias("retry_count") + .Default(TThat::DefaultInvocationCount); + + registrar.ExternalClassParameter("backoff", &TThat::Backoff) + .Default(TThat::DefaultBackoff); + + registrar.ExternalClassParameter("backoff_jitter", &TThat::BackoffJitter) + .Default(TThat::DefaultBackoffJitter); +} + +} // namespace NDetail + +//////////////////////////////////////////////////////////////////////////////// + } // namespace NYT diff --git a/yt/yt/core/misc/config.h b/yt/yt/core/misc/config.h index bf10114bf0..7b928e2151 100644 --- a/yt/yt/core/misc/config.h +++ b/yt/yt/core/misc/config.h @@ -10,6 +10,38 @@ namespace NYT { //////////////////////////////////////////////////////////////////////////////// +struct TExponentialBackoffOptions +{ + static constexpr int DefaultInvocationCount = 10; + static constexpr auto DefaultMinBackoff = TDuration::Seconds(1); + static constexpr auto DefaultMaxBackoff = TDuration::Seconds(5); + static constexpr double DefaultBackoffMultiplier = 1.5; + static constexpr double DefaultBackoffJitter = 0.1; + + int InvocationCount = DefaultInvocationCount; + TDuration MinBackoff = DefaultMinBackoff; + TDuration MaxBackoff = DefaultMaxBackoff; + double BackoffMultiplier = DefaultBackoffMultiplier; + double BackoffJitter = DefaultBackoffJitter; +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct TConstantBackoffOptions +{ + static constexpr int DefaultInvocationCount = 10; + static constexpr auto DefaultBackoff = TDuration::Seconds(3); + static constexpr double DefaultBackoffJitter = 0.1; + + int InvocationCount = DefaultInvocationCount; + TDuration Backoff = DefaultBackoff; + double BackoffJitter = DefaultBackoffJitter; + + operator TExponentialBackoffOptions() const; +}; + +//////////////////////////////////////////////////////////////////////////////// + class TLogDigestConfig : public NYTree::TYsonStruct { @@ -114,4 +146,36 @@ DEFINE_REFCOUNTED_TYPE(TAdaptiveHedgingManagerConfig) //////////////////////////////////////////////////////////////////////////////// +namespace NDetail { + +class TExponentialBackoffOptionsSerializer + : public virtual NYTree::TExternalizedYsonStruct +{ +public: + REGISTER_EXTERNALIZED_YSON_STRUCT(TExponentialBackoffOptions, TExponentialBackoffOptionsSerializer); + + static void Register(TRegistrar registrar); +}; + + +//////////////////////////////////////////////////////////////////////////////// + +class TConstantBackoffOptionsSerializer + : public NYTree::TExternalizedYsonStruct +{ +public: + REGISTER_EXTERNALIZED_YSON_STRUCT(TConstantBackoffOptions, TConstantBackoffOptionsSerializer); + + static void Register(TRegistrar registrar); +}; + + + +} // namespace NDetail + +//////////////////////////////////////////////////////////////////////////////// + } // namespace NYT + +ASSIGN_EXTERNAL_YSON_SERIALIZER(NYT::TExponentialBackoffOptions, NYT::NDetail::TExponentialBackoffOptionsSerializer); +ASSIGN_EXTERNAL_YSON_SERIALIZER(NYT::TConstantBackoffOptions, NYT::NDetail::TConstantBackoffOptionsSerializer); diff --git a/yt/yt/core/misc/protobuf_helpers-inl.h b/yt/yt/core/misc/protobuf_helpers-inl.h index e8d74b6c6f..887d11974a 100644 --- a/yt/yt/core/misc/protobuf_helpers-inl.h +++ b/yt/yt/core/misc/protobuf_helpers-inl.h @@ -337,11 +337,11 @@ typename std::enable_if_t<std::is_trivial_v<TValue>> SetPairValueImpl(TProtoPair template <class TSerializedArray, class T, class E, E Min, E Max> void ToProtoArrayImpl( TSerializedArray* serializedArray, - const TEnumIndexedVector<E, T, Min, Max>& originalArray) + const TEnumIndexedArray<E, T, Min, Max>& originalArray) { serializedArray->Clear(); for (auto key : TEnumTraits<E>::GetDomainValues()) { - if (originalArray.IsDomainValue(key)) { + if (originalArray.IsValidIndex(key)) { const auto& value = originalArray[key]; auto* pair = serializedArray->Add(); pair->set_key(static_cast<i32>(key)); @@ -352,17 +352,17 @@ void ToProtoArrayImpl( template <class T, class E, E Min, E Max, class TSerializedArray> void FromProtoArrayImpl( - TEnumIndexedVector<E, T, Min, Max>* originalArray, + TEnumIndexedArray<E, T, Min, Max>* originalArray, const TSerializedArray& serializedArray) { for (auto key : TEnumTraits<E>::GetDomainValues()) { - if (originalArray->IsDomainValue(key)) { + if (originalArray->IsValidIndex(key)) { (*originalArray)[key] = T{}; } } for (const auto& pair : serializedArray) { const auto& key = static_cast<E>(pair.key()); - if (originalArray->IsDomainValue(key)) { + if (originalArray->IsValidIndex(key)) { FromProto(&(*originalArray)[key], pair.value()); } } diff --git a/yt/yt/core/misc/public.h b/yt/yt/core/misc/public.h index 1577de2203..fa66b2ffef 100644 --- a/yt/yt/core/misc/public.h +++ b/yt/yt/core/misc/public.h @@ -191,10 +191,18 @@ struct TIsInvocable; template <class T, class TRet, bool NoExcept, class... TArgs> struct TIsInvocable<T, TRet(TArgs...) noexcept(NoExcept)> { +private: + static constexpr bool IsInvocable_ = requires (T&& t, TArgs&&... args) { + { std::forward<T>(t)(std::forward<TArgs>(args)...) } -> std::same_as<TRet>; + }; + + static constexpr bool IsNoThrowInvocable_ = requires (T&& t, TArgs&&... args) { + { std::forward<T>(t)(std::forward<TArgs>(args)...) } noexcept; + }; +public: static constexpr bool Value = - NoExcept ? - std::is_nothrow_invocable_r_v<TRet, T, TArgs...> : - std::is_invocable_r_v<TRet, T, TArgs...>; + IsInvocable_ && + (!NoExcept || IsNoThrowInvocable_); }; template <class T, class Sig> diff --git a/yt/yt/core/misc/serialize-inl.h b/yt/yt/core/misc/serialize-inl.h index 5269014db1..6a0948e051 100644 --- a/yt/yt/core/misc/serialize-inl.h +++ b/yt/yt/core/misc/serialize-inl.h @@ -10,6 +10,8 @@ #include <library/cpp/yt/small_containers/compact_flat_map.h> #include <library/cpp/yt/small_containers/compact_set.h> +#include <library/cpp/yt/misc/enum_indexed_array.h> + #include <optional> #include <variant> @@ -1356,17 +1358,17 @@ struct TOptionalListSerializer }; template <class TItemSerializer = TDefaultSerializer> -struct TEnumIndexedVectorSerializer +struct TEnumIndexedArraySerializer { template <class E, class T, class C, E Min, E Max> - static void Save(C& context, const TEnumIndexedVector<E, T, Min, Max>& vector) + static void Save(C& context, const TEnumIndexedArray<E, T, Min, Max>& vector) { using NYT::Save; auto keys = TEnumTraits<E>::GetDomainValues(); size_t count = 0; for (auto key : keys) { - if (!vector.IsDomainValue(key)) { + if (!vector.IsValidIndex(key)) { continue; } ++count; @@ -1375,7 +1377,7 @@ struct TEnumIndexedVectorSerializer TSizeSerializer::Save(context, count); for (auto key : keys) { - if (!vector.IsDomainValue(key)) { + if (!vector.IsValidIndex(key)) { continue; } Save(context, key); @@ -1384,7 +1386,7 @@ struct TEnumIndexedVectorSerializer } template <class E, class T, class C, E Min, E Max> - static void Load(C& context, TEnumIndexedVector<E, T, Min, Max>& vector) + static void Load(C& context, TEnumIndexedArray<E, T, Min, Max>& vector) { if constexpr (std::is_copy_assignable_v<T>) { std::fill(vector.begin(), vector.end(), T()); @@ -1403,7 +1405,7 @@ struct TEnumIndexedVectorSerializer auto key = LoadSuspended<E>(context); SERIALIZATION_DUMP_WRITE(context, "%v =>", key); SERIALIZATION_DUMP_INDENT(context) { - if (!vector.IsDomainValue(key)) { + if (!vector.IsValidIndex(key)) { T dummy; TItemSerializer::Load(context, dummy); } else { @@ -1967,9 +1969,9 @@ struct TSerializerTraits<THashMultiMap<K, V>, C, void> }; template <class E, class T, class C, E Min, E Max> -struct TSerializerTraits<TEnumIndexedVector<E, T, Min, Max>, C, void> +struct TSerializerTraits<TEnumIndexedArray<E, T, Min, Max>, C, void> { - using TSerializer = TEnumIndexedVectorSerializer<>; + using TSerializer = TEnumIndexedArraySerializer<>; }; template <class F, class S, class C> diff --git a/yt/yt/core/rpc/bus/channel.cpp b/yt/yt/core/rpc/bus/channel.cpp index 513fa531c1..e5d04ea83a 100644 --- a/yt/yt/core/rpc/bus/channel.cpp +++ b/yt/yt/core/rpc/bus/channel.cpp @@ -162,7 +162,7 @@ private: bool Terminated = false; }; - TEnumIndexedVector<EMultiplexingBand, TBandBucket> Buckets_; + TEnumIndexedArray<EMultiplexingBand, TBandBucket> Buckets_; std::atomic<bool> TerminationFlag_ = false; TAtomicObject<TError> TerminationError_; diff --git a/yt/yt/core/ya.make b/yt/yt/core/ya.make index fe08f07e71..5bd8822192 100644 --- a/yt/yt/core/ya.make +++ b/yt/yt/core/ya.make @@ -107,7 +107,6 @@ SRCS( misc/arithmetic_formula.cpp GLOBAL misc/assert.cpp misc/backoff_strategy.cpp - misc/backoff_strategy_config.cpp misc/bitmap.cpp misc/bit_packed_unsigned_vector.cpp misc/bit_packing.cpp diff --git a/yt/yt/core/yson/pull_parser_deserialize-inl.h b/yt/yt/core/yson/pull_parser_deserialize-inl.h index c5e39e7df8..9d45eec2a7 100644 --- a/yt/yt/core/yson/pull_parser_deserialize-inl.h +++ b/yt/yt/core/yson/pull_parser_deserialize-inl.h @@ -281,7 +281,7 @@ void Deserialize( template <class E, class T, E Min, E Max> void Deserialize( - TEnumIndexedVector<E, T, Min, Max>& vector, + TEnumIndexedArray<E, T, Min, Max>& vector, TYsonPullParserCursor* cursor, std::enable_if_t<ArePullParserDeserializable<T>(), void*>) { @@ -289,7 +289,7 @@ void Deserialize( auto itemVisitor = [&] (TYsonPullParserCursor* cursor) { auto key = ExtractTo<E>(cursor); - if (!vector.IsDomainValue(key)) { + if (!vector.IsValidIndex(key)) { THROW_ERROR_EXCEPTION("Enum value %Qlv is out of supported range", key); } diff --git a/yt/yt/core/yson/pull_parser_deserialize.h b/yt/yt/core/yson/pull_parser_deserialize.h index 0a03fc775e..20cd57b68a 100644 --- a/yt/yt/core/yson/pull_parser_deserialize.h +++ b/yt/yt/core/yson/pull_parser_deserialize.h @@ -4,12 +4,14 @@ #include "pull_parser.h" +#include <library/cpp/yt/misc/enum_indexed_array.h> + namespace NYT::NYson { //////////////////////////////////////////////////////////////////////////////// -inline void SkipAttributes(TYsonPullParserCursor* cursor); -inline void MaybeSkipAttributes(TYsonPullParserCursor* cursor); +void SkipAttributes(TYsonPullParserCursor* cursor); +void MaybeSkipAttributes(TYsonPullParserCursor* cursor); //////////////////////////////////////////////////////////////////////////////// @@ -17,12 +19,12 @@ namespace NDetail { template <typename T, typename = void> struct TIsPullParserDeserializable - : std::false_type + : public std::false_type { }; template <typename T> struct TIsPullParserDeserializable<T, std::void_t<decltype(Deserialize(std::declval<T&>(), (NYson::TYsonPullParserCursor*)(nullptr)))>> - : std::true_type + : public std::true_type { }; template <typename T> @@ -145,7 +147,7 @@ void Deserialize( template <class E, class T, E Min, E Max> void Deserialize( - TEnumIndexedVector<E, T, Min, Max>& vector, + TEnumIndexedArray<E, T, Min, Max>& vector, TYsonPullParserCursor* cursor, std::enable_if_t<ArePullParserDeserializable<T>(), void*> = nullptr); diff --git a/yt/yt/core/ytalloc/bindings.cpp b/yt/yt/core/ytalloc/bindings.cpp index 33eb077a5b..72b866114d 100644 --- a/yt/yt/core/ytalloc/bindings.cpp +++ b/yt/yt/core/ytalloc/bindings.cpp @@ -127,7 +127,7 @@ private: void PushSmallArenaStatistics( NProfiling::ISensorWriter* writer, size_t rank, - const TEnumIndexedVector<ESmallArenaCounter, ssize_t>& counters) + const TEnumIndexedArray<ESmallArenaCounter, ssize_t>& counters) { NProfiling::TWithTagGuard withTagGuard(writer, "rank", ToString(rank)); PushAllocationCounterStatistics(writer, "/small_arena", counters); @@ -147,7 +147,7 @@ private: void PushLargeArenaStatistics( NProfiling::ISensorWriter* writer, size_t rank, - const TEnumIndexedVector<ELargeArenaCounter, ssize_t>& counters) + const TEnumIndexedArray<ELargeArenaCounter, ssize_t>& counters) { NProfiling::TWithTagGuard withTagGuard(writer, "rank", ToString(rank)); diff --git a/yt/yt/core/ytree/serialize-inl.h b/yt/yt/core/ytree/serialize-inl.h index 74a1ad9c4d..eea8f121b4 100644 --- a/yt/yt/core/ytree/serialize-inl.h +++ b/yt/yt/core/ytree/serialize-inl.h @@ -426,11 +426,11 @@ void Serialize(const C<T...>& value, NYson::IYsonConsumer* consumer) } template <class E, class T, E Min, E Max> -void Serialize(const TEnumIndexedVector<E, T, Min, Max>& vector, NYson::IYsonConsumer* consumer) +void Serialize(const TEnumIndexedArray<E, T, Min, Max>& vector, NYson::IYsonConsumer* consumer) { consumer->OnBeginMap(); for (auto key : TEnumTraits<E>::GetDomainValues()) { - if (!vector.IsDomainValue(key)) { + if (!vector.IsValidIndex(key)) { continue; } const auto& value = vector[key]; @@ -614,13 +614,13 @@ void Deserialize(C<T...>& value, INodePtr node) } template <class E, class T, E Min, E Max> -void Deserialize(TEnumIndexedVector<E, T, Min, Max>& vector, INodePtr node) +void Deserialize(TEnumIndexedArray<E, T, Min, Max>& vector, INodePtr node) { vector = {}; auto mapNode = node->AsMap(); for (const auto& [stringKey, child] : mapNode->GetChildren()) { auto key = ParseEnum<E>(stringKey); - if (!vector.IsDomainValue(key)) { + if (!vector.IsValidIndex(key)) { THROW_ERROR_EXCEPTION("Enum value %Qlv is out of supported range", key); } diff --git a/yt/yt/core/ytree/serialize.h b/yt/yt/core/ytree/serialize.h index 046f5f3e18..ed58a6f934 100644 --- a/yt/yt/core/ytree/serialize.h +++ b/yt/yt/core/ytree/serialize.h @@ -12,6 +12,8 @@ #include <library/cpp/yt/small_containers/compact_vector.h> +#include <library/cpp/yt/misc/enum_indexed_array.h> + #include <optional> namespace NYT::NYTree { @@ -138,9 +140,9 @@ void Serialize(const std::tuple<T...>& value, NYson::IYsonConsumer* consumer); template <template<typename...> class C, class... T, class K = typename C<T...>::key_type> void Serialize(const C<T...>& value, NYson::IYsonConsumer* consumer); -// TEnumIndexedVector +// TEnumIndexedArray template <class E, class T, E Min, E Max> -void Serialize(const TEnumIndexedVector<E, T, Min, Max>& value, NYson::IYsonConsumer* consumer); +void Serialize(const TEnumIndexedArray<E, T, Min, Max>& value, NYson::IYsonConsumer* consumer); // Subtypes of google::protobuf::Message template <class T> @@ -241,9 +243,9 @@ void Deserialize(std::tuple<T...>& value, INodePtr node); template <template<typename...> class C, class... T, class K = typename C<T...>::key_type> void Deserialize(C<T...>& value, INodePtr node); -// TEnumIndexedVector +// TEnumIndexedArray template <class E, class T, E Min, E Max> -void Deserialize(TEnumIndexedVector<E, T, Min, Max>& vector, INodePtr node); +void Deserialize(TEnumIndexedArray<E, T, Min, Max>& vector, INodePtr node); // Subtypes of google::protobuf::Message template <class T> diff --git a/yt/yt/core/ytree/ypath_detail.cpp b/yt/yt/core/ytree/ypath_detail.cpp index bb8aed4797..1cc159b24f 100644 --- a/yt/yt/core/ytree/ypath_detail.cpp +++ b/yt/yt/core/ytree/ypath_detail.cpp @@ -1077,7 +1077,7 @@ void TSupportsAttributes::DoRemoveAttribute(const TYPath& path, bool force) } if (!descriptor->Writable) { - ThrowCannotSetBuiltinAttribute(key); + ThrowCannotRemoveAttribute(key); } permissionValidator.Validate(descriptor->ModifyPermission); diff --git a/yt/yt/flow/lib/client/public.h b/yt/yt/flow/lib/client/public.h index c813f0d5f6..e1812eaa08 100644 --- a/yt/yt/flow/lib/client/public.h +++ b/yt/yt/flow/lib/client/public.h @@ -27,6 +27,10 @@ DEFINE_ENUM(EPipelineState, ((Completed) (6)) ); +YT_DEFINE_ERROR_ENUM( + ((SpecVersionMismatch) (3300)) +); + YT_DEFINE_STRONG_TYPEDEF(TVersion, i64); //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/library/column_converters/column_converter.cpp b/yt/yt/library/column_converters/column_converter.cpp index 40d7a13733..b177657daa 100644 --- a/yt/yt/library/column_converters/column_converter.cpp +++ b/yt/yt/library/column_converters/column_converter.cpp @@ -107,7 +107,7 @@ TConvertedColumnRange TColumnConverters::ConvertRowsToColumns( YT_VERIFY(iterSchema != columnSchema.end()); auto converter = CreateColumnConvert(iterSchema->second, ColumnIds_[offset], offset); auto columns = converter->Convert(rowsValues); - convertedColumnsRange.emplace_back(std::move(columns)); + convertedColumnsRange.push_back(std::move(columns)); } return convertedColumnsRange; } diff --git a/yt/yt/library/column_converters/string_column_converter.cpp b/yt/yt/library/column_converters/string_column_converter.cpp index 68e1732386..f943d02e1c 100644 --- a/yt/yt/library/column_converters/string_column_converter.cpp +++ b/yt/yt/library/column_converters/string_column_converter.cpp @@ -274,9 +274,9 @@ private: } } - TEnumIndexedVector<EUnversionedStringSegmentType, ui64> GetEncodingMethodsCosts() const + TEnumIndexedArray<EUnversionedStringSegmentType, ui64> GetEncodingMethodsCosts() const { - TEnumIndexedVector<EUnversionedStringSegmentType, ui64> costs; + TEnumIndexedArray<EUnversionedStringSegmentType, ui64> costs; for (auto type : TEnumTraits<EUnversionedStringSegmentType>::GetDomainValues()) { costs[type] = GetSpecificEncodingMethodCosts(type); } diff --git a/yt/yt/library/formats/web_json_writer.cpp b/yt/yt/library/formats/web_json_writer.cpp index 582b2291a0..fdab73f878 100644 --- a/yt/yt/library/formats/web_json_writer.cpp +++ b/yt/yt/library/formats/web_json_writer.cpp @@ -343,7 +343,7 @@ private: std::vector<TLogicalTypePtr> Types_; std::vector<std::vector<int>> TableIndexToColumnIdToTypeIndex_; THashMap<std::pair<int, TString>, int> TableIndexAndColumnNameToTypeIndex_; - TEnumIndexedVector<EValueType, int> ValueTypeToTypeIndex_; + TEnumIndexedArray<EValueType, int> ValueTypeToTypeIndex_; private: int GetTypeIndex(int tableIndex, ui16 columnId, TStringBuf columnName, EValueType valueType) diff --git a/yt/yt_proto/yt/client/api/rpc_proxy/proto/api_service.proto b/yt/yt_proto/yt/client/api/rpc_proxy/proto/api_service.proto index 12fa0acd9a..9cab02e727 100644 --- a/yt/yt_proto/yt/client/api/rpc_proxy/proto/api_service.proto +++ b/yt/yt_proto/yt/client/api/rpc_proxy/proto/api_service.proto @@ -589,6 +589,7 @@ message TReqSelectRows optional bytes placeholder_values = 18; // YSON optional bool new_range_inference = 19; optional bool use_canonical_null_relations = 20; + optional bool merge_versioned_rows = 21; optional TSuppressableAccessTrackingOptions suppressable_access_tracking_options = 104; } |