mirror of
https://github.com/darlinghq/darling-libcxx.git
synced 2024-11-23 03:49:42 +00:00
Merge remote-tracking branch 'upstream/master' into HEAD
This commit is contained in:
commit
f1d9f7bb21
@ -1,4 +1,4 @@
|
||||
{
|
||||
"project_id" : "libcxx",
|
||||
"repository.callsign" : "CXX",
|
||||
"conduit_uri" : "https://reviews.llvm.org/"
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ BasedOnStyle: LLVM
|
||||
|
||||
---
|
||||
Language: Cpp
|
||||
Standard: Cpp03
|
||||
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
PointerAlignment: Left
|
||||
|
@ -41,6 +41,10 @@ N: Jonathan B Coe
|
||||
E: jbcoe@me.com
|
||||
D: Implementation of propagate_const.
|
||||
|
||||
N: Glen Joseph Fernandes
|
||||
E: glenjofe@gmail.com
|
||||
D: Implementation of to_address.
|
||||
|
||||
N: Eric Fiselier
|
||||
E: eric@efcs.ca
|
||||
D: LFTS support, patches and bug fixes.
|
||||
@ -97,7 +101,7 @@ E: nico.rieck@gmail.com
|
||||
D: Windows fixes
|
||||
|
||||
N: Jon Roelofs
|
||||
E: jonathan@codesourcery.com
|
||||
E: jroelofS@jroelofs.com
|
||||
D: Remote testing, Newlib port, baremetal/single-threaded support.
|
||||
|
||||
N: Jonathan Sauer
|
||||
|
239
LICENSE.TXT
239
LICENSE.TXT
@ -1,5 +1,240 @@
|
||||
==============================================================================
|
||||
libc++ License
|
||||
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
|
||||
==============================================================================
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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
|
||||
|
||||
http://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.
|
||||
|
||||
|
||||
---- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
|
||||
==============================================================================
|
||||
Software from third parties included in the LLVM Project:
|
||||
==============================================================================
|
||||
The LLVM Project contains third party software which is under different license
|
||||
terms. All such code will be identified clearly using at least one of two
|
||||
mechanisms:
|
||||
1) It will be in a separate directory tree with its own `LICENSE.txt` or
|
||||
`LICENSE` file at the top containing the specific license and restrictions
|
||||
which apply to that software, or
|
||||
2) It will contain specific license and restriction terms at the top of every
|
||||
file.
|
||||
|
||||
==============================================================================
|
||||
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
|
||||
==============================================================================
|
||||
|
||||
The libc++ library is dual licensed under both the University of Illinois
|
||||
@ -14,7 +249,7 @@ Full text of the relevant licenses is included below.
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2009-2017 by the contributors listed in CREDITS.TXT
|
||||
Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
@ -26,3 +26,4 @@ to libc++.
|
||||
1. Add a test under `test/libcxx` that the header defines `_LIBCPP_VERSION`.
|
||||
2. Update `test/libcxx/double_include.sh.cpp` to include the new header.
|
||||
3. Create a submodule in `include/module.modulemap` for the new header.
|
||||
4. Update the include/CMakeLists.txt file to include the new header.
|
||||
|
53
appveyor-reqs-install.cmd
Normal file
53
appveyor-reqs-install.cmd
Normal file
@ -0,0 +1,53 @@
|
||||
@echo on
|
||||
|
||||
if NOT EXIST C:\projects\deps (
|
||||
mkdir C:\projects\deps
|
||||
)
|
||||
cd C:\projects\deps
|
||||
|
||||
::###########################################################################
|
||||
:: Setup Compiler
|
||||
::###########################################################################
|
||||
if NOT EXIST llvm-installer.exe (
|
||||
appveyor DownloadFile https://prereleases.llvm.org/win-snapshots/LLVM-9.0.0-r357435-win32.exe -FileName llvm-installer.exe
|
||||
)
|
||||
if "%CLANG_VERSION%"=="ToT" (
|
||||
START /WAIT llvm-installer.exe /S /D=C:\"Program Files\LLVM"
|
||||
)
|
||||
if DEFINED CLANG_VERSION @set PATH="C:\Program Files\LLVM\bin";%PATH%
|
||||
if DEFINED CLANG_VERSION clang-cl -v
|
||||
|
||||
if DEFINED MINGW_PATH rename "C:\Program Files\Git\usr\bin\sh.exe" "sh-ignored.exe"
|
||||
if DEFINED MINGW_PATH @set "PATH=%PATH:C:\Program Files (x86)\Git\bin=%"
|
||||
if DEFINED MINGW_PATH @set "PATH=%PATH%;%MINGW_PATH%"
|
||||
if DEFINED MINGW_PATH g++ -v
|
||||
|
||||
::###########################################################################
|
||||
:: Install a recent CMake
|
||||
::###########################################################################
|
||||
if NOT EXIST cmake (
|
||||
appveyor DownloadFile https://cmake.org/files/v3.7/cmake-3.7.2-win64-x64.zip -FileName cmake.zip
|
||||
7z x cmake.zip -oC:\projects\deps > nul
|
||||
move C:\projects\deps\cmake-* C:\projects\deps\cmake
|
||||
rm cmake.zip
|
||||
)
|
||||
@set PATH=C:\projects\deps\cmake\bin;%PATH%
|
||||
cmake --version
|
||||
|
||||
::###########################################################################
|
||||
:: Install Ninja
|
||||
::###########################################################################
|
||||
if NOT EXIST ninja (
|
||||
appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
|
||||
7z x ninja.zip -oC:\projects\deps\ninja > nul
|
||||
rm ninja.zip
|
||||
)
|
||||
@set PATH=C:\projects\deps\ninja;%PATH%
|
||||
ninja --version
|
||||
|
||||
::###########################################################################
|
||||
:: Setup the cached copy of LLVM
|
||||
::###########################################################################
|
||||
git clone --depth=1 http://llvm.org/git/llvm.git
|
||||
|
||||
@echo off
|
71
appveyor.yml
Normal file
71
appveyor.yml
Normal file
@ -0,0 +1,71 @@
|
||||
version: '{build}'
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
build:
|
||||
verbosity: detailed
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_OPTIONS: -DCMAKE_C_COMPILER=clang-cl.exe -DCMAKE_CXX_COMPILER=clang-cl.exe
|
||||
CLANG_VERSION: ToT
|
||||
MSVC_SETUP_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat
|
||||
MSVC_SETUP_ARG: x86
|
||||
GENERATOR: Ninja
|
||||
MAKE_PROGRAM: ninja
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
# TODO: Maybe re-enable this configuration? Do we want to support MSVC 2015's runtime?
|
||||
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
# MINGW_PATH: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin
|
||||
# GENERATOR: MinGW Makefiles
|
||||
# MAKE_PROGRAM: mingw32-make
|
||||
# APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
|
||||
install:
|
||||
############################################################################
|
||||
# All external dependencies are installed in C:\projects\deps
|
||||
############################################################################
|
||||
- call "%APPVEYOR_BUILD_FOLDER%\\appveyor-reqs-install.cmd"
|
||||
|
||||
before_build:
|
||||
- if DEFINED MSVC_SETUP_PATH call "%MSVC_SETUP_PATH%" %MSVC_SETUP_ARG%
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
|
||||
build_script:
|
||||
- md C:\projects\build-libcxx
|
||||
- cd C:\projects\build-libcxx
|
||||
- echo %configuration%
|
||||
|
||||
#############################################################################
|
||||
# Configuration Step
|
||||
#############################################################################
|
||||
- cmake -G "%GENERATOR%" %CMAKE_OPTIONS%
|
||||
"-DCMAKE_BUILD_TYPE=%configuration%"
|
||||
"-DLLVM_PATH=C:\projects\deps\llvm" -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF
|
||||
-DLLVM_LIT_ARGS="-sv --show-xfail --show-unsupported"
|
||||
%APPVEYOR_BUILD_FOLDER%
|
||||
|
||||
#############################################################################
|
||||
# Build Step
|
||||
#############################################################################
|
||||
- "%MAKE_PROGRAM%"
|
||||
|
||||
test_script:
|
||||
- "%MAKE_PROGRAM% check-cxx"
|
||||
|
||||
on_failure:
|
||||
- appveyor PushArtifact CMakeFiles/CMakeOutput.log
|
||||
- appveyor PushArtifact CMakeFiles/CMakeError.log
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
name: logs
|
||||
|
||||
cache:
|
||||
- C:\projects\deps\ninja
|
||||
- C:\projects\deps\cmake
|
||||
- C:\projects\deps\llvm-installer.exe
|
@ -11,17 +11,21 @@ set(BENCHMARK_LIBCXX_COMPILE_FLAGS
|
||||
-isystem ${LIBCXX_SOURCE_DIR}/include
|
||||
-L${LIBCXX_LIBRARY_DIR}
|
||||
-Wl,-rpath,${LIBCXX_LIBRARY_DIR}
|
||||
${SANITIZER_FLAGS}
|
||||
)
|
||||
if (DEFINED LIBCXX_CXX_ABI_LIBRARY_PATH)
|
||||
list(APPEND BENCHMARK_LIBCXX_COMPILE_FLAGS
|
||||
-L${LIBCXX_CXX_ABI_LIBRARY_PATH}
|
||||
-Wl,-rpath,${LIBCXX_CXX_ABI_LIBRARY_PATH})
|
||||
endif()
|
||||
if (LIBCXX_NEEDS_SITE_CONFIG)
|
||||
list(APPEND BENCHMARK_LIBCXX_COMPILE_FLAGS -include "${LIBCXX_BINARY_DIR}/__config_site")
|
||||
endif()
|
||||
split_list(BENCHMARK_LIBCXX_COMPILE_FLAGS)
|
||||
|
||||
ExternalProject_Add(google-benchmark-libcxx
|
||||
EXCLUDE_FROM_ALL ON
|
||||
DEPENDS cxx
|
||||
DEPENDS cxx cxx-headers
|
||||
PREFIX benchmark-libcxx
|
||||
SOURCE_DIR ${LIBCXX_SOURCE_DIR}/utils/google-benchmark
|
||||
INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/benchmark-libcxx
|
||||
@ -59,15 +63,28 @@ if (LIBCXX_BENCHMARK_NATIVE_STDLIB)
|
||||
-DBENCHMARK_ENABLE_TESTING:BOOL=OFF)
|
||||
endif()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Benchmark tests configuration
|
||||
#==============================================================================
|
||||
add_custom_target(cxx-benchmarks)
|
||||
|
||||
set(BENCHMARK_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(BENCHMARK_LIBCXX_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/benchmark-libcxx)
|
||||
set(BENCHMARK_NATIVE_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/benchmark-native)
|
||||
|
||||
check_flag_supported("-std=c++17")
|
||||
mangle_name("LIBCXX_SUPPORTS_STD_EQ_c++17_FLAG" BENCHMARK_SUPPORTS_STD_CXX17_FLAG)
|
||||
if (${BENCHMARK_SUPPORTS_STD_CXX17_FLAG})
|
||||
set(BENCHMARK_DIALECT_FLAG "-std=c++17")
|
||||
else()
|
||||
# If the compiler doesn't support -std=c++17, attempt to fall back to -std=c++1z while still
|
||||
# requiring C++17 language features.
|
||||
set(BENCHMARK_DIALECT_FLAG "-std=c++1z")
|
||||
endif()
|
||||
|
||||
set(BENCHMARK_TEST_COMPILE_FLAGS
|
||||
-std=c++14 -O2
|
||||
${BENCHMARK_DIALECT_FLAG} -O2
|
||||
-fsized-deallocation
|
||||
-I${BENCHMARK_LIBCXX_INSTALL}/include
|
||||
-I${LIBCXX_SOURCE_DIR}/test/support
|
||||
)
|
||||
@ -75,11 +92,14 @@ set(BENCHMARK_TEST_LIBCXX_COMPILE_FLAGS
|
||||
-nostdinc++
|
||||
-isystem ${LIBCXX_SOURCE_DIR}/include
|
||||
${BENCHMARK_TEST_COMPILE_FLAGS}
|
||||
${SANITIZER_FLAGS}
|
||||
-Wno-user-defined-literals
|
||||
)
|
||||
|
||||
set(BENCHMARK_TEST_LIBCXX_LINK_FLAGS
|
||||
-nodefaultlibs
|
||||
-L${BENCHMARK_LIBCXX_INSTALL}/lib/
|
||||
${SANITIZER_FLAGS}
|
||||
)
|
||||
set(BENCHMARK_TEST_NATIVE_COMPILE_FLAGS
|
||||
${BENCHMARK_NATIVE_TARGET_FLAGS}
|
||||
@ -94,48 +114,73 @@ split_list(BENCHMARK_TEST_LIBCXX_COMPILE_FLAGS)
|
||||
split_list(BENCHMARK_TEST_LIBCXX_LINK_FLAGS)
|
||||
split_list(BENCHMARK_TEST_NATIVE_COMPILE_FLAGS)
|
||||
split_list(BENCHMARK_TEST_NATIVE_LINK_FLAGS)
|
||||
macro(add_benchmark_test name source_file)
|
||||
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libstdc++")
|
||||
find_library(LIBSTDCXX_FILESYSTEM_TEST stdc++fs
|
||||
PATHS ${LIBCXX_BENCHMARK_NATIVE_GCC_TOOLCHAIN}
|
||||
PATH_SUFFIXES lib lib64
|
||||
DOC "The libstdc++ filesystem library used by the benchmarks"
|
||||
)
|
||||
if (NOT "${LIBSTDCXX_FILESYSTEM_TEST}" STREQUAL "LIBSTDCXX_FILESYSTEM_TEST-NOTFOUND")
|
||||
set(LIBSTDCXX_FILESYSTEM_LIB "stdc++fs")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(libcxx_benchmark_targets)
|
||||
|
||||
function(add_benchmark_test name source_file)
|
||||
set(libcxx_target ${name}_libcxx)
|
||||
list(APPEND libcxx_benchmark_targets ${libcxx_target})
|
||||
add_executable(${libcxx_target} EXCLUDE_FROM_ALL ${source_file})
|
||||
add_dependencies(${libcxx_target} cxx google-benchmark-libcxx)
|
||||
add_dependencies(${libcxx_target} cxx cxx-headers google-benchmark-libcxx)
|
||||
add_dependencies(cxx-benchmarks ${libcxx_target})
|
||||
if (LIBCXX_ENABLE_SHARED)
|
||||
target_link_libraries(${libcxx_target} cxx_shared)
|
||||
target_link_libraries(${libcxx_target} PRIVATE cxx_shared)
|
||||
else()
|
||||
target_link_libraries(${libcxx_target} cxx_static)
|
||||
target_link_libraries(${libcxx_target} PRIVATE cxx_static)
|
||||
endif()
|
||||
if (TARGET cxx_experimental)
|
||||
target_link_libraries(${libcxx_target} cxx_experimental)
|
||||
target_link_libraries(${libcxx_target} PRIVATE cxx_experimental)
|
||||
endif()
|
||||
target_link_libraries(${libcxx_target} PRIVATE -lbenchmark)
|
||||
if (LLVM_USE_SANITIZER)
|
||||
target_link_libraries(${libcxx_target} PRIVATE -ldl)
|
||||
endif()
|
||||
target_link_libraries(${libcxx_target} -lbenchmark)
|
||||
set_target_properties(${libcxx_target}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "${name}.libcxx.out"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${BENCHMARK_OUTPUT_DIR}"
|
||||
COMPILE_FLAGS "${BENCHMARK_TEST_LIBCXX_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${BENCHMARK_TEST_LIBCXX_LINK_FLAGS}")
|
||||
cxx_link_system_libraries(${libcxx_target})
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB)
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libstdc++" AND NOT DEFINED LIBSTDCXX_FILESYSTEM_LIB
|
||||
AND "${name}" STREQUAL "filesystem")
|
||||
return()
|
||||
endif()
|
||||
set(native_target ${name}_native)
|
||||
add_executable(${native_target} EXCLUDE_FROM_ALL ${source_file})
|
||||
add_dependencies(${native_target} google-benchmark-native
|
||||
google-benchmark-libcxx)
|
||||
target_link_libraries(${native_target} -lbenchmark)
|
||||
target_link_libraries(${native_target} PRIVATE -lbenchmark)
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libstdc++")
|
||||
target_link_libraries(${native_target} -lstdc++fs)
|
||||
target_link_libraries(${native_target} PRIVATE ${LIBSTDCXX_FILESYSTEM_LIB})
|
||||
elseif (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libc++")
|
||||
target_link_libraries(${native_target} -lc++experimental)
|
||||
target_link_libraries(${native_target} PRIVATE -lc++fs -lc++experimental)
|
||||
endif()
|
||||
if (LIBCXX_HAS_PTHREAD_LIB)
|
||||
target_link_libraries(${native_target} -pthread)
|
||||
target_link_libraries(${native_target} PRIVATE -pthread)
|
||||
endif()
|
||||
add_dependencies(cxx-benchmarks ${native_target})
|
||||
set_target_properties(${native_target}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "${name}.native.out"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${BENCHMARK_OUTPUT_DIR}"
|
||||
INCLUDE_DIRECTORIES ""
|
||||
COMPILE_FLAGS "${BENCHMARK_TEST_NATIVE_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${BENCHMARK_TEST_NATIVE_LINK_FLAGS}")
|
||||
endif()
|
||||
endmacro()
|
||||
endfunction()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
@ -152,3 +197,24 @@ foreach(test_path ${BENCHMARK_TESTS})
|
||||
endif()
|
||||
add_benchmark_test(${test_name} ${test_file})
|
||||
endforeach()
|
||||
|
||||
if (LIBCXX_INCLUDE_TESTS)
|
||||
include(AddLLVM)
|
||||
|
||||
if (NOT DEFINED LIBCXX_TEST_DEPS)
|
||||
message(FATAL_ERROR "Expected LIBCXX_TEST_DEPS to be defined")
|
||||
endif()
|
||||
|
||||
configure_lit_site_cfg(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
|
||||
|
||||
set(BENCHMARK_LIT_ARGS "--show-all --show-xfail --show-unsupported ${LIT_ARGS_DEFAULT}")
|
||||
|
||||
add_lit_target(check-cxx-benchmarks
|
||||
"Running libcxx benchmarks tests"
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS cxx-benchmarks ${LIBCXX_TEST_DEPS}
|
||||
ARGS ${BENCHMARK_LIT_ARGS})
|
||||
endif()
|
||||
|
||||
|
134
benchmarks/CartesianBenchmarks.h
Normal file
134
benchmarks/CartesianBenchmarks.h
Normal file
@ -0,0 +1,134 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class D, class E, size_t I>
|
||||
struct EnumValue : std::integral_constant<E, static_cast<E>(I)> {
|
||||
static std::string name() { return std::string("_") + D::Names[I]; }
|
||||
};
|
||||
|
||||
template <class D, class E, size_t ...Idxs>
|
||||
constexpr auto makeEnumValueTuple(std::index_sequence<Idxs...>) {
|
||||
return std::make_tuple(EnumValue<D, E, Idxs>{}...);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
static auto skip(const B& Bench, int) -> decltype(Bench.skip()) {
|
||||
return Bench.skip();
|
||||
}
|
||||
template <class B>
|
||||
static auto skip(const B& Bench, char) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class B, class Args, size_t... Is>
|
||||
void makeBenchmarkFromValuesImpl(const Args& A, std::index_sequence<Is...>) {
|
||||
for (auto& V : A) {
|
||||
B Bench{std::get<Is>(V)...};
|
||||
if (!internal::skip(Bench, 0)) {
|
||||
benchmark::RegisterBenchmark(Bench.name().c_str(),
|
||||
[=](benchmark::State& S) { Bench.run(S); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class B, class... Args>
|
||||
void makeBenchmarkFromValues(const std::vector<std::tuple<Args...> >& A) {
|
||||
makeBenchmarkFromValuesImpl<B>(A, std::index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
template <template <class...> class B, class Args, class... U>
|
||||
void makeBenchmarkImpl(const Args& A, std::tuple<U...> t) {
|
||||
makeBenchmarkFromValues<B<U...> >(A);
|
||||
}
|
||||
|
||||
template <template <class...> class B, class Args, class... U,
|
||||
class... T, class... Tuples>
|
||||
void makeBenchmarkImpl(const Args& A, std::tuple<U...>, std::tuple<T...>,
|
||||
Tuples... rest) {
|
||||
(internal::makeBenchmarkImpl<B>(A, std::tuple<U..., T>(), rest...), ...);
|
||||
}
|
||||
|
||||
template <class R, class T>
|
||||
void allValueCombinations(R& Result, const T& Final) {
|
||||
return Result.push_back(Final);
|
||||
}
|
||||
|
||||
template <class R, class T, class V, class... Vs>
|
||||
void allValueCombinations(R& Result, const T& Prev, const V& Value,
|
||||
const Vs&... Values) {
|
||||
for (const auto& E : Value) {
|
||||
allValueCombinations(Result, std::tuple_cat(Prev, std::make_tuple(E)),
|
||||
Values...);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// CRTP class that enables using enum types as a dimension for
|
||||
// makeCartesianProductBenchmark below.
|
||||
// The type passed to `B` will be a std::integral_constant<E, e>, with the
|
||||
// additional static function `name()` that returns the stringified name of the
|
||||
// label.
|
||||
//
|
||||
// Eg:
|
||||
// enum class MyEnum { A, B };
|
||||
// struct AllMyEnum : EnumValuesAsTuple<AllMyEnum, MyEnum, 2> {
|
||||
// static constexpr absl::string_view Names[] = {"A", "B"};
|
||||
// };
|
||||
template <class Derived, class EnumType, size_t NumLabels>
|
||||
using EnumValuesAsTuple =
|
||||
decltype(internal::makeEnumValueTuple<Derived, EnumType>(
|
||||
std::make_index_sequence<NumLabels>{}));
|
||||
|
||||
// Instantiates B<T0, T1, ..., TN> where <Ti...> are the combinations in the
|
||||
// cartesian product of `Tuples...`, and pass (arg0, ..., argN) as constructor
|
||||
// arguments where `(argi...)` are the combination in the cartesian product of
|
||||
// the runtime values of `A...`.
|
||||
// B<T...> requires:
|
||||
// - std::string name(args...): The name of the benchmark.
|
||||
// - void run(benchmark::State&, args...): The body of the benchmark.
|
||||
// It can also optionally provide:
|
||||
// - bool skip(args...): When `true`, skips the combination. Default is false.
|
||||
//
|
||||
// Returns int to facilitate registration. The return value is unspecified.
|
||||
template <template <class...> class B, class... Tuples, class... Args>
|
||||
int makeCartesianProductBenchmark(const Args&... A) {
|
||||
std::vector<std::tuple<typename Args::value_type...> > V;
|
||||
internal::allValueCombinations(V, std::tuple<>(), A...);
|
||||
internal::makeBenchmarkImpl<B>(V, std::tuple<>(), Tuples()...);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class B, class... Args>
|
||||
int makeCartesianProductBenchmark(const Args&... A) {
|
||||
std::vector<std::tuple<typename Args::value_type...> > V;
|
||||
internal::allValueCombinations(V, std::tuple<>(), A...);
|
||||
internal::makeBenchmarkFromValues<B>(V);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// When `opaque` is true, this function hides the runtime state of `value` from
|
||||
// the optimizer.
|
||||
// It returns `value`.
|
||||
template <class T>
|
||||
TEST_ALWAYS_INLINE inline T maybeOpaque(T value, bool opaque) {
|
||||
if (opaque) benchmark::DoNotOptimize(value);
|
||||
return value;
|
||||
}
|
||||
|
@ -1,12 +1,39 @@
|
||||
#ifndef BENCHMARK_CONTAINER_BENCHMARKS_HPP
|
||||
#define BENCHMARK_CONTAINER_BENCHMARKS_HPP
|
||||
// -*- 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 BENCHMARK_CONTAINER_BENCHMARKS_H
|
||||
#define BENCHMARK_CONTAINER_BENCHMARKS_H
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "Utilities.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace ContainerBenchmarks {
|
||||
|
||||
template <class Container>
|
||||
void BM_ConstructSize(benchmark::State& st, Container) {
|
||||
auto size = st.range(0);
|
||||
for (auto _ : st) {
|
||||
Container c(size);
|
||||
DoNotOptimizeData(c);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
void BM_ConstructSizeValue(benchmark::State& st, Container, typename Container::value_type const& val) {
|
||||
const auto size = st.range(0);
|
||||
for (auto _ : st) {
|
||||
Container c(size, val);
|
||||
DoNotOptimizeData(c);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
void BM_ConstructIterIter(benchmark::State& st, Container, GenInputs gen) {
|
||||
@ -16,7 +43,7 @@ void BM_ConstructIterIter(benchmark::State& st, Container, GenInputs gen) {
|
||||
benchmark::DoNotOptimize(&in);
|
||||
while (st.KeepRunning()) {
|
||||
Container c(begin, end);
|
||||
benchmark::DoNotOptimize(c.data());
|
||||
DoNotOptimizeData(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,4 +137,4 @@ static void BM_FindRehash(benchmark::State& st, Container c, GenInputs gen) {
|
||||
|
||||
} // end namespace ContainerBenchmarks
|
||||
|
||||
#endif // BENCHMARK_CONTAINER_BENCHMARKS_HPP
|
||||
#endif // BENCHMARK_CONTAINER_BENCHMARKS_H
|
@ -1,5 +1,5 @@
|
||||
#ifndef BENCHMARK_GENERATE_INPUT_HPP
|
||||
#define BENCHMARK_GENERATE_INPUT_HPP
|
||||
#ifndef BENCHMARK_GENERATE_INPUT_H
|
||||
#define BENCHMARK_GENERATE_INPUT_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
@ -29,14 +29,16 @@ inline std::default_random_engine& getRandomEngine() {
|
||||
return RandEngine;
|
||||
}
|
||||
|
||||
|
||||
inline char getRandomChar() {
|
||||
std::uniform_int_distribution<> LettersDist(0, LettersSize-1);
|
||||
return Letters[LettersDist(getRandomEngine())];
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
inline IntT getRandomInteger() {
|
||||
std::uniform_int_distribution<IntT> dist;
|
||||
inline IntT getRandomInteger(IntT Min = 0,
|
||||
IntT Max = std::numeric_limits<IntT>::max()) {
|
||||
std::uniform_int_distribution<IntT> dist(Min, Max);
|
||||
return dist(getRandomEngine());
|
||||
}
|
||||
|
||||
@ -139,4 +141,4 @@ inline std::vector<const char*> getRandomCStringInputs(size_t N) {
|
||||
}
|
||||
|
||||
|
||||
#endif // BENCHMARK_GENERATE_INPUT_HPP
|
||||
#endif // BENCHMARK_GENERATE_INPUT_H
|
33
benchmarks/Utilities.h
Normal file
33
benchmarks/Utilities.h
Normal file
@ -0,0 +1,33 @@
|
||||
// -*- 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 BENCHMARK_UTILITIES_H
|
||||
#define BENCHMARK_UTILITIES_H
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace UtilitiesInternal {
|
||||
template <class Container>
|
||||
auto HaveDataImpl(int) -> decltype((std::declval<Container&>().data(), std::true_type{}));
|
||||
template <class Container>
|
||||
auto HaveDataImpl(long) -> std::false_type;
|
||||
template <class T>
|
||||
using HasData = decltype(HaveDataImpl<T>(0));
|
||||
} // namespace UtilitiesInternal
|
||||
|
||||
template <class Container, std::enable_if_t<UtilitiesInternal::HasData<Container>::value>* = nullptr>
|
||||
void DoNotOptimizeData(Container &c) { benchmark::DoNotOptimize(c.data()); }
|
||||
template <class Container, std::enable_if_t<!UtilitiesInternal::HasData<Container>::value>* = nullptr>
|
||||
void DoNotOptimizeData(Container &c) { benchmark::DoNotOptimize(&c); }
|
||||
|
||||
|
||||
#endif // BENCHMARK_UTILITIES_H
|
@ -1,62 +1,276 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "GenerateInput.hpp"
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
constexpr std::size_t TestNumInputs = 1024;
|
||||
namespace {
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_Sort(benchmark::State& st, GenInputs gen) {
|
||||
using ValueType = typename decltype(gen(0))::value_type;
|
||||
const auto in = gen(st.range(0));
|
||||
std::vector<ValueType> inputs[5];
|
||||
auto reset_inputs = [&]() {
|
||||
for (auto& C : inputs) {
|
||||
C = in;
|
||||
benchmark::DoNotOptimize(C.data());
|
||||
}
|
||||
};
|
||||
reset_inputs();
|
||||
while (st.KeepRunning()) {
|
||||
for (auto& I : inputs) {
|
||||
std::sort(I.data(), I.data() + I.size());
|
||||
benchmark::DoNotOptimize(I.data());
|
||||
}
|
||||
st.PauseTiming();
|
||||
reset_inputs();
|
||||
benchmark::ClobberMemory();
|
||||
st.ResumeTiming();
|
||||
}
|
||||
enum class ValueType { Uint32, String };
|
||||
struct AllValueTypes : EnumValuesAsTuple<AllValueTypes, ValueType, 2> {
|
||||
static constexpr const char* Names[] = {"uint32", "string"};
|
||||
};
|
||||
|
||||
template <class V>
|
||||
using Value =
|
||||
std::conditional_t<V() == ValueType::Uint32, uint32_t, std::string>;
|
||||
|
||||
enum class Order {
|
||||
Random,
|
||||
Ascending,
|
||||
Descending,
|
||||
SingleElement,
|
||||
PipeOrgan,
|
||||
Heap
|
||||
};
|
||||
struct AllOrders : EnumValuesAsTuple<AllOrders, Order, 6> {
|
||||
static constexpr const char* Names[] = {"Random", "Ascending",
|
||||
"Descending", "SingleElement",
|
||||
"PipeOrgan", "Heap"};
|
||||
};
|
||||
|
||||
void fillValues(std::vector<uint32_t>& V, size_t N, Order O) {
|
||||
if (O == Order::SingleElement) {
|
||||
V.resize(N, 0);
|
||||
} else {
|
||||
while (V.size() < N)
|
||||
V.push_back(V.size());
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, random_uint32,
|
||||
getRandomIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
void fillValues(std::vector<std::string>& V, size_t N, Order O) {
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, sorted_ascending_uint32,
|
||||
getSortedIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
if (O == Order::SingleElement) {
|
||||
V.resize(N, getRandomString(1024));
|
||||
} else {
|
||||
while (V.size() < N)
|
||||
V.push_back(getRandomString(1024));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, sorted_descending_uint32,
|
||||
getReverseSortedIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
template <class T>
|
||||
void sortValues(T& V, Order O) {
|
||||
assert(std::is_sorted(V.begin(), V.end()));
|
||||
switch (O) {
|
||||
case Order::Random: {
|
||||
std::random_device R;
|
||||
std::mt19937 M(R());
|
||||
std::shuffle(V.begin(), V.end(), M);
|
||||
break;
|
||||
}
|
||||
case Order::Ascending:
|
||||
std::sort(V.begin(), V.end());
|
||||
break;
|
||||
case Order::Descending:
|
||||
std::sort(V.begin(), V.end(), std::greater<>());
|
||||
break;
|
||||
case Order::SingleElement:
|
||||
// Nothing to do
|
||||
break;
|
||||
case Order::PipeOrgan:
|
||||
std::sort(V.begin(), V.end());
|
||||
std::reverse(V.begin() + V.size() / 2, V.end());
|
||||
break;
|
||||
case Order::Heap:
|
||||
std::make_heap(V.begin(), V.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, single_element_uint32,
|
||||
getDuplicateIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
template <class ValueType>
|
||||
std::vector<std::vector<Value<ValueType> > > makeOrderedValues(size_t N,
|
||||
Order O) {
|
||||
// Let's make sure that all random sequences of the same size are the same.
|
||||
// That way we can compare the different algorithms with the same input.
|
||||
static std::map<std::pair<size_t, Order>, std::vector<Value<ValueType> > >
|
||||
Cached;
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, pipe_organ_uint32,
|
||||
getPipeOrganIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
auto& Values = Cached[{N, O}];
|
||||
if (Values.empty()) {
|
||||
fillValues(Values, N, O);
|
||||
sortValues(Values, O);
|
||||
};
|
||||
const size_t NumCopies = std::max(size_t{1}, 1000 / N);
|
||||
return { NumCopies, Values };
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, random_strings,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
template <class T, class U>
|
||||
TEST_ALWAYS_INLINE void resetCopies(benchmark::State& state, T& Copies,
|
||||
U& Orig) {
|
||||
state.PauseTiming();
|
||||
for (auto& Copy : Copies)
|
||||
Copy = Orig;
|
||||
state.ResumeTiming();
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, sorted_ascending_strings,
|
||||
getSortedStringInputs)->Arg(TestNumInputs);
|
||||
template <class ValueType, class F>
|
||||
void runOpOnCopies(benchmark::State& state, size_t Quantity, Order O,
|
||||
bool CountElements, F f) {
|
||||
auto Copies = makeOrderedValues<ValueType>(Quantity, O);
|
||||
const auto Orig = Copies[0];
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, sorted_descending_strings,
|
||||
getReverseSortedStringInputs)->Arg(TestNumInputs);
|
||||
const size_t Batch = CountElements ? Copies.size() * Quantity : Copies.size();
|
||||
while (state.KeepRunningBatch(Batch)) {
|
||||
for (auto& Copy : Copies) {
|
||||
f(Copy);
|
||||
benchmark::DoNotOptimize(Copy);
|
||||
}
|
||||
resetCopies(state, Copies, Orig);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Sort, single_element_strings,
|
||||
getDuplicateStringInputs)->Arg(TestNumInputs);
|
||||
template <class ValueType, class Order>
|
||||
struct Sort {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), false, [](auto& Copy) {
|
||||
std::sort(Copy.begin(), Copy.end());
|
||||
});
|
||||
}
|
||||
|
||||
BENCHMARK_MAIN()
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Sort" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
|
||||
template <class ValueType, class Order>
|
||||
struct StableSort {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), false, [](auto& Copy) {
|
||||
std::stable_sort(Copy.begin(), Copy.end());
|
||||
});
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_StableSort" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
|
||||
template <class ValueType, class Order>
|
||||
struct MakeHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), false, [](auto& Copy) {
|
||||
std::make_heap(Copy.begin(), Copy.end());
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_MakeHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct SortHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order::Heap, false,
|
||||
[](auto& Copy) { std::sort_heap(Copy.begin(), Copy.end()); });
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_SortHeap" + ValueType::name() + "_" + std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
|
||||
template <class ValueType, class Order>
|
||||
struct MakeThenSortHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), false, [](auto& Copy) {
|
||||
std::make_heap(Copy.begin(), Copy.end());
|
||||
std::sort_heap(Copy.begin(), Copy.end());
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_MakeThenSortHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
|
||||
template <class ValueType, class Order>
|
||||
struct PushHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), true, [](auto& Copy) {
|
||||
for (auto I = Copy.begin(), E = Copy.end(); I != E; ++I) {
|
||||
std::push_heap(Copy.begin(), I + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_PushHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct PopHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), true, [](auto& Copy) {
|
||||
for (auto B = Copy.begin(), I = Copy.end(); I != B; --I) {
|
||||
std::pop_heap(B, I);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_PopHeap" + ValueType::name() + "_" + std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
const std::vector<size_t> Quantities = {1 << 0, 1 << 2, 1 << 4, 1 << 6,
|
||||
1 << 8, 1 << 10, 1 << 14,
|
||||
// Running each benchmark in parallel consumes too much memory with MSAN
|
||||
// and can lead to the test process being killed.
|
||||
#if !TEST_HAS_FEATURE(memory_sanitizer)
|
||||
1 << 18
|
||||
#endif
|
||||
};
|
||||
makeCartesianProductBenchmark<Sort, AllValueTypes, AllOrders>(Quantities);
|
||||
makeCartesianProductBenchmark<StableSort, AllValueTypes, AllOrders>(
|
||||
Quantities);
|
||||
makeCartesianProductBenchmark<MakeHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
makeCartesianProductBenchmark<SortHeap, AllValueTypes>(Quantities);
|
||||
makeCartesianProductBenchmark<MakeThenSortHeap, AllValueTypes, AllOrders>(
|
||||
Quantities);
|
||||
makeCartesianProductBenchmark<PushHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
makeCartesianProductBenchmark<PopHeap, AllValueTypes>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
||||
|
124
benchmarks/algorithms.partition_point.bench.cpp
Normal file
124
benchmarks/algorithms.partition_point.bench.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename I, typename N>
|
||||
std::array<I, 10> every_10th_percentile_N(I first, N n) {
|
||||
N step = n / 10;
|
||||
std::array<I, 10> res;
|
||||
|
||||
for (size_t i = 0; i < 10; ++i) {
|
||||
res[i] = first;
|
||||
std::advance(first, step);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
struct TestIntBase {
|
||||
static std::vector<IntT> generateInput(size_t size) {
|
||||
std::vector<IntT> Res(size);
|
||||
std::generate(Res.begin(), Res.end(),
|
||||
[] { return getRandomInteger<IntT>(); });
|
||||
return Res;
|
||||
}
|
||||
};
|
||||
|
||||
struct TestInt32 : TestIntBase<std::int32_t> {
|
||||
static constexpr const char* Name = "TestInt32";
|
||||
};
|
||||
|
||||
struct TestInt64 : TestIntBase<std::int64_t> {
|
||||
static constexpr const char* Name = "TestInt64";
|
||||
};
|
||||
|
||||
struct TestUint32 : TestIntBase<std::uint32_t> {
|
||||
static constexpr const char* Name = "TestUint32";
|
||||
};
|
||||
|
||||
struct TestMediumString {
|
||||
static constexpr const char* Name = "TestMediumString";
|
||||
static constexpr size_t StringSize = 32;
|
||||
|
||||
static std::vector<std::string> generateInput(size_t size) {
|
||||
std::vector<std::string> Res(size);
|
||||
std::generate(Res.begin(), Res.end(), [] { return getRandomString(StringSize); });
|
||||
return Res;
|
||||
}
|
||||
};
|
||||
|
||||
using AllTestTypes = std::tuple<TestInt32, TestInt64, TestUint32, TestMediumString>;
|
||||
|
||||
struct LowerBoundAlg {
|
||||
template <class I, class V>
|
||||
I operator()(I first, I last, const V& value) const {
|
||||
return std::lower_bound(first, last, value);
|
||||
}
|
||||
|
||||
static constexpr const char* Name = "LowerBoundAlg";
|
||||
};
|
||||
|
||||
struct UpperBoundAlg {
|
||||
template <class I, class V>
|
||||
I operator()(I first, I last, const V& value) const {
|
||||
return std::upper_bound(first, last, value);
|
||||
}
|
||||
|
||||
static constexpr const char* Name = "UpperBoundAlg";
|
||||
};
|
||||
|
||||
struct EqualRangeAlg {
|
||||
template <class I, class V>
|
||||
std::pair<I, I> operator()(I first, I last, const V& value) const {
|
||||
return std::equal_range(first, last, value);
|
||||
}
|
||||
|
||||
static constexpr const char* Name = "EqualRangeAlg";
|
||||
};
|
||||
|
||||
using AllAlgs = std::tuple<LowerBoundAlg, UpperBoundAlg, EqualRangeAlg>;
|
||||
|
||||
template <class Alg, class TestType>
|
||||
struct PartitionPointBench {
|
||||
size_t Quantity;
|
||||
|
||||
std::string name() const {
|
||||
return std::string("PartitionPointBench_") + Alg::Name + "_" +
|
||||
TestType::Name + '/' + std::to_string(Quantity);
|
||||
}
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
auto Data = TestType::generateInput(Quantity);
|
||||
std::sort(Data.begin(), Data.end());
|
||||
auto Every10Percentile = every_10th_percentile_N(Data.begin(), Data.size());
|
||||
|
||||
for (auto _ : state) {
|
||||
for (auto Test : Every10Percentile)
|
||||
benchmark::DoNotOptimize(Alg{}(Data.begin(), Data.end(), *Test));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
const std::vector<size_t> Quantities = {1 << 8, 1 << 10, 1 << 20};
|
||||
makeCartesianProductBenchmark<PartitionPointBench, AllAlgs, AllTestTypes>(
|
||||
Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
136
benchmarks/allocation.bench.cpp
Normal file
136
benchmarks/allocation.bench.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include <new>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
struct PointerList {
|
||||
PointerList* Next = nullptr;
|
||||
};
|
||||
|
||||
struct MallocWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return std::malloc(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t) {
|
||||
std::free(P);
|
||||
}
|
||||
};
|
||||
|
||||
struct NewWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return ::operator new(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t) {
|
||||
::operator delete(P);
|
||||
}
|
||||
};
|
||||
|
||||
struct BuiltinNewWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return __builtin_operator_new(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t) {
|
||||
__builtin_operator_delete(P);
|
||||
}
|
||||
};
|
||||
|
||||
struct BuiltinSizedNewWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return __builtin_operator_new(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t N) {
|
||||
__builtin_operator_delete(P, N);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class AllocWrapper>
|
||||
static void BM_AllocateAndDeallocate(benchmark::State& st) {
|
||||
const size_t alloc_size = st.range(0);
|
||||
while (st.KeepRunning()) {
|
||||
void* p = AllocWrapper::Allocate(alloc_size);
|
||||
benchmark::DoNotOptimize(p);
|
||||
AllocWrapper::Deallocate(p, alloc_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class AllocWrapper>
|
||||
static void BM_AllocateOnly(benchmark::State& st) {
|
||||
const size_t alloc_size = st.range(0);
|
||||
PointerList *Start = nullptr;
|
||||
|
||||
while (st.KeepRunning()) {
|
||||
PointerList* p = (PointerList*)AllocWrapper::Allocate(alloc_size);
|
||||
benchmark::DoNotOptimize(p);
|
||||
p->Next = Start;
|
||||
Start = p;
|
||||
}
|
||||
|
||||
PointerList *Next = Start;
|
||||
while (Next) {
|
||||
PointerList *Tmp = Next;
|
||||
Next = Tmp->Next;
|
||||
AllocWrapper::Deallocate(Tmp, alloc_size);
|
||||
}
|
||||
}
|
||||
|
||||
template <class AllocWrapper>
|
||||
static void BM_DeallocateOnly(benchmark::State& st) {
|
||||
const size_t alloc_size = st.range(0);
|
||||
const auto NumAllocs = st.max_iterations;
|
||||
|
||||
using PtrT = void*;
|
||||
std::vector<void*> Pointers(NumAllocs);
|
||||
for (auto& p : Pointers) {
|
||||
p = AllocWrapper::Allocate(alloc_size);
|
||||
}
|
||||
|
||||
void** Data = Pointers.data();
|
||||
void** const End = Pointers.data() + Pointers.size();
|
||||
while (st.KeepRunning()) {
|
||||
AllocWrapper::Deallocate(*Data, alloc_size);
|
||||
Data += 1;
|
||||
}
|
||||
assert(Data == End);
|
||||
}
|
||||
|
||||
static int RegisterAllocBenchmarks() {
|
||||
using FnType = void(*)(benchmark::State&);
|
||||
struct {
|
||||
const char* name;
|
||||
FnType func;
|
||||
} TestCases[] = {
|
||||
{"BM_Malloc", &BM_AllocateAndDeallocate<MallocWrapper>},
|
||||
{"BM_New", &BM_AllocateAndDeallocate<NewWrapper>},
|
||||
{"BM_BuiltinNewDelete", BM_AllocateAndDeallocate<BuiltinNewWrapper>},
|
||||
{"BM_BuiltinSizedNewDelete", BM_AllocateAndDeallocate<BuiltinSizedNewWrapper>},
|
||||
{"BM_BuiltinNewAllocateOnly", BM_AllocateOnly<BuiltinSizedNewWrapper>},
|
||||
{"BM_BuiltinNewSizedDeallocateOnly", BM_DeallocateOnly<BuiltinSizedNewWrapper>},
|
||||
|
||||
};
|
||||
for (auto TC : TestCases) {
|
||||
benchmark::RegisterBenchmark(TC.name, TC.func)->Range(16, 4096 * 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int Sink = RegisterAllocBenchmarks();
|
||||
|
||||
BENCHMARK_MAIN();
|
47
benchmarks/deque.bench.cpp
Normal file
47
benchmarks/deque.bench.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
// -*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "ContainerBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
|
||||
using namespace ContainerBenchmarks;
|
||||
|
||||
constexpr std::size_t TestNumInputs = 1024;
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSize,
|
||||
deque_byte,
|
||||
std::deque<unsigned char>{})->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSizeValue,
|
||||
deque_byte,
|
||||
std::deque<unsigned char>{}, 0)->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
deque_char,
|
||||
std::deque<char>{},
|
||||
getRandomIntegerInputs<char>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
deque_size_t,
|
||||
std::deque<size_t>{},
|
||||
getRandomIntegerInputs<size_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
deque_string,
|
||||
std::deque<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,17 +1,14 @@
|
||||
#include <experimental/filesystem>
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "GenerateInput.hpp"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "GenerateInput.h"
|
||||
#include "test_iterators.h"
|
||||
|
||||
namespace fs = std::experimental::filesystem;
|
||||
#include "filesystem_include.h"
|
||||
|
||||
static const size_t TestNumInputs = 1024;
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructString(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
@ -21,14 +18,15 @@ void BM_PathConstructString(benchmark::State &st, GenInputs gen) {
|
||||
const path P(PP.native());
|
||||
benchmark::DoNotOptimize(P.native().data());
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathConstructString, large_string,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructCStr(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
@ -45,7 +43,7 @@ BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string,
|
||||
|
||||
template <template <class...> class ItType, class GenInputs>
|
||||
void BM_PathConstructIter(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
using fs::path;
|
||||
using Iter = ItType<std::string::const_iterator>;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
@ -60,6 +58,7 @@ void BM_PathConstructIter(benchmark::State &st, GenInputs gen) {
|
||||
const path P(Start, End);
|
||||
benchmark::DoNotOptimize(P.native().data());
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructInputIter(benchmark::State &st, GenInputs gen) {
|
||||
@ -70,14 +69,14 @@ void BM_PathConstructForwardIter(benchmark::State &st, GenInputs gen) {
|
||||
BM_PathConstructIter<forward_iterator>(st, gen);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathIterateMultipleTimes(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
@ -89,14 +88,15 @@ void BM_PathIterateMultipleTimes(benchmark::State &st, GenInputs gen) {
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathIterateOnce(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
@ -109,13 +109,14 @@ void BM_PathIterateOnce(benchmark::State &st, GenInputs gen) {
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathIterateOnceBackwards(benchmark::State &st, GenInputs gen) {
|
||||
using namespace fs;
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
@ -135,4 +136,28 @@ void BM_PathIterateOnceBackwards(benchmark::State &st, GenInputs gen) {
|
||||
BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_MAIN()
|
||||
static fs::path getRandomPaths(int NumParts, int PathLen) {
|
||||
fs::path Result;
|
||||
while (NumParts--) {
|
||||
std::string Part = getRandomString(PathLen);
|
||||
Result /= Part;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
template <class GenInput>
|
||||
void BM_LexicallyNormal(benchmark::State &st, GenInput gen, size_t PathLen) {
|
||||
using fs::path;
|
||||
auto In = gen(st.range(0), PathLen);
|
||||
benchmark::DoNotOptimize(&In);
|
||||
while (st.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(In.lexically_normal());
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path,
|
||||
getRandomPaths, /*PathLen*/5)->RangeMultiplier(2)->Range(2, 256)->Complexity();
|
||||
BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path,
|
||||
getRandomPaths, /*PathLen*/32)->RangeMultiplier(2)->Range(2, 256)->Complexity();
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
231
benchmarks/function.bench.cpp
Normal file
231
benchmarks/function.bench.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class FunctionType {
|
||||
Null,
|
||||
FunctionPointer,
|
||||
MemberFunctionPointer,
|
||||
MemberPointer,
|
||||
SmallTrivialFunctor,
|
||||
SmallNonTrivialFunctor,
|
||||
LargeTrivialFunctor,
|
||||
LargeNonTrivialFunctor
|
||||
};
|
||||
|
||||
struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {
|
||||
static constexpr const char* Names[] = {"Null",
|
||||
"FuncPtr",
|
||||
"MemFuncPtr",
|
||||
"MemPtr",
|
||||
"SmallTrivialFunctor",
|
||||
"SmallNonTrivialFunctor",
|
||||
"LargeTrivialFunctor",
|
||||
"LargeNonTrivialFunctor"};
|
||||
};
|
||||
|
||||
enum class Opacity { kOpaque, kTransparent };
|
||||
|
||||
struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
|
||||
static constexpr const char* Names[] = {"Opaque", "Transparent"};
|
||||
};
|
||||
|
||||
struct S {
|
||||
int function() const { return 0; }
|
||||
int field = 0;
|
||||
};
|
||||
|
||||
int FunctionWithS(const S*) { return 0; }
|
||||
|
||||
struct SmallTrivialFunctor {
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct SmallNonTrivialFunctor {
|
||||
SmallNonTrivialFunctor() {}
|
||||
SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {}
|
||||
~SmallNonTrivialFunctor() {}
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct LargeTrivialFunctor {
|
||||
LargeTrivialFunctor() {
|
||||
// Do not spend time initializing the padding.
|
||||
}
|
||||
int padding[16];
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct LargeNonTrivialFunctor {
|
||||
int padding[16];
|
||||
LargeNonTrivialFunctor() {
|
||||
// Do not spend time initializing the padding.
|
||||
}
|
||||
LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {}
|
||||
~LargeNonTrivialFunctor() {}
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
|
||||
using Function = std::function<int(const S*)>;
|
||||
|
||||
TEST_ALWAYS_INLINE
|
||||
inline Function MakeFunction(FunctionType type, bool opaque = false) {
|
||||
switch (type) {
|
||||
case FunctionType::Null:
|
||||
return nullptr;
|
||||
case FunctionType::FunctionPointer:
|
||||
return maybeOpaque(FunctionWithS, opaque);
|
||||
case FunctionType::MemberFunctionPointer:
|
||||
return maybeOpaque(&S::function, opaque);
|
||||
case FunctionType::MemberPointer:
|
||||
return maybeOpaque(&S::field, opaque);
|
||||
case FunctionType::SmallTrivialFunctor:
|
||||
return maybeOpaque(SmallTrivialFunctor{}, opaque);
|
||||
case FunctionType::SmallNonTrivialFunctor:
|
||||
return maybeOpaque(SmallNonTrivialFunctor{}, opaque);
|
||||
case FunctionType::LargeTrivialFunctor:
|
||||
return maybeOpaque(LargeTrivialFunctor{}, opaque);
|
||||
case FunctionType::LargeNonTrivialFunctor:
|
||||
return maybeOpaque(LargeNonTrivialFunctor{}, opaque);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Opacity, class FunctionType>
|
||||
struct ConstructAndDestroy {
|
||||
static void run(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
if (Opacity() == ::Opacity::kOpaque) {
|
||||
benchmark::DoNotOptimize(MakeFunction(FunctionType(), true));
|
||||
} else {
|
||||
MakeFunction(FunctionType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Copy {
|
||||
static void run(benchmark::State& state) {
|
||||
auto value = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(value);
|
||||
auto copy = value; // NOLINT
|
||||
benchmark::DoNotOptimize(copy);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_Copy" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Move {
|
||||
static void run(benchmark::State& state) {
|
||||
Function values[2] = {MakeFunction(FunctionType())};
|
||||
int i = 0;
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(values);
|
||||
benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));
|
||||
i ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_Move" + FunctionType::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Function1, class Function2>
|
||||
struct Swap {
|
||||
static void run(benchmark::State& state) {
|
||||
Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())};
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(values);
|
||||
values[0].swap(values[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return Function1() > Function2(); }
|
||||
|
||||
static std::string name() {
|
||||
return "BM_Swap" + Function1::name() + Function2::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct OperatorBool {
|
||||
static void run(benchmark::State& state) {
|
||||
auto f = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(f);
|
||||
benchmark::DoNotOptimize(static_cast<bool>(f));
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Invoke {
|
||||
static void run(benchmark::State& state) {
|
||||
S s;
|
||||
const auto value = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(value);
|
||||
benchmark::DoNotOptimize(value(&s));
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return FunctionType() == ::FunctionType::Null; }
|
||||
|
||||
static std::string name() { return "BM_Invoke" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct InvokeInlined {
|
||||
static void run(benchmark::State& state) {
|
||||
S s;
|
||||
for (auto _ : state) {
|
||||
MakeFunction(FunctionType())(&s);
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return FunctionType() == ::FunctionType::Null; }
|
||||
|
||||
static std::string name() {
|
||||
return "BM_InvokeInlined" + FunctionType::name();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity,
|
||||
AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Copy, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Move, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
23
benchmarks/lit.cfg.py
Normal file
23
benchmarks/lit.cfg.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
|
||||
# Configuration file for the 'lit' test runner.
|
||||
import os
|
||||
import site
|
||||
|
||||
site.addsitedir(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'utils'))
|
||||
from libcxx.test.googlebenchmark import GoogleBenchmark
|
||||
|
||||
# Tell pylint that we know config and lit_config exist somewhere.
|
||||
if 'PYLINT_IMPORT' in os.environ:
|
||||
config = object()
|
||||
lit_config = object()
|
||||
|
||||
# name: The name of this test suite.
|
||||
config.name = 'libc++ benchmarks'
|
||||
config.suffixes = []
|
||||
|
||||
config.test_exec_root = os.path.join(config.libcxx_obj_root, 'benchmarks')
|
||||
config.test_source_root = config.test_exec_root
|
||||
|
||||
config.test_format = GoogleBenchmark(test_sub_dirs='.',
|
||||
test_suffix='.libcxx.out',
|
||||
benchmark_args=config.benchmark_args)
|
10
benchmarks/lit.site.cfg.py.in
Normal file
10
benchmarks/lit.site.cfg.py.in
Normal file
@ -0,0 +1,10 @@
|
||||
@LIT_SITE_CFG_IN_HEADER@
|
||||
|
||||
import sys
|
||||
|
||||
config.libcxx_src_root = "@LIBCXX_SOURCE_DIR@"
|
||||
config.libcxx_obj_root = "@LIBCXX_BINARY_DIR@"
|
||||
config.benchmark_args = "@LIBCXX_BENCHMARK_TEST_ARGS@".split(';')
|
||||
|
||||
# Let the main config do the real work.
|
||||
lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/benchmarks/lit.cfg.py")
|
248
benchmarks/ordered_set.bench.cpp
Normal file
248
benchmarks/ordered_set.bench.cpp
Normal file
@ -0,0 +1,248 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class HitType { Hit, Miss };
|
||||
|
||||
struct AllHitTypes : EnumValuesAsTuple<AllHitTypes, HitType, 2> {
|
||||
static constexpr const char* Names[] = {"Hit", "Miss"};
|
||||
};
|
||||
|
||||
enum class AccessPattern { Ordered, Random };
|
||||
|
||||
struct AllAccessPattern
|
||||
: EnumValuesAsTuple<AllAccessPattern, AccessPattern, 2> {
|
||||
static constexpr const char* Names[] = {"Ordered", "Random"};
|
||||
};
|
||||
|
||||
void sortKeysBy(std::vector<uint64_t>& Keys, AccessPattern AP) {
|
||||
if (AP == AccessPattern::Random) {
|
||||
std::random_device R;
|
||||
std::mt19937 M(R());
|
||||
std::shuffle(std::begin(Keys), std::end(Keys), M);
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSets {
|
||||
std::vector<std::set<uint64_t> > Sets;
|
||||
std::vector<uint64_t> Keys;
|
||||
};
|
||||
|
||||
TestSets makeTestingSets(size_t TableSize, size_t NumTables, HitType Hit,
|
||||
AccessPattern Access) {
|
||||
TestSets R;
|
||||
R.Sets.resize(1);
|
||||
|
||||
for (uint64_t I = 0; I < TableSize; ++I) {
|
||||
R.Sets[0].insert(2 * I);
|
||||
R.Keys.push_back(Hit == HitType::Hit ? 2 * I : 2 * I + 1);
|
||||
}
|
||||
R.Sets.resize(NumTables, R.Sets[0]);
|
||||
sortKeysBy(R.Keys, Access);
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
struct Base {
|
||||
size_t TableSize;
|
||||
size_t NumTables;
|
||||
Base(size_t T, size_t N) : TableSize(T), NumTables(N) {}
|
||||
|
||||
bool skip() const {
|
||||
size_t Total = TableSize * NumTables;
|
||||
return Total < 100 || Total > 1000000;
|
||||
}
|
||||
|
||||
std::string baseName() const {
|
||||
return "_TableSize" + std::to_string(TableSize) + "_NumTables" +
|
||||
std::to_string(NumTables);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct Create : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
std::vector<uint64_t> Keys(TableSize);
|
||||
std::iota(Keys.begin(), Keys.end(), uint64_t{0});
|
||||
sortKeysBy(Keys, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
std::vector<std::set<uint64_t>> Sets(NumTables);
|
||||
for (auto K : Keys) {
|
||||
for (auto& Set : Sets) {
|
||||
benchmark::DoNotOptimize(Set.insert(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Create" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Hit, class Access>
|
||||
struct Find : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.find(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Find" + Hit::name() + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Hit, class Access>
|
||||
struct FindNeEnd : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.find(K) != Set.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_FindNeEnd" + Hit::name() + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct InsertHit : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Hit, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.insert(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_InsertHit" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct InsertMissAndErase : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.erase(Set.insert(K).first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_InsertMissAndErase" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
struct IterateRangeFor : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
|
||||
AccessPattern::Ordered);
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
for (auto& V : Set) {
|
||||
benchmark::DoNotOptimize(V);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const { return "BM_IterateRangeFor" + baseName(); }
|
||||
};
|
||||
|
||||
struct IterateBeginEnd : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
|
||||
AccessPattern::Ordered);
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
for (auto it = Set.begin(); it != Set.end(); ++it) {
|
||||
benchmark::DoNotOptimize(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const { return "BM_IterateBeginEnd" + baseName(); }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
const std::vector<size_t> TableSize{1, 10, 100, 1000, 10000, 100000, 1000000};
|
||||
const std::vector<size_t> NumTables{1, 10, 100, 1000, 10000, 100000, 1000000};
|
||||
|
||||
makeCartesianProductBenchmark<Create, AllAccessPattern>(TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<Find, AllHitTypes, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<FindNeEnd, AllHitTypes, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<InsertHit, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<InsertMissAndErase, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<IterateRangeFor>(TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<IterateBeginEnd>(TableSize, NumTables);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "GenerateInput.hpp"
|
||||
#include <cstdint>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
constexpr std::size_t MAX_STRING_LEN = 8 << 14;
|
||||
|
||||
@ -11,7 +14,7 @@ constexpr std::size_t MAX_STRING_LEN = 8 << 14;
|
||||
static void BM_StringFindNoMatch(benchmark::State &state) {
|
||||
std::string s1(state.range(0), '-');
|
||||
std::string s2(8, '*');
|
||||
while (state.KeepRunning())
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindNoMatch)->Range(10, MAX_STRING_LEN);
|
||||
@ -20,7 +23,7 @@ BENCHMARK(BM_StringFindNoMatch)->Range(10, MAX_STRING_LEN);
|
||||
static void BM_StringFindAllMatch(benchmark::State &state) {
|
||||
std::string s1(MAX_STRING_LEN, '-');
|
||||
std::string s2(state.range(0), '-');
|
||||
while (state.KeepRunning())
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindAllMatch)->Range(1, MAX_STRING_LEN);
|
||||
@ -30,7 +33,7 @@ static void BM_StringFindMatch1(benchmark::State &state) {
|
||||
std::string s1(MAX_STRING_LEN / 2, '*');
|
||||
s1 += std::string(state.range(0), '-');
|
||||
std::string s2(state.range(0), '-');
|
||||
while (state.KeepRunning())
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindMatch1)->Range(1, MAX_STRING_LEN / 4);
|
||||
@ -41,9 +44,404 @@ static void BM_StringFindMatch2(benchmark::State &state) {
|
||||
s1 += std::string(state.range(0), '-');
|
||||
s1 += std::string(state.range(0), '*');
|
||||
std::string s2(state.range(0), '-');
|
||||
while (state.KeepRunning())
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);
|
||||
|
||||
BENCHMARK_MAIN()
|
||||
static void BM_StringCtorDefault(benchmark::State &state) {
|
||||
for (auto _ : state) {
|
||||
std::string Default;
|
||||
benchmark::DoNotOptimize(Default);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_StringCtorDefault);
|
||||
|
||||
enum class Length { Empty, Small, Large, Huge };
|
||||
struct AllLengths : EnumValuesAsTuple<AllLengths, Length, 4> {
|
||||
static constexpr const char* Names[] = {"Empty", "Small", "Large", "Huge"};
|
||||
};
|
||||
|
||||
enum class Opacity { Opaque, Transparent };
|
||||
struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
|
||||
static constexpr const char* Names[] = {"Opaque", "Transparent"};
|
||||
};
|
||||
|
||||
enum class DiffType { Control, ChangeFirst, ChangeMiddle, ChangeLast };
|
||||
struct AllDiffTypes : EnumValuesAsTuple<AllDiffTypes, DiffType, 4> {
|
||||
static constexpr const char* Names[] = {"Control", "ChangeFirst",
|
||||
"ChangeMiddle", "ChangeLast"};
|
||||
};
|
||||
|
||||
static constexpr char SmallStringLiteral[] = "012345678";
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getSmallString(DiffType D) {
|
||||
switch (D) {
|
||||
case DiffType::Control:
|
||||
return SmallStringLiteral;
|
||||
case DiffType::ChangeFirst:
|
||||
return "-12345678";
|
||||
case DiffType::ChangeMiddle:
|
||||
return "0123-5678";
|
||||
case DiffType::ChangeLast:
|
||||
return "01234567-";
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr char LargeStringLiteral[] =
|
||||
"012345678901234567890123456789012345678901234567890123456789012";
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getLargeString(DiffType D) {
|
||||
#define LARGE_STRING_FIRST "123456789012345678901234567890"
|
||||
#define LARGE_STRING_SECOND "234567890123456789012345678901"
|
||||
switch (D) {
|
||||
case DiffType::Control:
|
||||
return "0" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "2";
|
||||
case DiffType::ChangeFirst:
|
||||
return "-" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "2";
|
||||
case DiffType::ChangeMiddle:
|
||||
return "0" LARGE_STRING_FIRST "-" LARGE_STRING_SECOND "2";
|
||||
case DiffType::ChangeLast:
|
||||
return "0" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "-";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getHugeString(DiffType D) {
|
||||
#define HUGE_STRING0 "0123456789"
|
||||
#define HUGE_STRING1 HUGE_STRING0 HUGE_STRING0 HUGE_STRING0 HUGE_STRING0
|
||||
#define HUGE_STRING2 HUGE_STRING1 HUGE_STRING1 HUGE_STRING1 HUGE_STRING1
|
||||
#define HUGE_STRING3 HUGE_STRING2 HUGE_STRING2 HUGE_STRING2 HUGE_STRING2
|
||||
#define HUGE_STRING4 HUGE_STRING3 HUGE_STRING3 HUGE_STRING3 HUGE_STRING3
|
||||
switch (D) {
|
||||
case DiffType::Control:
|
||||
return "0123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "0123456789";
|
||||
case DiffType::ChangeFirst:
|
||||
return "-123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "0123456789";
|
||||
case DiffType::ChangeMiddle:
|
||||
return "0123456789" HUGE_STRING4 "01234-6789" HUGE_STRING4 "0123456789";
|
||||
case DiffType::ChangeLast:
|
||||
return "0123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "012345678-";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ALWAYS_INLINE std::string makeString(Length L,
|
||||
DiffType D = DiffType::Control,
|
||||
Opacity O = Opacity::Transparent) {
|
||||
switch (L) {
|
||||
case Length::Empty:
|
||||
return maybeOpaque("", O == Opacity::Opaque);
|
||||
case Length::Small:
|
||||
return maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
case Length::Large:
|
||||
return maybeOpaque(getLargeString(D), O == Opacity::Opaque);
|
||||
case Length::Huge:
|
||||
return maybeOpaque(getHugeString(D), O == Opacity::Opaque);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Length, class Opaque>
|
||||
struct StringConstructDestroyCStr {
|
||||
static void run(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(
|
||||
makeString(Length(), DiffType::Control, Opaque()));
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringConstructDestroyCStr" + Length::name() + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Length, bool MeasureCopy, bool MeasureDestroy>
|
||||
static void StringCopyAndDestroy(benchmark::State& state) {
|
||||
static constexpr size_t NumStrings = 1024;
|
||||
auto Orig = makeString(Length());
|
||||
std::aligned_storage<sizeof(std::string)>::type Storage[NumStrings];
|
||||
|
||||
while (state.KeepRunningBatch(NumStrings)) {
|
||||
if (!MeasureCopy)
|
||||
state.PauseTiming();
|
||||
for (size_t I = 0; I < NumStrings; ++I) {
|
||||
::new (static_cast<void*>(Storage + I)) std::string(Orig);
|
||||
}
|
||||
if (!MeasureCopy)
|
||||
state.ResumeTiming();
|
||||
if (!MeasureDestroy)
|
||||
state.PauseTiming();
|
||||
for (size_t I = 0; I < NumStrings; ++I) {
|
||||
using S = std::string;
|
||||
reinterpret_cast<S*>(Storage + I)->~S();
|
||||
}
|
||||
if (!MeasureDestroy)
|
||||
state.ResumeTiming();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Length>
|
||||
struct StringCopy {
|
||||
static void run(benchmark::State& state) {
|
||||
StringCopyAndDestroy<Length, true, false>(state);
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_StringCopy" + Length::name(); }
|
||||
};
|
||||
|
||||
template <class Length>
|
||||
struct StringDestroy {
|
||||
static void run(benchmark::State& state) {
|
||||
StringCopyAndDestroy<Length, false, true>(state);
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_StringDestroy" + Length::name(); }
|
||||
};
|
||||
|
||||
template <class Length>
|
||||
struct StringMove {
|
||||
static void run(benchmark::State& state) {
|
||||
// Keep two object locations and move construct back and forth.
|
||||
std::aligned_storage<sizeof(std::string), alignof(std::string)>::type Storage[2];
|
||||
using S = std::string;
|
||||
size_t I = 0;
|
||||
S *newS = new (static_cast<void*>(Storage)) std::string(makeString(Length()));
|
||||
for (auto _ : state) {
|
||||
// Switch locations.
|
||||
I ^= 1;
|
||||
benchmark::DoNotOptimize(Storage);
|
||||
// Move construct into the new location,
|
||||
S *tmpS = new (static_cast<void*>(Storage + I)) S(std::move(*newS));
|
||||
// then destroy the old one.
|
||||
newS->~S();
|
||||
newS = tmpS;
|
||||
}
|
||||
newS->~S();
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_StringMove" + Length::name(); }
|
||||
};
|
||||
|
||||
enum class Relation { Eq, Less, Compare };
|
||||
struct AllRelations : EnumValuesAsTuple<AllRelations, Relation, 3> {
|
||||
static constexpr const char* Names[] = {"Eq", "Less", "Compare"};
|
||||
};
|
||||
|
||||
template <class Rel, class LHLength, class RHLength, class DiffType>
|
||||
struct StringRelational {
|
||||
static void run(benchmark::State& state) {
|
||||
auto Lhs = makeString(RHLength());
|
||||
auto Rhs = makeString(LHLength(), DiffType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(Lhs);
|
||||
benchmark::DoNotOptimize(Rhs);
|
||||
switch (Rel()) {
|
||||
case Relation::Eq:
|
||||
benchmark::DoNotOptimize(Lhs == Rhs);
|
||||
break;
|
||||
case Relation::Less:
|
||||
benchmark::DoNotOptimize(Lhs < Rhs);
|
||||
break;
|
||||
case Relation::Compare:
|
||||
benchmark::DoNotOptimize(Lhs.compare(Rhs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() {
|
||||
// Eq is commutative, so skip half the matrix.
|
||||
if (Rel() == Relation::Eq && LHLength() > RHLength())
|
||||
return true;
|
||||
// We only care about control when the lengths differ.
|
||||
if (LHLength() != RHLength() && DiffType() != ::DiffType::Control)
|
||||
return true;
|
||||
// For empty, only control matters.
|
||||
if (LHLength() == Length::Empty && DiffType() != ::DiffType::Control)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringRelational" + Rel::name() + LHLength::name() +
|
||||
RHLength::name() + DiffType::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Rel, class LHLength, class RHLength, class DiffType>
|
||||
struct StringRelationalLiteral {
|
||||
static void run(benchmark::State& state) {
|
||||
auto Lhs = makeString(LHLength(), DiffType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(Lhs);
|
||||
constexpr const char* Literal = RHLength::value == Length::Empty
|
||||
? ""
|
||||
: RHLength::value == Length::Small
|
||||
? SmallStringLiteral
|
||||
: LargeStringLiteral;
|
||||
switch (Rel()) {
|
||||
case Relation::Eq:
|
||||
benchmark::DoNotOptimize(Lhs == Literal);
|
||||
break;
|
||||
case Relation::Less:
|
||||
benchmark::DoNotOptimize(Lhs < Literal);
|
||||
break;
|
||||
case Relation::Compare:
|
||||
benchmark::DoNotOptimize(Lhs.compare(Literal));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() {
|
||||
// Doesn't matter how they differ if they have different size.
|
||||
if (LHLength() != RHLength() && DiffType() != ::DiffType::Control)
|
||||
return true;
|
||||
// We don't need huge. Doensn't give anything different than Large.
|
||||
if (LHLength() == Length::Huge || RHLength() == Length::Huge)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringRelationalLiteral" + Rel::name() + LHLength::name() +
|
||||
RHLength::name() + DiffType::name();
|
||||
}
|
||||
};
|
||||
|
||||
enum class Depth { Shallow, Deep };
|
||||
struct AllDepths : EnumValuesAsTuple<AllDepths, Depth, 2> {
|
||||
static constexpr const char* Names[] = {"Shallow", "Deep"};
|
||||
};
|
||||
|
||||
enum class Temperature { Hot, Cold };
|
||||
struct AllTemperatures : EnumValuesAsTuple<AllTemperatures, Temperature, 2> {
|
||||
static constexpr const char* Names[] = {"Hot", "Cold"};
|
||||
};
|
||||
|
||||
template <class Temperature, class Depth, class Length>
|
||||
struct StringRead {
|
||||
void run(benchmark::State& state) const {
|
||||
static constexpr size_t NumStrings =
|
||||
Temperature() == ::Temperature::Hot
|
||||
? 1 << 10
|
||||
: /* Enough strings to overflow the cache */ 1 << 20;
|
||||
static_assert((NumStrings & (NumStrings - 1)) == 0,
|
||||
"NumStrings should be a power of two to reduce overhead.");
|
||||
|
||||
std::vector<std::string> Values(NumStrings, makeString(Length()));
|
||||
size_t I = 0;
|
||||
for (auto _ : state) {
|
||||
// Jump long enough to defeat cache locality, and use a value that is
|
||||
// coprime with NumStrings to ensure we visit every element.
|
||||
I = (I + 17) % NumStrings;
|
||||
const auto& V = Values[I];
|
||||
|
||||
// Read everything first. Escaping data() through DoNotOptimize might
|
||||
// cause the compiler to have to recalculate information about `V` due to
|
||||
// aliasing.
|
||||
const char* const Data = V.data();
|
||||
const size_t Size = V.size();
|
||||
benchmark::DoNotOptimize(Data);
|
||||
benchmark::DoNotOptimize(Size);
|
||||
if (Depth() == ::Depth::Deep) {
|
||||
// Read into the payload. This mainly shows the benefit of SSO when the
|
||||
// data is cold.
|
||||
benchmark::DoNotOptimize(*Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() {
|
||||
// Huge does not give us anything that Large doesn't have. Skip it.
|
||||
if (Length() == ::Length::Huge) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_StringRead" + Temperature::name() + Depth::name() +
|
||||
Length::name();
|
||||
}
|
||||
};
|
||||
|
||||
void sanityCheckGeneratedStrings() {
|
||||
for (auto Lhs : {Length::Empty, Length::Small, Length::Large, Length::Huge}) {
|
||||
const auto LhsString = makeString(Lhs);
|
||||
for (auto Rhs :
|
||||
{Length::Empty, Length::Small, Length::Large, Length::Huge}) {
|
||||
if (Lhs > Rhs)
|
||||
continue;
|
||||
const auto RhsString = makeString(Rhs);
|
||||
|
||||
// The smaller one must be a prefix of the larger one.
|
||||
if (RhsString.find(LhsString) != 0) {
|
||||
fprintf(stderr, "Invalid autogenerated strings for sizes (%d,%d).\n",
|
||||
static_cast<int>(Lhs), static_cast<int>(Rhs));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Verify the autogenerated diffs
|
||||
for (auto L : {Length::Small, Length::Large, Length::Huge}) {
|
||||
const auto Control = makeString(L);
|
||||
const auto Verify = [&](std::string Exp, size_t Pos) {
|
||||
// Only change on the Pos char.
|
||||
if (Control[Pos] != Exp[Pos]) {
|
||||
Exp[Pos] = Control[Pos];
|
||||
if (Control == Exp)
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "Invalid autogenerated diff with size %d\n",
|
||||
static_cast<int>(L));
|
||||
std::abort();
|
||||
};
|
||||
Verify(makeString(L, DiffType::ChangeFirst), 0);
|
||||
Verify(makeString(L, DiffType::ChangeMiddle), Control.size() / 2);
|
||||
Verify(makeString(L, DiffType::ChangeLast), Control.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Some small codegen thunks to easily see generated code.
|
||||
bool StringEqString(const std::string& a, const std::string& b) {
|
||||
return a == b;
|
||||
}
|
||||
bool StringEqCStr(const std::string& a, const char* b) { return a == b; }
|
||||
bool CStrEqString(const char* a, const std::string& b) { return a == b; }
|
||||
bool StringEqCStrLiteralEmpty(const std::string& a) {
|
||||
return a == "";
|
||||
}
|
||||
bool StringEqCStrLiteralSmall(const std::string& a) {
|
||||
return a == SmallStringLiteral;
|
||||
}
|
||||
bool StringEqCStrLiteralLarge(const std::string& a) {
|
||||
return a == LargeStringLiteral;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
sanityCheckGeneratedStrings();
|
||||
|
||||
makeCartesianProductBenchmark<StringConstructDestroyCStr, AllLengths,
|
||||
AllOpacity>();
|
||||
makeCartesianProductBenchmark<StringCopy, AllLengths>();
|
||||
makeCartesianProductBenchmark<StringMove, AllLengths>();
|
||||
makeCartesianProductBenchmark<StringDestroy, AllLengths>();
|
||||
makeCartesianProductBenchmark<StringRelational, AllRelations, AllLengths,
|
||||
AllLengths, AllDiffTypes>();
|
||||
makeCartesianProductBenchmark<StringRelationalLiteral, AllRelations,
|
||||
AllLengths, AllLengths, AllDiffTypes>();
|
||||
makeCartesianProductBenchmark<StringRead, AllTemperatures, AllDepths,
|
||||
AllLengths>();
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
|
||||
if (argc < 0) {
|
||||
// ODR-use the functions to force them being generated in the binary.
|
||||
auto functions = std::make_tuple(
|
||||
StringEqString, StringEqCStr, CStrEqString, StringEqCStrLiteralEmpty,
|
||||
StringEqCStrLiteralSmall, StringEqCStrLiteralLarge);
|
||||
printf("%p", &functions);
|
||||
}
|
||||
}
|
||||
|
40
benchmarks/stringstream.bench.cpp
Normal file
40
benchmarks/stringstream.bench.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
TEST_NOINLINE double istream_numbers();
|
||||
|
||||
double istream_numbers() {
|
||||
const char *a[] = {
|
||||
"-6 69 -71 2.4882e-02 -100 101 -2.00005 5000000 -50000000",
|
||||
"-25 71 7 -9.3262e+01 -100 101 -2.00005 5000000 -50000000",
|
||||
"-14 53 46 -6.7026e-02 -100 101 -2.00005 5000000 -50000000"
|
||||
};
|
||||
|
||||
int a1, a2, a3, a4, a5, a6, a7;
|
||||
double f1 = 0.0, f2 = 0.0, q = 0.0;
|
||||
for (int i=0; i < 3; i++) {
|
||||
std::istringstream s(a[i]);
|
||||
s >> a1
|
||||
>> a2
|
||||
>> a3
|
||||
>> f1
|
||||
>> a4
|
||||
>> a5
|
||||
>> f2
|
||||
>> a6
|
||||
>> a7;
|
||||
q += (a1 + a2 + a3 + a4 + a5 + a6 + a7 + f1 + f2)/1000000;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
static void BM_Istream_numbers(benchmark::State &state) {
|
||||
double i = 0;
|
||||
while (state.KeepRunning())
|
||||
benchmark::DoNotOptimize(i += istream_numbers());
|
||||
}
|
||||
|
||||
BENCHMARK(BM_Istream_numbers)->RangeMultiplier(2)->Range(1024, 4096);
|
||||
BENCHMARK_MAIN();
|
@ -5,29 +5,30 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "ContainerBenchmarks.hpp"
|
||||
#include "GenerateInput.hpp"
|
||||
#include "ContainerBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
using namespace ContainerBenchmarks;
|
||||
|
||||
constexpr std::size_t TestNumInputs = 1024;
|
||||
|
||||
template <class _Size>
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
_Size loadword(const void* __p) {
|
||||
_Size __r;
|
||||
std::memcpy(&__r, __p, sizeof(__r));
|
||||
return __r;
|
||||
}
|
||||
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t rotate_by_at_least_1(std::size_t __val, int __shift) {
|
||||
return (__val >> __shift) | (__val << (64 - __shift));
|
||||
}
|
||||
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t hash_len_16(std::size_t __u, std::size_t __v) {
|
||||
const std::size_t __mul = 0x9ddfea08eb382d69ULL;
|
||||
std::size_t __a = (__u ^ __v) * __mul;
|
||||
@ -40,7 +41,7 @@ std::size_t hash_len_16(std::size_t __u, std::size_t __v) {
|
||||
|
||||
|
||||
template <std::size_t _Len>
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t hash_len_0_to_8(const char* __s) {
|
||||
static_assert(_Len == 4 || _Len == 8, "");
|
||||
const uint64_t __a = loadword<uint32_t>(__s);
|
||||
@ -50,7 +51,7 @@ std::size_t hash_len_0_to_8(const char* __s) {
|
||||
|
||||
struct UInt32Hash {
|
||||
UInt32Hash() = default;
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint32_t data) const {
|
||||
return hash_len_0_to_8<4>(reinterpret_cast<const char*>(&data));
|
||||
}
|
||||
@ -58,7 +59,7 @@ struct UInt32Hash {
|
||||
|
||||
struct UInt64Hash {
|
||||
UInt64Hash() = default;
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint64_t data) const {
|
||||
return hash_len_0_to_8<8>(reinterpret_cast<const char*>(&data));
|
||||
}
|
||||
@ -66,7 +67,7 @@ struct UInt64Hash {
|
||||
|
||||
struct UInt128Hash {
|
||||
UInt128Hash() = default;
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(__uint128_t data) const {
|
||||
const __uint128_t __mask = static_cast<std::size_t>(-1);
|
||||
const std::size_t __a = (std::size_t)(data & __mask);
|
||||
@ -77,7 +78,7 @@ struct UInt128Hash {
|
||||
|
||||
struct UInt32Hash2 {
|
||||
UInt32Hash2() = default;
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint32_t data) const {
|
||||
const uint32_t __m = 0x5bd1e995;
|
||||
const uint32_t __r = 24;
|
||||
@ -97,7 +98,7 @@ struct UInt32Hash2 {
|
||||
|
||||
struct UInt64Hash2 {
|
||||
UInt64Hash2() = default;
|
||||
inline __attribute__((__always_inline__))
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint64_t data) const {
|
||||
return hash_len_0_to_8<8>(reinterpret_cast<const char*>(&data));
|
||||
}
|
||||
@ -303,4 +304,4 @@ BENCHMARK_CAPTURE(BM_EmplaceDuplicate,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomCStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_MAIN()
|
||||
BENCHMARK_MAIN();
|
||||
|
@ -1,42 +1,41 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
|
||||
static void BM_SharedPtrCreateDestroy(benchmark::State& st) {
|
||||
while (st.KeepRunning()) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SharedPtrCreateDestroy);
|
||||
|
||||
static void BM_SharedPtrIncDecRef(benchmark::State& st) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
while (st.KeepRunning()) {
|
||||
std::shared_ptr<int> sp2(sp);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SharedPtrIncDecRef);
|
||||
|
||||
static void BM_WeakPtrIncDecRef(benchmark::State& st) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
while (st.KeepRunning()) {
|
||||
std::weak_ptr<int> wp(sp);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_WeakPtrIncDecRef);
|
||||
|
||||
BENCHMARK_MAIN()
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
static void BM_SharedPtrCreateDestroy(benchmark::State& st) {
|
||||
while (st.KeepRunning()) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SharedPtrCreateDestroy);
|
||||
|
||||
static void BM_SharedPtrIncDecRef(benchmark::State& st) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
while (st.KeepRunning()) {
|
||||
std::shared_ptr<int> sp2(sp);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SharedPtrIncDecRef);
|
||||
|
||||
static void BM_WeakPtrIncDecRef(benchmark::State& st) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
while (st.KeepRunning()) {
|
||||
std::weak_ptr<int> wp(sp);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_WeakPtrIncDecRef);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
@ -4,15 +4,23 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "benchmark/benchmark_api.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "ContainerBenchmarks.hpp"
|
||||
#include "GenerateInput.hpp"
|
||||
#include "ContainerBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
|
||||
using namespace ContainerBenchmarks;
|
||||
|
||||
constexpr std::size_t TestNumInputs = 1024;
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSize,
|
||||
vector_byte,
|
||||
std::vector<unsigned char>{})->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSizeValue,
|
||||
vector_byte,
|
||||
std::vector<unsigned char>{}, 0)->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
vector_char,
|
||||
std::vector<char>{},
|
||||
@ -29,4 +37,4 @@ BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
BENCHMARK_MAIN()
|
||||
BENCHMARK_MAIN();
|
||||
|
@ -9,7 +9,7 @@ INCLUDE(CheckCXXSourceCompiles)
|
||||
|
||||
function(check_cxx_atomics varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-nodefaultlibs -std=c++11 -nostdinc++ -isystem ${LIBCXX_SOURCE_DIR}/include")
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs -std=c++11 -nostdinc++ -isystem ${LIBCXX_SOURCE_DIR}/include")
|
||||
if (${LIBCXX_GCC_TOOLCHAIN})
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} --gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}")
|
||||
endif()
|
||||
@ -24,14 +24,23 @@ function(check_cxx_atomics varname)
|
||||
#include <atomic>
|
||||
std::atomic<uintptr_t> x;
|
||||
std::atomic<uintmax_t> y;
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
return x + y;
|
||||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction(check_cxx_atomics)
|
||||
|
||||
check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
# Perform the check for 64bit atomics without libatomic. It may have been
|
||||
# added to the required libraries during in the configuration of LLVM, which
|
||||
# would cause the check for CXX atomics without libatomic to incorrectly pass.
|
||||
if (CMAKE_REQUIRED_LIBRARIES)
|
||||
set(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES})
|
||||
endif()
|
||||
|
||||
check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB)
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
|
52
cmake/Modules/DefineLinkerScript.cmake
Normal file
52
cmake/Modules/DefineLinkerScript.cmake
Normal file
@ -0,0 +1,52 @@
|
||||
# This function defines a linker script in place of the symlink traditionally
|
||||
# created for shared libraries.
|
||||
#
|
||||
# More specifically, this function goes through the PUBLIC and INTERFACE
|
||||
# library dependencies of <target> and gathers them into a linker script,
|
||||
# such that those libraries are linked against when the shared library for
|
||||
# <target> is linked against.
|
||||
#
|
||||
# Arguments:
|
||||
# <target>: A target representing a shared library. A linker script will be
|
||||
# created in place of that target's TARGET_LINKER_FILE, which is
|
||||
# the symlink pointing to the actual shared library (usually
|
||||
# libFoo.so pointing to libFoo.so.1, which itself points to
|
||||
# libFoo.so.1.0).
|
||||
|
||||
function(define_linker_script target)
|
||||
if (NOT TARGET "${target}")
|
||||
message(FATAL_ERROR "The provided target '${target}' is not actually a target.")
|
||||
endif()
|
||||
|
||||
get_target_property(target_type "${target}" TYPE)
|
||||
if (NOT "${target_type}" STREQUAL "SHARED_LIBRARY")
|
||||
message(FATAL_ERROR "The provided target '${target}' is not a shared library (its type is '${target_type}').")
|
||||
endif()
|
||||
|
||||
set(symlink "$<TARGET_LINKER_FILE:${target}>")
|
||||
set(soname "$<TARGET_SONAME_FILE_NAME:${target}>")
|
||||
|
||||
get_target_property(interface_libs "${target}" INTERFACE_LINK_LIBRARIES)
|
||||
|
||||
set(link_libraries)
|
||||
if (interface_libs)
|
||||
foreach(lib IN LISTS interface_libs)
|
||||
if (TARGET "${lib}" OR
|
||||
(${lib} MATCHES "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI) OR
|
||||
(${lib} MATCHES "unwind(_static|_shared)?" AND HAVE_LIBUNWIND))
|
||||
list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}$<TARGET_PROPERTY:${lib},OUTPUT_NAME>")
|
||||
else()
|
||||
list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}${lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
string(REPLACE ";" " " link_libraries "${link_libraries}")
|
||||
|
||||
set(linker_script "INPUT(${soname} ${link_libraries})")
|
||||
add_custom_command(TARGET "${target}" POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E remove "${symlink}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "${symlink}"
|
||||
COMMENT "Generating linker script: '${linker_script}' as file ${symlink}"
|
||||
VERBATIM
|
||||
)
|
||||
endfunction()
|
@ -5,12 +5,19 @@ function(find_compiler_rt_library name dest)
|
||||
set(dest "" PARENT_SCOPE)
|
||||
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBCXX_COMPILE_FLAGS}
|
||||
"--rtlib=compiler-rt" "--print-libgcc-file-name")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_TARGET)
|
||||
list(APPEND CLANG_COMMAND "--target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
endif()
|
||||
get_property(LIBCXX_CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
|
||||
string(REPLACE " " ";" LIBCXX_CXX_FLAGS "${LIBCXX_CXX_FLAGS}")
|
||||
list(APPEND CLANG_COMMAND ${LIBCXX_CXX_FLAGS})
|
||||
execute_process(
|
||||
COMMAND ${CLANG_COMMAND}
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE LIBRARY_FILE
|
||||
)
|
||||
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
|
||||
file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
|
||||
string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}")
|
||||
if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}")
|
||||
message(STATUS "Found compiler-rt library: ${LIBRARY_FILE}")
|
||||
@ -34,6 +41,7 @@ function(find_compiler_rt_dir dest)
|
||||
OUTPUT_VARIABLE LIBRARY_DIR
|
||||
)
|
||||
string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR)
|
||||
file(TO_CMAKE_PATH "${LIBRARY_DIR}" LIBRARY_DIR)
|
||||
set(LIBRARY_DIR "${LIBRARY_DIR}/darwin")
|
||||
else()
|
||||
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBCXX_COMPILE_FLAGS}
|
||||
@ -44,6 +52,7 @@ function(find_compiler_rt_dir dest)
|
||||
OUTPUT_VARIABLE LIBRARY_FILE
|
||||
)
|
||||
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
|
||||
file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
|
||||
get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY)
|
||||
endif()
|
||||
if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}")
|
||||
|
@ -8,7 +8,8 @@
|
||||
#
|
||||
# Parameters:
|
||||
# abidefines: A list of defines needed to compile libc++ with the ABI library
|
||||
# abilib : The ABI library to link against.
|
||||
# abishared : The shared ABI library to link against.
|
||||
# abistatic : The static ABI library to link against.
|
||||
# abifiles : A list of files (which may be relative paths) to copy into the
|
||||
# libc++ build tree for the build. These files will be copied
|
||||
# twice: once into include/, so the libc++ build itself can find
|
||||
@ -19,7 +20,7 @@
|
||||
# in the libc++ build directory.
|
||||
#
|
||||
|
||||
macro(setup_abi_lib abidefines abilib abifiles abidirs)
|
||||
macro(setup_abi_lib abidefines abishared abistatic abifiles abidirs)
|
||||
list(APPEND LIBCXX_COMPILE_FLAGS ${abidefines})
|
||||
set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_CXX_ABI_INCLUDE_PATHS}"
|
||||
CACHE PATH
|
||||
@ -29,17 +30,10 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs)
|
||||
CACHE PATH
|
||||
"Paths to C++ ABI library directory"
|
||||
)
|
||||
set(LIBCXX_CXX_ABI_LIBRARY ${abilib})
|
||||
set(LIBCXX_CXX_SHARED_ABI_LIBRARY ${abishared})
|
||||
set(LIBCXX_CXX_STATIC_ABI_LIBRARY ${abistatic})
|
||||
set(LIBCXX_ABILIB_FILES ${abifiles})
|
||||
|
||||
# The place in the build tree where we store out-of-source headers.
|
||||
file(MAKE_DIRECTORY "${LIBCXX_BUILD_HEADERS_ROOT}")
|
||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1")
|
||||
foreach(_d ${abidirs})
|
||||
file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}/${_d}")
|
||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1/${_d}")
|
||||
endforeach()
|
||||
|
||||
foreach(fpath ${LIBCXX_ABILIB_FILES})
|
||||
set(found FALSE)
|
||||
foreach(incpath ${LIBCXX_CXX_ABI_INCLUDE_PATHS})
|
||||
@ -47,20 +41,31 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs)
|
||||
set(found TRUE)
|
||||
get_filename_component(dstdir ${fpath} PATH)
|
||||
get_filename_component(ifile ${fpath} NAME)
|
||||
file(COPY "${incpath}/${fpath}"
|
||||
DESTINATION "${LIBCXX_BINARY_INCLUDE_DIR}/${dstdir}"
|
||||
)
|
||||
file(COPY "${incpath}/${fpath}"
|
||||
DESTINATION "${CMAKE_BINARY_DIR}/include/c++/v1/${dstdir}"
|
||||
)
|
||||
set(src ${incpath}/${fpath})
|
||||
|
||||
set(dst ${LIBCXX_BINARY_INCLUDE_DIR}/${dstdir}/${ifile})
|
||||
add_custom_command(OUTPUT ${dst}
|
||||
DEPENDS ${src}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
|
||||
COMMENT "Copying C++ ABI header ${fpath}...")
|
||||
list(APPEND abilib_headers "${dst}")
|
||||
|
||||
if (NOT LIBCXX_USING_INSTALLED_LLVM AND LIBCXX_HEADER_DIR)
|
||||
set(dst "${LIBCXX_HEADER_DIR}/include/c++/v1/${dstdir}/${fpath}")
|
||||
add_custom_command(OUTPUT ${dst}
|
||||
DEPENDS ${src}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
|
||||
COMMENT "Copying C++ ABI header ${fpath}...")
|
||||
list(APPEND abilib_headers "${dst}")
|
||||
endif()
|
||||
|
||||
if (LIBCXX_INSTALL_HEADERS)
|
||||
install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}"
|
||||
DESTINATION include/c++/v1/${dstdir}
|
||||
COMPONENT libcxx
|
||||
DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dstdir}
|
||||
COMPONENT cxx-headers
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
)
|
||||
endif()
|
||||
list(APPEND abilib_headers "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}")
|
||||
endif()
|
||||
endforeach()
|
||||
if (NOT found)
|
||||
@ -69,6 +74,8 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs)
|
||||
endforeach()
|
||||
|
||||
include_directories("${LIBCXX_BINARY_INCLUDE_DIR}")
|
||||
add_custom_target(cxx_abi_headers ALL DEPENDS ${abilib_headers})
|
||||
set(LIBCXX_CXX_ABI_HEADER_TARGET "cxx_abi_headers")
|
||||
endmacro()
|
||||
|
||||
|
||||
@ -88,29 +95,30 @@ if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR
|
||||
endif()
|
||||
setup_abi_lib(
|
||||
"-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}"
|
||||
"${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits"
|
||||
"${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits"
|
||||
)
|
||||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi")
|
||||
if (LIBCXX_CXX_ABI_INTREE)
|
||||
# Link against just-built "cxxabi" target.
|
||||
if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY)
|
||||
set(CXXABI_LIBNAME cxxabi_static)
|
||||
else()
|
||||
set(CXXABI_LIBNAME cxxabi_shared)
|
||||
endif()
|
||||
set(LIBCXX_LIBCPPABI_VERSION "2" PARENT_SCOPE)
|
||||
set(CXXABI_SHARED_LIBNAME cxxabi_shared)
|
||||
set(CXXABI_STATIC_LIBNAME cxxabi_static)
|
||||
else()
|
||||
# Assume c++abi is installed in the system, rely on -lc++abi link flag.
|
||||
set(CXXABI_LIBNAME "c++abi")
|
||||
set(CXXABI_SHARED_LIBNAME "c++abi")
|
||||
set(CXXABI_STATIC_LIBNAME "c++abi")
|
||||
endif()
|
||||
set(HEADERS "cxxabi.h;__cxxabi_config.h")
|
||||
if (LIBCXX_CXX_ABI_SYSTEM)
|
||||
set(HEADERS "")
|
||||
else()
|
||||
set(HEADERS "cxxabi.h;__cxxabi_config.h")
|
||||
endif()
|
||||
setup_abi_lib("-DLIBCXX_BUILDING_LIBCXXABI" ${CXXABI_LIBNAME} "${HEADERS}" "")
|
||||
setup_abi_lib(
|
||||
"-DLIBCXX_BUILDING_LIBCXXABI"
|
||||
"${CXXABI_SHARED_LIBNAME}" "${CXXABI_STATIC_LIBNAME}" "${HEADERS}" "")
|
||||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt")
|
||||
setup_abi_lib("-DLIBCXXRT"
|
||||
"cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" ""
|
||||
setup_abi_lib(
|
||||
"-DLIBCXXRT"
|
||||
"cxxrt" "cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" ""
|
||||
)
|
||||
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "vcruntime")
|
||||
# Nothing TODO
|
||||
|
@ -16,6 +16,7 @@ macro(mangle_name str output)
|
||||
string(REGEX REPLACE "^-+" "" strippedStr "${strippedStr}")
|
||||
string(REGEX REPLACE "-+$" "" strippedStr "${strippedStr}")
|
||||
string(REPLACE "-" "_" strippedStr "${strippedStr}")
|
||||
string(REPLACE ":" "_COLON_" strippedStr "${strippedStr}")
|
||||
string(REPLACE "=" "_EQ_" strippedStr "${strippedStr}")
|
||||
string(REPLACE "+" "X" strippedStr "${strippedStr}")
|
||||
string(TOUPPER "${strippedStr}" ${output})
|
||||
@ -44,6 +45,29 @@ macro(check_flag_supported flag)
|
||||
check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG")
|
||||
endmacro()
|
||||
|
||||
macro(append_flags DEST)
|
||||
foreach(value ${ARGN})
|
||||
list(APPEND ${DEST} ${value})
|
||||
list(APPEND ${DEST} ${value})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# If the specified 'condition' is true then append the specified list of flags to DEST
|
||||
macro(append_flags_if condition DEST)
|
||||
if (${condition})
|
||||
list(APPEND ${DEST} ${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add each flag in the list specified by DEST if that flag is supported by the current compiler.
|
||||
macro(append_flags_if_supported DEST)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG")
|
||||
append_flags_if(LIBCXX_SUPPORTS_${flagname}_FLAG ${DEST} ${flag})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Add a macro definition if condition is true.
|
||||
macro(define_if condition def)
|
||||
if (${condition})
|
||||
@ -192,15 +216,31 @@ macro(add_library_flags_if condition)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add a list of libraries or link flags to 'LIBCXX_LIBRARIES'.
|
||||
macro(add_interface_library)
|
||||
foreach(lib ${ARGN})
|
||||
list(APPEND LIBCXX_LIBRARIES ${lib})
|
||||
list(APPEND LIBCXX_INTERFACE_LIBRARIES ${lib})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Turn a comma separated CMake list into a space separated string.
|
||||
macro(split_list listname)
|
||||
string(REPLACE ";" " " ${listname} "${${listname}}")
|
||||
endmacro()
|
||||
|
||||
# For each specified flag, add that link flag to the provided target.
|
||||
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
|
||||
function(target_add_link_flags_if_supported target visibility)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG")
|
||||
if (LIBCXX_SUPPORTS_${flagname}_FLAG)
|
||||
target_link_libraries(${target} ${visibility} ${flag})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# For each specified flag, add that compile flag to the provided target.
|
||||
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
|
||||
function(target_add_compile_flags_if_supported target visibility)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG")
|
||||
if (LIBCXX_SUPPORTS_${flagname}_FLAG)
|
||||
target_compile_options(${target} ${visibility} ${flag})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
@ -9,6 +9,9 @@ macro(find_llvm_parts)
|
||||
set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree")
|
||||
set(LLVM_MAIN_SRC_DIR ${LLVM_PATH})
|
||||
set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules")
|
||||
if (NOT IS_DIRECTORY "${LLVM_PATH}")
|
||||
message(FATAL_ERROR "The provided LLVM_PATH (${LLVM_PATH}) is not a valid directory")
|
||||
endif()
|
||||
elseif(LLVM_CONFIG_PATH)
|
||||
message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}")
|
||||
set(LIBCXX_USING_INSTALLED_LLVM 1)
|
||||
@ -46,10 +49,11 @@ macro(find_llvm_parts)
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT
|
||||
ERROR_QUIET)
|
||||
if(NOT HAD_ERROR)
|
||||
string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH)
|
||||
string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
|
||||
file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH)
|
||||
else()
|
||||
set(LLVM_CMAKE_PATH
|
||||
"${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
|
||||
file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE)
|
||||
set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
|
||||
endif()
|
||||
else()
|
||||
set(LLVM_FOUND OFF)
|
||||
@ -106,14 +110,22 @@ macro(configure_out_of_tree_llvm)
|
||||
set(LLVM_ENABLE_SPHINX OFF)
|
||||
endif()
|
||||
|
||||
# Required LIT Configuration ------------------------------------------------
|
||||
# Define the default arguments to use with 'lit', and an option for the user
|
||||
# to override.
|
||||
set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported")
|
||||
if (MSVC OR XCODE)
|
||||
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
|
||||
# In a standalone build, we don't have llvm to automatically generate the
|
||||
# llvm-lit script for us. So we need to provide an explicit directory that
|
||||
# the configurator should write the script into.
|
||||
set(LLVM_LIT_OUTPUT_DIR "${libcxx_BINARY_DIR}/bin")
|
||||
|
||||
if (LLVM_INCLUDE_TESTS)
|
||||
# Required LIT Configuration ------------------------------------------------
|
||||
# Define the default arguments to use with 'lit', and an option for the user
|
||||
# to override.
|
||||
set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py")
|
||||
set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported")
|
||||
if (MSVC OR XCODE)
|
||||
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
|
||||
endif()
|
||||
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
|
||||
endif()
|
||||
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
|
||||
|
||||
# Required doc configuration
|
||||
if (LLVM_ENABLE_SPHINX)
|
||||
|
15
cmake/caches/Apple.cmake
Normal file
15
cmake/caches/Apple.cmake
Normal file
@ -0,0 +1,15 @@
|
||||
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "")
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE OFF CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_ASSERTIONS ON CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_ABI_VERSION "1" CACHE STRING "")
|
||||
|
||||
set(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY OFF CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_STATIC OFF CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_HIDE_FROM_ABI_PER_TU_BY_DEFAULT ON CACHE BOOL "")
|
@ -1,5 +1,8 @@
|
||||
include(CMakePushCheckState)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
if(WIN32 AND NOT MINGW)
|
||||
# NOTE(compnerd) this is technically a lie, there is msvcrt, but for now, lets
|
||||
@ -24,17 +27,32 @@ endif()
|
||||
# required during compilation (which has the -nodefaultlibs). libc is
|
||||
# required for the link to go through. We remove sanitizers from the
|
||||
# configuration checks to avoid spurious link errors.
|
||||
check_cxx_compiler_flag(-nodefaultlibs LIBCXX_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
check_c_compiler_flag(-nodefaultlibs LIBCXX_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
if (LIBCXX_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
|
||||
if (LIBCXX_HAS_C_LIB)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
|
||||
endif ()
|
||||
if (LIBCXX_USE_COMPILER_RT)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES -rtlib=compiler-rt)
|
||||
list(APPEND CMAKE_REQUIRED_FLAGS -rtlib=compiler-rt)
|
||||
find_compiler_rt_library(builtins LIBCXX_BUILTINS_LIBRARY)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBCXX_BUILTINS_LIBRARY}")
|
||||
elseif (LIBCXX_HAS_GCC_S_LIB)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
|
||||
endif ()
|
||||
if (MINGW)
|
||||
# Mingw64 requires quite a few "C" runtime libraries in order for basic
|
||||
# programs to link successfully with -nodefaultlibs.
|
||||
if (LIBCXX_USE_COMPILER_RT)
|
||||
set(MINGW_RUNTIME ${LIBCXX_BUILTINS_LIBRARY})
|
||||
else ()
|
||||
set(MINGW_RUNTIME gcc_s gcc)
|
||||
endif()
|
||||
set(MINGW_LIBRARIES mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt advapi32
|
||||
shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME}
|
||||
moldname mingwex msvcrt)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES})
|
||||
endif()
|
||||
if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all")
|
||||
endif ()
|
||||
@ -43,20 +61,21 @@ if (LIBCXX_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Check compiler pragmas
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unknown-pragmas")
|
||||
check_c_source_compiles("
|
||||
#pragma comment(lib, \"c\")
|
||||
int main() { return 0; }
|
||||
" LIBCXX_HAS_COMMENT_LIB_PRAGMA)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 OR MINGW)
|
||||
include(CheckLibcxxAtomic)
|
||||
endif()
|
||||
|
||||
# Check compiler flags
|
||||
|
||||
check_cxx_compiler_flag(/WX LIBCXX_HAS_WX_FLAG)
|
||||
check_cxx_compiler_flag(/WX- LIBCXX_HAS_NO_WX_FLAG)
|
||||
check_cxx_compiler_flag(/EHsc LIBCXX_HAS_EHSC_FLAG)
|
||||
check_cxx_compiler_flag(/EHs- LIBCXX_HAS_NO_EHS_FLAG)
|
||||
check_cxx_compiler_flag(/EHa- LIBCXX_HAS_NO_EHA_FLAG)
|
||||
check_cxx_compiler_flag(/GR- LIBCXX_HAS_NO_GR_FLAG)
|
||||
|
||||
|
||||
# Check libraries
|
||||
if(WIN32 AND NOT MINGW)
|
||||
# TODO(compnerd) do we want to support an emulation layer that allows for the
|
||||
@ -64,8 +83,15 @@ if(WIN32 AND NOT MINGW)
|
||||
set(LIBCXX_HAS_PTHREAD_LIB NO)
|
||||
set(LIBCXX_HAS_M_LIB NO)
|
||||
set(LIBCXX_HAS_RT_LIB NO)
|
||||
set(LIBCXX_HAS_SYSTEM_LIB NO)
|
||||
elseif(APPLE)
|
||||
check_library_exists(System write "" LIBCXX_HAS_SYSTEM_LIB)
|
||||
set(LIBCXX_HAS_PTHREAD_LIB NO)
|
||||
set(LIBCXX_HAS_M_LIB NO)
|
||||
set(LIBCXX_HAS_RT_LIB NO)
|
||||
else()
|
||||
check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB)
|
||||
check_library_exists(m ccos "" LIBCXX_HAS_M_LIB)
|
||||
check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB)
|
||||
set(LIBCXX_HAS_SYSTEM_LIB NO)
|
||||
endif()
|
||||
|
@ -18,33 +18,10 @@ Xcode 4.2 or later. However if you want to install tip-of-trunk from here
|
||||
|
||||
The basic steps needed to build libc++ are:
|
||||
|
||||
#. Checkout LLVM:
|
||||
|
||||
* ``cd where-you-want-llvm-to-live``
|
||||
* ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm``
|
||||
|
||||
#. Checkout libc++:
|
||||
|
||||
* ``cd where-you-want-llvm-to-live``
|
||||
* ``cd llvm/projects``
|
||||
* ``svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx``
|
||||
|
||||
#. Checkout libc++abi:
|
||||
|
||||
* ``cd where-you-want-llvm-to-live``
|
||||
* ``cd llvm/projects``
|
||||
* ``svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi``
|
||||
|
||||
#. Configure and build libc++ with libc++abi:
|
||||
|
||||
CMake is the only supported configuration system.
|
||||
|
||||
Clang is the preferred compiler when building and using libc++.
|
||||
|
||||
* ``cd where you want to build llvm``
|
||||
* ``mkdir build``
|
||||
* ``cd build``
|
||||
* ``cmake -G <generator> [options] <path to llvm sources>``
|
||||
#. Checkout and configure LLVM (including libc++ and libc++abi), according to the `LLVM
|
||||
getting started <https://llvm.org/docs/GettingStarted.html>`_ documentation. Make sure
|
||||
to include ``libcxx`` and ``libcxxabi`` in the ``LLVM_ENABLE_PROJECTS`` option passed
|
||||
to CMake.
|
||||
|
||||
For more information about configuring libc++ see :ref:`CMake Options`.
|
||||
|
||||
@ -64,30 +41,28 @@ The basic steps needed to build libc++ are:
|
||||
|
||||
.. warning::
|
||||
* Replacing your systems libc++ installation could render the system non-functional.
|
||||
* Mac OS X will not boot without a valid copy of ``libc++.1.dylib`` in ``/usr/lib``.
|
||||
* macOS will not boot without a valid copy of ``libc++.1.dylib`` in ``/usr/lib``.
|
||||
|
||||
|
||||
The instructions are for building libc++ on
|
||||
FreeBSD, Linux, or Mac using `libc++abi`_ as the C++ ABI library.
|
||||
On Linux, it is also possible to use :ref:`libsupc++ <libsupcxx>` or libcxxrt.
|
||||
|
||||
It is sometimes beneficial to build outside of the LLVM tree. An out-of-tree
|
||||
build would look like this:
|
||||
It is sometimes beneficial to build separately from the full LLVM build. An
|
||||
out-of-tree build would look like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd where-you-want-libcxx-to-live
|
||||
$ # Check out llvm, libc++ and libc++abi.
|
||||
$ ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm``
|
||||
$ ``svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx``
|
||||
$ ``svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi``
|
||||
$ # Check out the sources (includes everything, but we'll only use libcxx)
|
||||
$ ``git clone https://github.com/llvm/llvm-project.git``
|
||||
$ cd where-you-want-to-build
|
||||
$ mkdir build && cd build
|
||||
$ export CC=clang CXX=clang++
|
||||
$ cmake -DLLVM_PATH=path/to/llvm \
|
||||
$ cmake -DLLVM_PATH=path/to/separate/llvm \
|
||||
-DLIBCXX_CXX_ABI=libcxxabi \
|
||||
-DLIBCXX_CXX_ABI_INCLUDE_PATHS=path/to/libcxxabi/include \
|
||||
path/to/libcxx
|
||||
-DLIBCXX_CXX_ABI_INCLUDE_PATHS=path/to/separate/libcxxabi/include \
|
||||
path/to/llvm-project/libcxx
|
||||
$ make
|
||||
$ make check-libcxx # optional
|
||||
|
||||
@ -130,7 +105,7 @@ just specify a toolset.
|
||||
-DCMAKE_SYSTEM_NAME=Windows ^
|
||||
-DCMAKE_C_COMPILER=clang-cl ^
|
||||
-DCMAKE_C_FLAGS="-fms-compatibility-version=19.00 --target=i686--windows" ^
|
||||
-DCMAKE_CXX_COMPILER=clang-c ^
|
||||
-DCMAKE_CXX_COMPILER=clang-cl ^
|
||||
-DCMAKE_CXX_FLAGS="-fms-compatibility-version=19.00 --target=i686--windows" ^
|
||||
-DLLVM_PATH=/path/to/llvm/tree ^
|
||||
-DLIBCXX_ENABLE_SHARED=YES ^
|
||||
@ -216,6 +191,27 @@ libc++ specific options
|
||||
Extra suffix to append to the directory where libraries are to be installed.
|
||||
This option overrides `LLVM_LIBDIR_SUFFIX`.
|
||||
|
||||
.. option:: LIBCXX_INSTALL_PREFIX:STRING
|
||||
|
||||
**Default**: ``""``
|
||||
|
||||
Define libc++ destination prefix.
|
||||
|
||||
.. option:: LIBCXX_HERMETIC_STATIC_LIBRARY:BOOL
|
||||
|
||||
**Default**: ``OFF``
|
||||
|
||||
Do not export any symbols from the static libc++ library.
|
||||
This is useful when the static libc++ library is being linked into shared
|
||||
libraries that may be used in with other shared libraries that use different
|
||||
C++ library. We want to avoid exporting any libc++ symbols in that case.
|
||||
|
||||
.. option:: LIBCXX_ENABLE_FILESYSTEM:BOOL
|
||||
|
||||
**Default**: ``ON`` except on Windows.
|
||||
|
||||
This option can be used to enable or disable the filesystem components on
|
||||
platforms that may not support them. For example on Windows.
|
||||
|
||||
.. _libc++experimental options:
|
||||
|
||||
@ -235,14 +231,6 @@ libc++experimental Specific Options
|
||||
Install libc++experimental.a alongside libc++.
|
||||
|
||||
|
||||
.. option:: LIBCXX_ENABLE_FILESYSTEM:BOOL
|
||||
|
||||
**Default**: ``LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY``
|
||||
|
||||
Build filesystem as part of libc++experimental.a. This allows filesystem
|
||||
to be disabled without turning off the entire experimental library.
|
||||
|
||||
|
||||
.. _ABI Library Specific Options:
|
||||
|
||||
ABI Library Specific Options
|
||||
@ -300,6 +288,12 @@ libc++ Feature Options
|
||||
|
||||
Build libc++ with run time type information.
|
||||
|
||||
.. option:: LIBCXX_INCLUDE_TESTS:BOOL
|
||||
|
||||
**Default**: ``ON`` (or value of ``LLVM_INCLUDE_DIR``)
|
||||
|
||||
Build the libc++ tests.
|
||||
|
||||
.. option:: LIBCXX_INCLUDE_BENCHMARKS:BOOL
|
||||
|
||||
**Default**: ``ON``
|
||||
@ -307,6 +301,15 @@ libc++ Feature Options
|
||||
Build the libc++ benchmark tests and the Google Benchmark library needed
|
||||
to support them.
|
||||
|
||||
.. option:: LIBCXX_BENCHMARK_TEST_ARGS:STRING
|
||||
|
||||
**Default**: ``--benchmark_min_time=0.01``
|
||||
|
||||
A semicolon list of arguments to pass when running the libc++ benchmarks using the
|
||||
``check-cxx-benchmarks`` rule. By default we run the benchmarks for a very short amount of time,
|
||||
since the primary use of ``check-cxx-benchmarks`` is to get test and sanitizer coverage, not to
|
||||
get accurate measurements.
|
||||
|
||||
.. option:: LIBCXX_BENCHMARK_NATIVE_STDLIB:STRING
|
||||
|
||||
**Default**:: ``""``
|
||||
@ -314,7 +317,7 @@ libc++ Feature Options
|
||||
**Values**:: ``libc++``, ``libstdc++``
|
||||
|
||||
Build the libc++ benchmark tests and Google Benchmark library against the
|
||||
specified standard library on the platform. On linux this can be used to
|
||||
specified standard library on the platform. On Linux this can be used to
|
||||
compare libc++ to libstdc++ by building the benchmark tests against both
|
||||
standard libraries.
|
||||
|
||||
@ -323,6 +326,15 @@ libc++ Feature Options
|
||||
Use the specified GCC toolchain and standard library when building the native
|
||||
stdlib benchmark tests.
|
||||
|
||||
.. option:: LIBCXX_HIDE_FROM_ABI_PER_TU_BY_DEFAULT:BOOL
|
||||
|
||||
**Default**: ``OFF``
|
||||
|
||||
Pick the default for whether to constrain ABI-unstable symbols to
|
||||
each individual translation unit. This setting controls whether
|
||||
`_LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT` is defined by default --
|
||||
see the documentation of that macro for details.
|
||||
|
||||
|
||||
libc++ ABI Feature Options
|
||||
--------------------------
|
||||
@ -342,6 +354,42 @@ The following options allow building libc++ for a different ABI version.
|
||||
Build the "unstable" ABI version of libc++. Includes all ABI changing features
|
||||
on top of the current stable version.
|
||||
|
||||
.. option:: LIBCXX_ABI_NAMESPACE:STRING
|
||||
|
||||
**Default**: ``__n`` where ``n`` is the current ABI version.
|
||||
|
||||
This option defines the name of the inline ABI versioning namespace. It can be used for building
|
||||
custom versions of libc++ with unique symbol names in order to prevent conflicts or ODR issues
|
||||
with other libc++ versions.
|
||||
|
||||
.. warning::
|
||||
When providing a custom namespace, it's the users responsibility to ensure the name won't cause
|
||||
conflicts with other names defined by libc++, both now and in the future. In particular, inline
|
||||
namespaces of the form ``__[0-9]+`` are strictly reserved by libc++ and may not be used by users.
|
||||
Doing otherwise could cause conflicts and hinder libc++ ABI evolution.
|
||||
|
||||
.. option:: LIBCXX_ABI_DEFINES:STRING
|
||||
|
||||
**Default**: ``""``
|
||||
|
||||
A semicolon-separated list of ABI macros to persist in the site config header.
|
||||
See ``include/__config`` for the list of ABI macros.
|
||||
|
||||
|
||||
.. option:: LIBCXX_HAS_MERGED_TYPEINFO_NAMES_DEFAULT
|
||||
|
||||
**Default**: ``None``. When defined this option overrides the libraries default configuration
|
||||
for whether merged type info names are present.
|
||||
|
||||
|
||||
Build ``std::type_info`` with the assumption that type info names for a type have been fully
|
||||
merged are unique across the entire program. This may not be the case for libraries built with
|
||||
``-Bsymbolic`` or due to compiler or linker bugs (Ex. llvm.org/PR37398).
|
||||
|
||||
When the value is ``ON`` typeinfo comparisons compare only the pointer value, otherwise ``strcmp``
|
||||
is used as a fallback.
|
||||
|
||||
|
||||
.. _LLVM-specific variables:
|
||||
|
||||
LLVM-specific options
|
||||
@ -356,7 +404,7 @@ LLVM-specific options
|
||||
.. option:: LLVM_BUILD_32_BITS:BOOL
|
||||
|
||||
Build 32-bits executables and libraries on 64-bits systems. This option is
|
||||
available only on some 64-bits unix systems. Defaults to OFF.
|
||||
available only on some 64-bits Unix systems. Defaults to OFF.
|
||||
|
||||
.. option:: LLVM_LIT_ARGS:STRING
|
||||
|
||||
@ -479,7 +527,7 @@ These instructions should only be used when you can't install your ABI library.
|
||||
|
||||
Normally you must link libc++ against a ABI shared library that the
|
||||
linker can find. If you want to build and test libc++ against an ABI
|
||||
library not in the linker's path you needq to set
|
||||
library not in the linker's path you need to set
|
||||
``-DLIBCXX_CXX_ABI_LIBRARY_PATH=/path/to/abi/lib`` when configuring CMake.
|
||||
|
||||
An example build using libc++abi would look like:
|
||||
|
@ -1,9 +1,9 @@
|
||||
|
||||
if (LLVM_ENABLE_SPHINX)
|
||||
include(AddSphinxTarget)
|
||||
if (SPHINX_FOUND)
|
||||
include(AddSphinxTarget)
|
||||
if (${SPHINX_OUTPUT_HTML})
|
||||
add_sphinx_target(html libcxx)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
105
docs/DesignDocs/AvailabilityMarkup.rst
Normal file
105
docs/DesignDocs/AvailabilityMarkup.rst
Normal file
@ -0,0 +1,105 @@
|
||||
===================
|
||||
Availability Markup
|
||||
===================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Libc++ is used as a system library on macOS and iOS (amongst others). In order
|
||||
for users to be able to compile a binary that is intended to be deployed to an
|
||||
older version of the platform, clang provides the
|
||||
`availability attribute <https://clang.llvm.org/docs/AttributeReference.html#availability>`_
|
||||
that can be placed on declarations to describe the lifecycle of a symbol in the
|
||||
library.
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
When a new feature is introduced that requires dylib support, a macro should be
|
||||
created in include/__config to mark this feature as unavailable for all the
|
||||
systems. For example::
|
||||
|
||||
// Define availability macros.
|
||||
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE)
|
||||
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
|
||||
#else if defined(_LIBCPP_USE_AVAILABILITY_SOME_OTHER_VENDOR)
|
||||
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
|
||||
#else
|
||||
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
#endif
|
||||
|
||||
When the library is updated by the platform vendor, the markup can be updated.
|
||||
For example::
|
||||
|
||||
#define _LIBCPP_AVAILABILITY_SHARED_MUTEX \
|
||||
__attribute__((availability(macosx,strict,introduced=10.12))) \
|
||||
__attribute__((availability(ios,strict,introduced=10.0))) \
|
||||
__attribute__((availability(tvos,strict,introduced=10.0))) \
|
||||
__attribute__((availability(watchos,strict,introduced=3.0)))
|
||||
|
||||
In the source code, the macro can be added on a class if the full class requires
|
||||
type info from the library for example::
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
|
||||
: public std::logic_error {
|
||||
|
||||
or on a particular symbol:
|
||||
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
|
||||
|
||||
Furthermore, a lit feature should be added to match that availability macro,
|
||||
so that tests depending on that feature can be marked to XFAIL if the feature
|
||||
is not supported. This way, the test suite will work on platforms that have
|
||||
not shipped the feature yet. This can be done by adding the appropriate lit
|
||||
feature in test/config.py.
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
Some parameters can be passed to lit to run the test-suite and exercise the
|
||||
availability.
|
||||
|
||||
* The `platform` parameter controls the deployment target. For example lit can
|
||||
be invoked with `--param=platform=macosx10.8`. Default is the current host.
|
||||
* The `use_system_cxx_lib` parameter indicates to use another library than the
|
||||
just built one. Invoking lit with `--param=use_system_cxx_lib=true` will run
|
||||
the test-suite against the host system library. Alternatively a path to the
|
||||
directory containing a specific prebuilt libc++ can be used, for example:
|
||||
`--param=use_system_cxx_lib=/path/to/macOS/10.8/`.
|
||||
|
||||
Tests can be marked as XFAIL based on multiple features made available by lit:
|
||||
|
||||
|
||||
* if `--param=platform=macosx10.8` is passed, the following features will be available:
|
||||
|
||||
- availability
|
||||
- availability=x86_64
|
||||
- availability=macosx
|
||||
- availability=x86_64-macosx
|
||||
- availability=x86_64-apple-macosx10.8
|
||||
- availability=macosx10.8
|
||||
|
||||
This feature is used to XFAIL a test that *is* using a class or a method marked
|
||||
as unavailable *and* that is expected to *fail* if deployed on an older system.
|
||||
|
||||
* if `use_system_cxx_lib` and `--param=platform=macosx10.8` are passed to lit,
|
||||
the following features will also be available:
|
||||
|
||||
- with_system_cxx_lib
|
||||
- with_system_cxx_lib=x86_64
|
||||
- with_system_cxx_lib=macosx
|
||||
- with_system_cxx_lib=x86_64-macosx
|
||||
- with_system_cxx_lib=x86_64-apple-macosx10.8
|
||||
- with_system_cxx_lib=macosx10.8
|
||||
|
||||
This feature is used to XFAIL a test that is *not* using a class or a method
|
||||
marked as unavailable *but* that is expected to fail if deployed on an older
|
||||
system. For example, if the test exhibits a bug in the libc on a particular
|
||||
system version, or if the test uses a symbol that is not available on an
|
||||
older version of the dylib (but for which there is no availability markup,
|
||||
otherwise the XFAIL should use `availability` above).
|
@ -28,7 +28,7 @@ Design Goals
|
||||
It makes developers lives harder if they have to regenerate the libc++ headers
|
||||
every time they are modified.
|
||||
|
||||
* The solution should not make any of the libc++ headers dependant on
|
||||
* The solution should not make any of the libc++ headers dependent on
|
||||
files generated by the build system. The headers should be able to compile
|
||||
out of the box without any modification.
|
||||
|
||||
@ -46,7 +46,7 @@ we do NOTHING.
|
||||
|
||||
Otherwise we create a custom installation rule that modifies the installed __config
|
||||
header. The rule first generates a dummy "__config_site" header containing the required
|
||||
#defines. The contents of the dummy header are then prependend to the installed
|
||||
#defines. The contents of the dummy header are then prepended to the installed
|
||||
__config header. By manually prepending the files we avoid the cost of an
|
||||
extra #include and we allow the __config header to be ignorant of the extra
|
||||
configuration all together. An example "__config" header generated when
|
||||
@ -56,10 +56,9 @@ configuration all together. An example "__config" header generated when
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -77,10 +76,9 @@ configuration all together. An example "__config" header generated when
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- __config ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -28,41 +28,32 @@ they can be enabled using the ``_LIBCPP_DEBUG`` macro.
|
||||
which provides additional assertions about the validity of iterators used by
|
||||
the program.
|
||||
|
||||
Note that this option has no effect on libc++'s ABI
|
||||
|
||||
**_LIBCPP_DEBUG_USE_EXCEPTIONS**:
|
||||
When this macro is defined ``_LIBCPP_ASSERT`` failures throw
|
||||
``__libcpp_debug_exception`` instead of aborting. Additionally this macro
|
||||
disables exception specifications on functions containing ``_LIBCPP_ASSERT``
|
||||
checks. This allows assertion failures to correctly throw through these
|
||||
functions.
|
||||
Note that this option has no effect on libc++'s ABI; but it does have broad
|
||||
ODR implications. Users should compile their whole program at the same
|
||||
debugging level.
|
||||
|
||||
Handling Assertion Failures
|
||||
---------------------------
|
||||
|
||||
When a debug assertion fails the assertion handler is called via the
|
||||
``std::__libcpp_debug_function`` function pointer. It is possible to override
|
||||
this function pointer using a different handler function. Libc++ provides two
|
||||
different assertion handlers, the default handler
|
||||
``std::__libcpp_abort_debug_handler`` which aborts the program, and
|
||||
``std::__libcpp_throw_debug_handler`` which throws an instance of
|
||||
``std::__libcpp_debug_exception``. Libc++ can be changed to use the throwing
|
||||
assertion handler as follows:
|
||||
this function pointer using a different handler function. Libc++ provides a
|
||||
the default handler, ``std::__libcpp_abort_debug_handler``, which aborts the
|
||||
program. The handler may not return. Libc++ can be changed to use a custom
|
||||
assertion handler as follows.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#define _LIBCPP_DEBUG 1
|
||||
#include <string>
|
||||
int main() {
|
||||
std::__libcpp_debug_function = std::__libcpp_throw_debug_function;
|
||||
try {
|
||||
std::string::iterator bad_it;
|
||||
std::string str("hello world");
|
||||
str.insert(bad_it, '!'); // causes debug assertion
|
||||
} catch (std::__libcpp_debug_exception const&) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
void my_handler(std::__libcpp_debug_info const&);
|
||||
int main(int, char**) {
|
||||
std::__libcpp_debug_function = &my_handler;
|
||||
|
||||
std::string::iterator bad_it;
|
||||
std::string str("hello world");
|
||||
str.insert(bad_it, '!'); // causes debug assertion
|
||||
// control flow doesn't return
|
||||
}
|
||||
|
||||
Debug Mode Checks
|
||||
|
203
docs/DesignDocs/ExperimentalFeatures.rst
Normal file
203
docs/DesignDocs/ExperimentalFeatures.rst
Normal file
@ -0,0 +1,203 @@
|
||||
=====================
|
||||
Experimental Features
|
||||
=====================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. _experimental features:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Libc++ implements technical specifications (TSes) and ships them as experimental
|
||||
features that users are free to try out. The goal is to allow getting feedback
|
||||
on those experimental features.
|
||||
|
||||
However, libc++ does not provide the same guarantees about those features as
|
||||
it does for the rest of the library. In particular, no ABI or API stability
|
||||
is guaranteed, and experimental features are deprecated once the non-experimental
|
||||
equivalent has shipped in the library. This document outlines the details of
|
||||
that process.
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
The "end game" of a Technical Specification (TS) is to have the features in
|
||||
there added to a future version of the C++ Standard. When this happens, the TS
|
||||
can be retired. Sometimes, only part of at TS is added to the standard, and
|
||||
the rest of the features may be incorporated into the next version of the TS.
|
||||
|
||||
Adoption leaves library implementors with two implementations of a feature,
|
||||
one in namespace ``std``, and the other in namespace ``std::experimental``.
|
||||
The first one will continue to evolve (via issues and papers), while the other
|
||||
will not. Gradually they will diverge. It's not good for users to have two
|
||||
(subtly) different implementations of the same functionality in the same library.
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
When a feature is adopted into the main standard, we implement it in namespace
|
||||
``std``. Once that implementation is complete, we then create a deprecation
|
||||
warning for the corresponding experimental feature warning users to move off
|
||||
of it and to the now-standardized feature.
|
||||
|
||||
These deprecation warnings are guarded by a macro of the form
|
||||
``_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_<FEATURE>``, which
|
||||
can be defined by users to disable the deprecation warning. Whenever
|
||||
possible, deprecation warnings are put on a per-declaration basis
|
||||
using the ``[[deprecated]]`` attribute, which also allows disabling
|
||||
the warnings using ``-Wno-deprecated-declarations``.
|
||||
|
||||
After **2 releases** of LLVM, the experimental feature is removed completely
|
||||
(and the deprecation notice too). Using the experimental feature simply becomes
|
||||
an error. Furthermore, when an experimental header becomes empty due to the
|
||||
removal of the corresponding experimental feature, the header is removed.
|
||||
Keeping the header around creates incorrect assumptions from users and breaks
|
||||
``__has_include``.
|
||||
|
||||
|
||||
Status of TSes
|
||||
==============
|
||||
|
||||
Library Fundamentals TS `V1 <https://wg21.link/N4480>`__ and `V2 <https://wg21.link/N4617>`__
|
||||
---------------------------------------------------------------------------------------------
|
||||
|
||||
Most (but not all) of the features of the LFTS were accepted into C++17.
|
||||
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| Section | Feature | Shipped in ``std`` | To be removed from ``std::experimental`` | Notes |
|
||||
+=========+=======================================================+====================+==========================================+=========================+
|
||||
| 2.1 | ``uses_allocator construction`` | 5.0 | 7.0 | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.1.2 | ``erased_type`` | | n/a | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.2.1 | ``tuple_size_v`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.2.2 | ``apply`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.3.1 | All of the ``_v`` traits in ``<type_traits>`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.3.2 | ``invocation_type`` and ``raw_invocation_type`` | | n/a | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.3.3 | Logical operator traits | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.3.3 | Detection Idiom | 5.0 | | Only partially in C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.4.1 | All of the ``_v`` traits in ``<ratio>`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.5.1 | All of the ``_v`` traits in ``<chrono>`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.6.1 | All of the ``_v`` traits in ``<system_error>`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 3.7 | ``propagate_const`` | | n/a | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 4.2 | Enhancements to ``function`` | Not yet | | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 4.3 | searchers | 7.0 | 9.0 | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 5 | optional | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 6 | ``any`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 7 | ``string_view`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.2.1 | ``shared_ptr`` enhancements | Not yet | Never added | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.2.2 | ``weak_ptr`` enhancements | Not yet | Never added | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.5 | ``memory_resource`` | Not yet | | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.6 | ``polymorphic_allocator`` | Not yet | | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.7 | ``resource_adaptor`` | | n/a | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.8 | Access to program-wide ``memory_resource`` objects | Not yet | | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.9 | Pool resource classes | Not yet | | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.10 | ``monotonic_buffer_resource`` | Not yet | | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.11 | Alias templates using polymorphic memory resources | Not yet | | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 8.12 | Non-owning pointers | | n/a | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 11.2 | ``promise`` | | n/a | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 11.3 | ``packaged_task`` | | n/a | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 12.2 | ``search`` | 7.0 | 9.0 | |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 12.3 | ``sample`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 12.4 | ``shuffle`` | | | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 13.1 | ``gcd`` and ``lcm`` | 5.0 | 7.0 | Removed |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 13.2 | Random number generation | | | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
| 14 | Reflection Library | | | Not part of C++17 |
|
||||
+---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
|
||||
|
||||
`FileSystem TS <https://wg21.link/N4100>`__
|
||||
-------------------------------------------
|
||||
The FileSystem TS was accepted (in totality) for C++17.
|
||||
The FileSystem TS implementation was shipped in namespace ``std`` in LLVM 7.0, and will be removed in LLVM 11.0 (due to the lack of deprecation warnings before LLVM 9.0).
|
||||
|
||||
Parallelism TS `V1 <https://wg21.link/N4507>`__ and `V2 <https://wg21.link/N4706>`__
|
||||
------------------------------------------------------------------------------------
|
||||
Some (most) of the Parallelism TS was accepted for C++17.
|
||||
We have not yet shipped an implementation of the Parallelism TS.
|
||||
|
||||
`Coroutines TS <https://wg21.link/N4680>`__
|
||||
-------------------------------------------
|
||||
The Coroutines TS is not yet part of a shipping standard.
|
||||
We are shipping (as of v5.0) an implementation of the Coroutines TS in namespace ``std::experimental``.
|
||||
|
||||
`Networking TS <https://wg21.link/N4656>`__
|
||||
-------------------------------------------
|
||||
The Networking TS is not yet part of a shipping standard.
|
||||
We have not yet shipped an implementation of the Networking TS.
|
||||
|
||||
`Ranges TS <https://wg21.link/N4685>`__
|
||||
---------------------------------------
|
||||
The Ranges TS is not yet part of a shipping standard.
|
||||
We have not yet shipped an implementation of the Ranges TS.
|
||||
|
||||
`Concepts TS <https://wg21.link/N4641>`__
|
||||
-----------------------------------------
|
||||
The Concepts TS is not yet part of a shipping standard, but it has been adopted into the C++20 working draft.
|
||||
We have not yet shipped an implementation of the Concepts TS.
|
||||
|
||||
`Concurrency TS <https://wg21.link/P0159>`__
|
||||
--------------------------------------------
|
||||
The Concurrency TS was adopted in Kona (2015).
|
||||
None of the Concurrency TS was accepted for C++17.
|
||||
We have not yet shipped an implementation of the Concurrency TS.
|
||||
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | Section | Feature | Shipped in ``std`` | To be removed from ``std::experimental`` | Notes |
|
||||
.. +=========+=======================================================+====================+==========================================+=========================+
|
||||
.. | 2.3 | class template ``future`` | | | |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.4 | class template ``shared_future`` | | | |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.5 | class template ``promise`` | | | Only using ``future`` |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.6 | class template ``packaged_task`` | | | Only using ``future`` |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.7 | function template ``when_all`` | | | Not part of C++17 |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.8 | class template ``when_any_result`` | | | Not part of C++17 |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.9 | function template ``when_any`` | | | Not part of C++17 |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.10 | function template ``make_ready_future`` | | | Not part of C++17 |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 2.11 | function template ``make_exeptional_future`` | | | Not part of C++17 |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 3 | ``latches`` and ``barriers`` | | | Not part of C++17 |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
||||
.. | 4 | Atomic Smart Pointers | | | Adopted for C++20 |
|
||||
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+
|
118
docs/DesignDocs/ExtendedCXX03Support.rst
Normal file
118
docs/DesignDocs/ExtendedCXX03Support.rst
Normal file
@ -0,0 +1,118 @@
|
||||
=======================
|
||||
Extended C++03 Support
|
||||
=======================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
libc++ is an implementation of the C++ standard library targeting C++11 or later.
|
||||
|
||||
In C++03, the library implements the C++11 standard using C++11 language extensions provided
|
||||
by Clang.
|
||||
|
||||
This document tracks the C++11 extensions libc++ requires, the C++11 extensions it provides,
|
||||
and how to write minimal C++11 inside libc++.
|
||||
|
||||
Required C++11 Compiler Extensions
|
||||
==================================
|
||||
|
||||
Clang provides a large subset of C++11 in C++03 as an extension. The features
|
||||
libc++ expects Clang to provide are:
|
||||
|
||||
* Variadic templates.
|
||||
* RValue references and perfect forwarding.
|
||||
* Alias templates
|
||||
* defaulted and deleted Functions.
|
||||
* reference qualified Functions
|
||||
|
||||
There are also features that Clang *does not* provide as an extension in C++03
|
||||
mode. These include:
|
||||
|
||||
* ``constexpr`` and ``noexcept``
|
||||
* ``auto``
|
||||
* Trailing return types.
|
||||
* ``>>`` without a space.
|
||||
|
||||
|
||||
Provided C++11 Library Extensions
|
||||
=================================
|
||||
|
||||
.. warning::
|
||||
The C++11 extensions libc++ provides in C++03 are currently undergoing change. Existing extensions
|
||||
may be removed in the future. New users are strongly discouraged depending on these extension
|
||||
in new code.
|
||||
|
||||
This section will be updated once the libc++ developer community has further discussed the
|
||||
future of C++03 with libc++.
|
||||
|
||||
|
||||
Using Minimal C++11 in libc++
|
||||
=============================
|
||||
|
||||
This section is for developers submitting patches to libc++. It describes idioms that should be
|
||||
used in libc++ code, even in C++03, and the reasons behind them.
|
||||
|
||||
|
||||
Use Alias Templates over Class Templates
|
||||
----------------------------------------
|
||||
|
||||
Alias templates should be used instead of class templates in metaprogramming. Unlike class templates,
|
||||
Alias templates do not produce a new instantiation every time they are used. This significantly
|
||||
decreases the amount of memory used by the compiler.
|
||||
|
||||
For example, libc++ should not use ``add_const`` internally. Instead it should use an alias template
|
||||
like
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
template <class _Tp>
|
||||
using _AddConst = const _Tp;
|
||||
|
||||
Use Default Template Parameters for SFINAE
|
||||
------------------------------------------
|
||||
|
||||
There are three places in a function declaration that SFINAE may occur: In the template parameter list,
|
||||
in the function parameter list, and in the return type. For example:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
template <class _Tp, class _ = enable_if_t</*...*/ >
|
||||
void foo(_Tp); // #1
|
||||
|
||||
template <class _Tp>
|
||||
void bar(_Tp, enable_if_t</*...*/>* = nullptr); // # 2
|
||||
|
||||
template <class _Tp>
|
||||
enable_if_t</*...*/> baz(_Tp); // # 3
|
||||
|
||||
Using default template parameters for SFINAE (#1) should always be prefered.
|
||||
|
||||
Option #2 has two problems. First, users can observe and accidentally pass values to the SFINAE
|
||||
function argument. Second, the default arguement creates a live variable, which causes debug
|
||||
information to be emitted containing the text of the SFINAE.
|
||||
|
||||
Option #3 can also cause more debug information to be emitted than is needed, because the function
|
||||
return type will appear in the debug information.
|
||||
|
||||
Use ``unique_ptr`` when allocating memory
|
||||
------------------------------------------
|
||||
|
||||
The standard library often needs to allocate memory and then construct a user type in it.
|
||||
If the users constructor throws, the library needs to deallocate that memory. The idiomatic way to
|
||||
achieve this is with ``unique_ptr``.
|
||||
|
||||
``__builtin_new_allocator`` is an example of this idiom. Example usage would look like:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
template <class T>
|
||||
T* __create() {
|
||||
using _UniquePtr = unique_ptr<void*, __default_new_allocator::__default_new_deleter>;
|
||||
_UniquePtr __p = __default_new_allocator::__allocate_bytes(sizeof(T), alignof(T));
|
||||
T* __res = ::new(__p.get()) T();
|
||||
(void)__p.release();
|
||||
return __res;
|
||||
}
|
45
docs/DesignDocs/FeatureTestMacros.rst
Normal file
45
docs/DesignDocs/FeatureTestMacros.rst
Normal file
@ -0,0 +1,45 @@
|
||||
===================
|
||||
Feature Test Macros
|
||||
===================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Libc++ implements the C++ feature test macros as specified in the C++2a standard,
|
||||
and before that in non-normative guiding documents
|
||||
(`See cppreference <https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros>`_)
|
||||
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
Feature test macros are tricky to track, implement, test, and document correctly.
|
||||
They must be available from a list of headers, they may have different values in
|
||||
different dialects, and they may or may not be implemented by libc++. In order to
|
||||
track all of these conditions correctly and easily, we want a Single Source of
|
||||
Truth (SSoT) that defines each feature test macro, its values, the headers it
|
||||
lives in, and whether or not is is implemented by libc++. From this SSoA we
|
||||
have enough information to automatically generate the `<version>` header,
|
||||
the tests, and the documentation.
|
||||
|
||||
Therefore we maintain a SSoA in `libcxx/utils/generate_feature_test_macro_components.py`
|
||||
which doubles as a script to generate the following components:
|
||||
|
||||
* The `<version>` header.
|
||||
* The version tests under `support.limits.general`.
|
||||
* Documentation of libc++'s implementation of each macro.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The `generate_feature_test_macro_components.py` script is used to track and
|
||||
update feature test macros in libc++.
|
||||
|
||||
Whenever a feature test macro is added or changed, the table should be updated
|
||||
and the script should be re-ran. The script will clobber the existing test files
|
||||
and the documentation and it will generate a new `<version>` header as a
|
||||
temporary file. The generated `<version>` header should be merged with the
|
||||
existing one.
|
495
docs/DesignDocs/FileTimeType.rst
Normal file
495
docs/DesignDocs/FileTimeType.rst
Normal file
@ -0,0 +1,495 @@
|
||||
==============
|
||||
File Time Type
|
||||
==============
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. _file-time-type-motivation:
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
The filesystem library provides interfaces for getting and setting the last
|
||||
write time of a file or directory. The interfaces use the ``file_time_type``
|
||||
type, which is a specialization of ``chrono::time_point`` for the
|
||||
"filesystem clock". According to [fs.filesystem.syn]
|
||||
|
||||
trivial-clock is an implementation-defined type that satisfies the
|
||||
Cpp17TrivialClock requirements ([time.clock.req]) and that is capable of
|
||||
representing and measuring file time values. Implementations should ensure
|
||||
that the resolution and range of file_time_type reflect the operating
|
||||
system dependent resolution and range of file time values.
|
||||
|
||||
|
||||
On POSIX systems, file times are represented using the ``timespec`` struct,
|
||||
which is defined as follows:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
struct timespec {
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
|
||||
To represent the range and resolution of ``timespec``, we need to (A) have
|
||||
nanosecond resolution, and (B) use more than 64 bits (assuming a 64 bit ``time_t``).
|
||||
|
||||
As the standard requires us to use the ``chrono`` interface, we have to define
|
||||
our own filesystem clock which specifies the period and representation of
|
||||
the time points and duration it provides. It will look like this:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
struct _FilesystemClock {
|
||||
using period = nano;
|
||||
using rep = TBD; // What is this?
|
||||
|
||||
using duration = chrono::duration<rep, period>;
|
||||
using time_point = chrono::time_point<_FilesystemClock>;
|
||||
|
||||
// ... //
|
||||
};
|
||||
|
||||
using file_time_type = _FilesystemClock::time_point;
|
||||
|
||||
|
||||
To get nanosecond resolution, we simply define ``period`` to be ``std::nano``.
|
||||
But what type can we use as the arithmetic representation that is capable
|
||||
of representing the range of the ``timespec`` struct?
|
||||
|
||||
Problems To Consider
|
||||
====================
|
||||
|
||||
Before considering solutions, let's consider the problems they should solve,
|
||||
and how important solving those problems are:
|
||||
|
||||
|
||||
Having a Smaller Range than ``timespec``
|
||||
----------------------------------------
|
||||
|
||||
One solution to the range problem is to simply reduce the resolution of
|
||||
``file_time_type`` to be less than that of nanoseconds. This is what libc++'s
|
||||
initial implementation of ``file_time_type`` did; it's also what
|
||||
``std::system_clock`` does. As a result, it can represent time points about
|
||||
292 thousand years on either side of the epoch, as opposed to only 292 years
|
||||
at nanosecond resolution.
|
||||
|
||||
``timespec`` can represent time points +/- 292 billion years from the epoch
|
||||
(just in case you needed a time point 200 billion years before the big bang,
|
||||
and with nanosecond resolution).
|
||||
|
||||
To get the same range, we would need to drop our resolution to that of seconds
|
||||
to come close to having the same range.
|
||||
|
||||
This begs the question, is the range problem "really a problem"? Sane usages
|
||||
of file time stamps shouldn't exceed +/- 300 years, so should we care to support it?
|
||||
|
||||
I believe the answer is yes. We're not designing the filesystem time API, we're
|
||||
providing glorified C++ wrappers for it. If the underlying API supports
|
||||
a value, then we should too. Our wrappers should not place artificial restrictions
|
||||
on users that are not present in the underlying filesystem.
|
||||
|
||||
Having a smaller range that the underlying filesystem forces the
|
||||
implementation to report ``value_too_large`` errors when it encounters a time
|
||||
point that it can't represent. This can cause the call to ``last_write_time``
|
||||
to throw in cases where the user was confident the call should succeed. (See below)
|
||||
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <filesystem>
|
||||
using namespace std::filesystem;
|
||||
|
||||
// Set the times using the system interface.
|
||||
void set_file_times(const char* path, struct timespec ts) {
|
||||
timespec both_times[2];
|
||||
both_times[0] = ts;
|
||||
both_times[1] = ts;
|
||||
int result = ::utimensat(AT_FDCWD, path, both_times, 0);
|
||||
assert(result != -1);
|
||||
}
|
||||
|
||||
// Called elsewhere to set the file time to something insane, and way
|
||||
// out of the 300 year range we might expect.
|
||||
void some_bad_persons_code() {
|
||||
struct timespec new_times;
|
||||
new_times.tv_sec = numeric_limits<time_t>::max();
|
||||
new_times.tv_nsec = 0;
|
||||
set_file_times("/tmp/foo", new_times); // OK, supported by most FSes
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
path p = "/tmp/foo";
|
||||
file_status st = status(p);
|
||||
if (!exists(st) || !is_regular_file(st))
|
||||
return 1;
|
||||
if ((st.permissions() & perms::others_read) == perms::none)
|
||||
return 1;
|
||||
// It seems reasonable to assume this call should succeed.
|
||||
file_time_type tp = last_write_time(p); // BAD! Throws value_too_large.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Having a Smaller Resolution than ``timespec``
|
||||
---------------------------------------------
|
||||
|
||||
As mentioned in the previous section, one way to solve the range problem
|
||||
is by reducing the resolution. But matching the range of ``timespec`` using a
|
||||
64 bit representation requires limiting the resolution to seconds.
|
||||
|
||||
So we might ask: Do users "need" nanosecond precision? Is seconds not good enough?
|
||||
I limit my consideration of the point to this: Why was it not good enough for
|
||||
the underlying system interfaces? If it wasn't good enough for them, then it
|
||||
isn't good enough for us. Our job is to match the filesystems range and
|
||||
representation, not design it.
|
||||
|
||||
|
||||
Having a Larger Range than ``timespec``
|
||||
----------------------------------------
|
||||
|
||||
We should also consider the opposite problem of having a ``file_time_type``
|
||||
that is able to represent a larger range than ``timespec``. At least in
|
||||
this case ``last_write_time`` can be used to get and set all possible values
|
||||
supported by the underlying filesystem; meaning ``last_write_time(p)`` will
|
||||
never throw a overflow error when retrieving a value.
|
||||
|
||||
However, this introduces a new problem, where users are allowed to attempt to
|
||||
create a time point beyond what the filesystem can represent. Two particular
|
||||
values which cause this are ``file_time_type::min()`` and
|
||||
``file_time_type::max()``. As a result, the following code would throw:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void test() {
|
||||
last_write_time("/tmp/foo", file_time_type::max()); // Throws
|
||||
last_write_time("/tmp/foo", file_time_type::min()); // Throws.
|
||||
}
|
||||
|
||||
Apart from cases explicitly using ``min`` and ``max``, I don't see users taking
|
||||
a valid time point, adding a couple hundred billions of years in error,
|
||||
and then trying to update a file's write time to that value very often.
|
||||
|
||||
Compared to having a smaller range, this problem seems preferable. At least
|
||||
now we can represent any time point the filesystem can, so users won't be forced
|
||||
to revert back to system interfaces to avoid limitations in the C++ STL.
|
||||
|
||||
I posit that we should only consider this concern *after* we have something
|
||||
with at least the same range and resolution of the underlying filesystem. The
|
||||
latter two problems are much more important to solve.
|
||||
|
||||
Potential Solutions And Their Complications
|
||||
===========================================
|
||||
|
||||
Source Code Portability Across Implementations
|
||||
-----------------------------------------------
|
||||
|
||||
As we've discussed, ``file_time_type`` needs a representation that uses more
|
||||
than 64 bits. The possible solutions include using ``__int128_t``, emulating a
|
||||
128 bit integer using a class, or potentially defining a ``timespec`` like
|
||||
arithmetic type. All three will allow us to, at minimum, match the range
|
||||
and resolution, and the last one might even allow us to match them exactly.
|
||||
|
||||
But when considering these potential solutions we need to consider more than
|
||||
just the values they can represent. We need to consider the effects they will
|
||||
have on users and their code. For example, each of them breaks the following
|
||||
code in some way:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
// Bug caused by an unexpected 'rep' type returned by count.
|
||||
void print_time(path p) {
|
||||
// __int128_t doesn't have streaming operators, and neither would our
|
||||
// custom arithmetic types.
|
||||
cout << last_write_time(p).time_since_epoch().count() << endl;
|
||||
}
|
||||
|
||||
// Overflow during creation bug.
|
||||
file_time_type timespec_to_file_time_type(struct timespec ts) {
|
||||
// woops! chrono::seconds and chrono::nanoseconds use a 64 bit representation
|
||||
// this may overflow before it's converted to a file_time_type.
|
||||
auto dur = seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec);
|
||||
return file_time_type(dur);
|
||||
}
|
||||
|
||||
file_time_type correct_timespec_to_file_time_type(struct timespec ts) {
|
||||
// This is the correct version of the above example, where we
|
||||
// avoid using the chrono typedefs as they're not sufficient.
|
||||
// Can we expect users to avoid this bug?
|
||||
using fs_seconds = chrono::duration<file_time_type::rep>;
|
||||
using fs_nanoseconds = chrono::duration<file_time_type::rep, nano>;
|
||||
auto dur = fs_seconds(ts.tv_sec) + fs_nanoseconds(tv.tv_nsec);
|
||||
return file_time_type(dur);
|
||||
}
|
||||
|
||||
// Implicit truncation during conversion bug.
|
||||
intmax_t get_time_in_seconds(path p) {
|
||||
using fs_seconds = duration<file_time_type::rep, ratio<1, 1> >;
|
||||
auto tp = last_write_time(p);
|
||||
|
||||
// This works with truncation for __int128_t, but what does it do for
|
||||
// our custom arithmetic types.
|
||||
return duration_cast<fs_seconds>().count();
|
||||
}
|
||||
|
||||
|
||||
Each of the above examples would require a user to adjust their filesystem code
|
||||
to the particular eccentricities of the representation, hopefully only in such
|
||||
a way that the code is still portable across implementations.
|
||||
|
||||
At least some of the above issues are unavoidable, no matter what
|
||||
representation we choose. But some representations may be quirkier than others,
|
||||
and, as I'll argue later, using an actual arithmetic type (``__int128_t``)
|
||||
provides the least aberrant behavior.
|
||||
|
||||
|
||||
Chrono and ``timespec`` Emulation.
|
||||
----------------------------------
|
||||
|
||||
One of the options we've considered is using something akin to ``timespec``
|
||||
to represent the ``file_time_type``. It only seems natural seeing as that's
|
||||
what the underlying system uses, and because it might allow us to match
|
||||
the range and resolution exactly. But would it work with chrono? And could
|
||||
it still act at all like a ``timespec`` struct?
|
||||
|
||||
For ease of consideration, let's consider what the implementation might
|
||||
look like.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
struct fs_timespec_rep {
|
||||
fs_timespec_rep(long long v)
|
||||
: tv_sec(v / nano::den), tv_nsec(v % nano::den)
|
||||
{ }
|
||||
private:
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
bool operator==(fs_timespec_rep, fs_timespec_rep);
|
||||
fs_int128_rep operator+(fs_timespec_rep, fs_timespec_rep);
|
||||
// ... arithmetic operators ... //
|
||||
|
||||
The first thing to notice is that we can't construct ``fs_timespec_rep`` like
|
||||
a ``timespec`` by passing ``{secs, nsecs}``. Instead we're limited to
|
||||
constructing it from a single 64 bit integer.
|
||||
|
||||
We also can't allow the user to inspect the ``tv_sec`` or ``tv_nsec`` values
|
||||
directly. A ``chrono::duration`` represents its value as a tick period and a
|
||||
number of ticks stored using ``rep``. The representation is unaware of the
|
||||
tick period it is being used to represent, but ``timespec`` is setup to assume
|
||||
a nanosecond tick period; which is the only case where the names ``tv_sec``
|
||||
and ``tv_nsec`` match the values they store.
|
||||
|
||||
When we convert a nanosecond duration to seconds, ``fs_timespec_rep`` will
|
||||
use ``tv_sec`` to represent the number of giga seconds, and ``tv_nsec`` the
|
||||
remaining seconds. Let's consider how this might cause a bug were users allowed
|
||||
to manipulate the fields directly.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
template <class Period>
|
||||
timespec convert_to_timespec(duration<fs_time_rep, Period> dur) {
|
||||
fs_timespec_rep rep = dur.count();
|
||||
return {rep.tv_sec, rep.tv_nsec}; // Oops! Period may not be nanoseconds.
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
Duration convert_to_duration(timespec ts) {
|
||||
Duration dur({ts.tv_sec, ts.tv_nsec}); // Oops! Period may not be nanoseconds.
|
||||
return file_time_type(dur);
|
||||
file_time_type tp = last_write_time(p);
|
||||
auto dur =
|
||||
}
|
||||
|
||||
time_t extract_seconds(file_time_type tp) {
|
||||
// Converting to seconds is a silly bug, but I could see it happening.
|
||||
using SecsT = chrono::duration<file_time_type::rep, ratio<1, 1>>;
|
||||
auto secs = duration_cast<Secs>(tp.time_since_epoch());
|
||||
// tv_sec is now representing gigaseconds.
|
||||
return secs.count().tv_sec; // Oops!
|
||||
}
|
||||
|
||||
Despite ``fs_timespec_rep`` not being usable in any manner resembling
|
||||
``timespec``, it still might buy us our goal of matching its range exactly,
|
||||
right?
|
||||
|
||||
Sort of. Chrono provides a specialization point which specifies the minimum
|
||||
and maximum values for a custom representation. It looks like this:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
template <>
|
||||
struct duration_values<fs_timespec_rep> {
|
||||
static fs_timespec_rep zero();
|
||||
static fs_timespec_rep min();
|
||||
static fs_timespec_rep max() { // assume friendship.
|
||||
fs_timespec_rep val;
|
||||
val.tv_sec = numeric_limits<time_t>::max();
|
||||
val.tv_nsec = nano::den - 1;
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
Notice that ``duration_values`` doesn't tell the representation what tick
|
||||
period it's actually representing. This would indeed correctly limit the range
|
||||
of ``duration<fs_timespec_rep, nano>`` to exactly that of ``timespec``. But
|
||||
nanoseconds isn't the only tick period it will be used to represent. For
|
||||
example:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void test() {
|
||||
using rep = file_time_type::rep;
|
||||
using fs_nsec = duration<rep, nano>;
|
||||
using fs_sec = duration<rep>;
|
||||
fs_nsec nsecs(fs_seconds::max()); // Truncates
|
||||
}
|
||||
|
||||
Though the above example may appear silly, I think it follows from the incorrect
|
||||
notion that using a ``timespec`` rep in chrono actually makes it act as if it
|
||||
were an actual ``timespec``.
|
||||
|
||||
Interactions with 32 bit ``time_t``
|
||||
-----------------------------------
|
||||
|
||||
Up until now we've only be considering cases where ``time_t`` is 64 bits, but what
|
||||
about 32 bit systems/builds where ``time_t`` is 32 bits? (this is the common case
|
||||
for 32 bit builds).
|
||||
|
||||
When ``time_t`` is 32 bits, we can implement ``file_time_type`` simply using 64-bit
|
||||
``long long``. There is no need to get either ``__int128_t`` or ``timespec`` emulation
|
||||
involved. And nor should we, as it would suffer from the numerous complications
|
||||
described by this paper.
|
||||
|
||||
Obviously our implementation for 32-bit builds should act as similarly to the
|
||||
64-bit build as possible. Code which compiles in one, should compile in the other.
|
||||
This consideration is important when choosing between ``__int128_t`` and
|
||||
emulating ``timespec``. The solution which provides the most uniformity with
|
||||
the least eccentricity is the preferable one.
|
||||
|
||||
Summary
|
||||
=======
|
||||
|
||||
The ``file_time_type`` time point is used to represent the write times for files.
|
||||
Its job is to act as part of a C++ wrapper for less ideal system interfaces. The
|
||||
underlying filesystem uses the ``timespec`` struct for the same purpose.
|
||||
|
||||
However, the initial implementation of ``file_time_type`` could not represent
|
||||
either the range or resolution of ``timespec``, making it unsuitable. Fixing
|
||||
this requires an implementation which uses more than 64 bits to store the
|
||||
time point.
|
||||
|
||||
We primarily considered two solutions: Using ``__int128_t`` and using a
|
||||
arithmetic emulation of ``timespec``. Each has its pros and cons, and both
|
||||
come with more than one complication.
|
||||
|
||||
The Potential Solutions
|
||||
-----------------------
|
||||
|
||||
``long long`` - The Status Quo
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Pros:
|
||||
|
||||
* As a type ``long long`` plays the nicest with others:
|
||||
|
||||
* It works with streaming operators and other library entities which support
|
||||
builtin integer types, but don't support ``__int128_t``.
|
||||
* Its the representation used by chrono's ``nanosecond`` and ``second`` typedefs.
|
||||
|
||||
Cons:
|
||||
|
||||
* It cannot provide the same resolution as ``timespec`` unless we limit it
|
||||
to a range of +/- 300 years from the epoch.
|
||||
* It cannot provide the same range as ``timespec`` unless we limit its resolution
|
||||
to seconds.
|
||||
* ``last_write_time`` has to report an error when the time reported by the filesystem
|
||||
is unrepresentable.
|
||||
|
||||
__int128_t
|
||||
~~~~~~~~~~~
|
||||
|
||||
Pros:
|
||||
|
||||
* It is an integer type.
|
||||
* It makes the implementation simple and efficient.
|
||||
* Acts exactly like other arithmetic types.
|
||||
* Can be implicitly converted to a builtin integer type by the user.
|
||||
|
||||
* This is important for doing things like:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void c_interface_using_time_t(const char* p, time_t);
|
||||
|
||||
void foo(path p) {
|
||||
file_time_type tp = last_write_time(p);
|
||||
time_t secs = duration_cast<seconds>(tp.time_since_epoch()).count();
|
||||
c_interface_using_time_t(p.c_str(), secs);
|
||||
}
|
||||
|
||||
Cons:
|
||||
|
||||
* It isn't always available (but on 64 bit machines, it normally is).
|
||||
* It causes ``file_time_type`` to have a larger range than ``timespec``.
|
||||
* It doesn't always act the same as other builtin integer types. For example
|
||||
with ``cout`` or ``to_string``.
|
||||
* Allows implicit truncation to 64 bit integers.
|
||||
* It can be implicitly converted to a builtin integer type by the user,
|
||||
truncating its value.
|
||||
|
||||
Arithmetic ``timespec`` Emulation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Pros:
|
||||
|
||||
* It has the exact same range and resolution of ``timespec`` when representing
|
||||
a nanosecond tick period.
|
||||
* It's always available, unlike ``__int128_t``.
|
||||
|
||||
Cons:
|
||||
|
||||
* It has a larger range when representing any period longer than a nanosecond.
|
||||
* Doesn't actually allow users to use it like a ``timespec``.
|
||||
* The required representation of using ``tv_sec`` to store the giga tick count
|
||||
and ``tv_nsec`` to store the remainder adds nothing over a 128 bit integer,
|
||||
but complicates a lot.
|
||||
* It isn't a builtin integer type, and can't be used anything like one.
|
||||
* Chrono can be made to work with it, but not nicely.
|
||||
* Emulating arithmetic classes come with their own host of problems regarding
|
||||
overload resolution (Each operator needs three SFINAE constrained versions of
|
||||
it in order to act like builtin integer types).
|
||||
* It offers little over simply using ``__int128_t``.
|
||||
* It acts the most differently than implementations using an actual integer type,
|
||||
which has a high chance of breaking source compatibility.
|
||||
|
||||
|
||||
Selected Solution - Using ``__int128_t``
|
||||
=========================================
|
||||
|
||||
The solution I selected for libc++ is using ``__int128_t`` when available,
|
||||
and otherwise falling back to using ``long long`` with nanosecond precision.
|
||||
|
||||
When ``__int128_t`` is available, or when ``time_t`` is 32-bits, the implementation
|
||||
provides same resolution and a greater range than ``timespec``. Otherwise
|
||||
it still provides the same resolution, but is limited to a range of +/- 300
|
||||
years. This final case should be rather rare, as ``__int128_t``
|
||||
is normally available in 64-bit builds, and ``time_t`` is normally 32-bits
|
||||
during 32-bit builds.
|
||||
|
||||
Although falling back to ``long long`` and nanosecond precision is less than
|
||||
ideal, it also happens to be the implementation provided by both libstdc++
|
||||
and MSVC. (So that makes it better, right?)
|
||||
|
||||
Although the ``timespec`` emulation solution is feasible and would largely
|
||||
do what we want, it comes with too many complications, potential problems
|
||||
and discrepancies when compared to "normal" chrono time points and durations.
|
||||
|
||||
An emulation of a builtin arithmetic type using a class is never going to act
|
||||
exactly the same, and the difference will be felt by users. It's not reasonable
|
||||
to expect them to tolerate and work around these differences. And once
|
||||
we commit to an ABI it will be too late to change. Committing to this seems
|
||||
risky.
|
||||
|
||||
Therefore, ``__int128_t`` seems like the better solution.
|
@ -66,6 +66,10 @@ Threading Configuration Macros
|
||||
This macro is defined when libc++ should use POSIX threads to implement the
|
||||
internal threading API.
|
||||
|
||||
**_LIBCPP_HAS_THREAD_API_WIN32**
|
||||
This macro is defined when libc++ should use Win32 threads to implement the
|
||||
internal threading API.
|
||||
|
||||
**_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL**
|
||||
This macro is defined when libc++ expects the definitions of the internal
|
||||
threading API to be provided by an external library. When defined
|
||||
|
@ -22,11 +22,11 @@ Visibility Macros
|
||||
Mark a symbol as being exported by the libc++ library. This attribute must
|
||||
be applied to the declaration of all functions exported by the libc++ dylib.
|
||||
|
||||
**_LIBCPP_EXTERN_VIS**
|
||||
**_LIBCPP_EXPORTED_FROM_ABI**
|
||||
Mark a symbol as being exported by the libc++ library. This attribute may
|
||||
only be applied to objects defined in the libc++ library. On Windows this
|
||||
macro applies `dllimport`/`dllexport` to the symbol. On all other platforms
|
||||
this macro has no effect.
|
||||
only be applied to objects defined in the libc++ runtime library. On Windows,
|
||||
this macro applies `dllimport`/`dllexport` to the symbol, and on other
|
||||
platforms it gives the symbol default visibility.
|
||||
|
||||
**_LIBCPP_OVERRIDABLE_FUNC_VIS**
|
||||
Mark a symbol as being exported by the libc++ library, but allow it to be
|
||||
@ -40,11 +40,59 @@ Visibility Macros
|
||||
this macro therefore expands to `__declspec(dllexport)` when building the
|
||||
library and has an empty definition otherwise.
|
||||
|
||||
**_LIBCPP_INLINE_VISIBILITY**
|
||||
Mark a function as hidden and force inlining whenever possible.
|
||||
**_LIBCPP_HIDE_FROM_ABI**
|
||||
Mark a function as not being part of the ABI of any final linked image that
|
||||
uses it.
|
||||
|
||||
**_LIBCPP_ALWAYS_INLINE**
|
||||
A synonym for `_LIBCPP_INLINE_VISIBILITY`
|
||||
**_LIBCPP_HIDE_FROM_ABI_AFTER_V1**
|
||||
Mark a function as being hidden from the ABI (per `_LIBCPP_HIDE_FROM_ABI`)
|
||||
when libc++ is built with an ABI version after ABI v1. This macro is used to
|
||||
maintain ABI compatibility for symbols that have been historically exported
|
||||
by libc++ in v1 of the ABI, but that we don't want to export in the future.
|
||||
|
||||
This macro works as follows. When we build libc++, we either hide the symbol
|
||||
from the ABI (if the symbol is not part of the ABI in the version we're
|
||||
building), or we leave it included. From user code (i.e. when we're not
|
||||
building libc++), the macro always marks symbols as internal so that programs
|
||||
built using new libc++ headers stop relying on symbols that are removed from
|
||||
the ABI in a future version. Each time we release a new stable version of the
|
||||
ABI, we should create a new _LIBCPP_HIDE_FROM_ABI_AFTER_XXX macro, and we can
|
||||
use it to start removing symbols from the ABI after that stable version.
|
||||
|
||||
**_LIBCPP_HIDE_FROM_ABI_PER_TU**
|
||||
This macro controls whether symbols hidden from the ABI with `_LIBCPP_HIDE_FROM_ABI`
|
||||
are local to each translation unit in addition to being local to each final
|
||||
linked image. This macro is defined to either 0 or 1. When it is defined to
|
||||
1, translation units compiled with different versions of libc++ can be linked
|
||||
together, since all non ABI-facing functions are local to each translation unit.
|
||||
This allows static archives built with different versions of libc++ to be linked
|
||||
together. This also means that functions marked with `_LIBCPP_HIDE_FROM_ABI`
|
||||
are not guaranteed to have the same address across translation unit boundaries.
|
||||
|
||||
When the macro is defined to 0, there is no guarantee that translation units
|
||||
compiled with different versions of libc++ can interoperate. However, this
|
||||
leads to code size improvements, since non ABI-facing functions can be
|
||||
deduplicated across translation unit boundaries.
|
||||
|
||||
This macro can be defined by users to control the behavior they want from
|
||||
libc++. The default value of this macro (0 or 1) is controlled by whether
|
||||
`_LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT` is defined, which is intended to
|
||||
be used by vendors only (see below).
|
||||
|
||||
**_LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT**
|
||||
This macro controls the default value for `_LIBCPP_HIDE_FROM_ABI_PER_TU`.
|
||||
When the macro is defined, per TU ABI insulation is enabled by default, and
|
||||
`_LIBCPP_HIDE_FROM_ABI_PER_TU` is defined to 1 unless overridden by users.
|
||||
Otherwise, per TU ABI insulation is disabled by default, and
|
||||
`_LIBCPP_HIDE_FROM_ABI_PER_TU` is defined to 0 unless overridden by users.
|
||||
|
||||
This macro is intended for vendors to control whether they want to ship
|
||||
libc++ with per TU ABI insulation enabled by default. Users can always
|
||||
control the behavior they want by defining `_LIBCPP_HIDE_FROM_ABI_PER_TU`
|
||||
appropriately.
|
||||
|
||||
By default, this macro is not defined, which means that per TU ABI insulation
|
||||
is not provided unless explicitly overridden by users.
|
||||
|
||||
**_LIBCPP_TYPE_VIS**
|
||||
Mark a type's typeinfo, vtable and members as having default visibility.
|
||||
@ -90,20 +138,21 @@ Visibility Macros
|
||||
The macro has an empty definition with GCC.
|
||||
|
||||
**Windows Behavior**: `extern template` and `dllexport` are fundamentally
|
||||
incompatible *on a template class* on Windows; the former suppresses
|
||||
incompatible *on a class template* on Windows; the former suppresses
|
||||
instantiation, while the latter forces it. Specifying both on the same
|
||||
declaration makes the template class be instantiated, which is not desirable
|
||||
declaration makes the class template be instantiated, which is not desirable
|
||||
inside headers. This macro therefore expands to `dllimport` outside of libc++
|
||||
but nothing inside of it (rather than expanding to `dllexport`); instead, the
|
||||
explicit instantiations themselves are marked as exported. Note that this
|
||||
applies *only* to extern template *classes*. Extern template *functions* obey
|
||||
applies *only* to extern *class* templates. Extern *function* templates obey
|
||||
regular import/export semantics, and applying `dllexport` directly to the
|
||||
extern template declaration is the correct thing to do for them.
|
||||
extern template declaration (i.e. using `_LIBCPP_FUNC_VIS`) is the correct
|
||||
thing to do for them.
|
||||
|
||||
**_LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS**
|
||||
Mark the member functions, typeinfo, and vtable of an explicit instantiation
|
||||
of a class template as being exported by the libc++ library. This attribute
|
||||
must be specified on all template class explicit instantiations.
|
||||
must be specified on all class template explicit instantiations.
|
||||
|
||||
It is only necessary to mark the explicit instantiation itself (as opposed to
|
||||
the extern template declaration) as exported on Windows, as discussed above.
|
||||
@ -138,15 +187,6 @@ Visibility Macros
|
||||
against the libc++ headers after making `_LIBCPP_TYPE_VIS` and
|
||||
`_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` expand to default visibility.
|
||||
|
||||
**_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY**
|
||||
Mark a member function of a class template as visible and always inline. This
|
||||
macro should only be applied to member functions of class templates that are
|
||||
externally instantiated. It is important that these symbols are not marked
|
||||
as hidden as that will prevent the dylib definition from being found.
|
||||
|
||||
This macro is used to maintain ABI compatibility for symbols that have been
|
||||
historically exported by the libc++ library but are now marked inline.
|
||||
|
||||
**_LIBCPP_EXCEPTION_ABI**
|
||||
Mark the member functions, typeinfo, and vtable of the type as being exported
|
||||
by the libc++ library. This macro must be applied to all *exception types*.
|
||||
@ -154,6 +194,22 @@ Visibility Macros
|
||||
versioning namespace. This allows throwing and catching some exception types
|
||||
between libc++ and libstdc++.
|
||||
|
||||
**_LIBCPP_INTERNAL_LINKAGE**
|
||||
Mark the affected entity as having internal linkage (i.e. the `static`
|
||||
keyword in C). This is only a best effort: when the `internal_linkage`
|
||||
attribute is not available, we fall back to forcing the function to be
|
||||
inlined, which approximates internal linkage since an externally visible
|
||||
symbol is never generated for that function. This is an internal macro
|
||||
used as an implementation detail by other visibility macros. Never mark
|
||||
a function or a class with this macro directly.
|
||||
|
||||
**_LIBCPP_ALWAYS_INLINE**
|
||||
Forces inlining of the function it is applied to. For visibility purposes,
|
||||
this macro is used to make sure that an externally visible symbol is never
|
||||
generated in an object file when the `internal_linkage` attribute is not
|
||||
available. This is an internal macro used by other visibility macros, and
|
||||
it should not be used directly.
|
||||
|
||||
Links
|
||||
=====
|
||||
|
||||
|
202
docs/FeatureTestMacroTable.rst
Normal file
202
docs/FeatureTestMacroTable.rst
Normal file
@ -0,0 +1,202 @@
|
||||
.. _FeatureTestMacroTable:
|
||||
|
||||
==========================
|
||||
Feature Test Macro Support
|
||||
==========================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This file documents the feature test macros currently supported by libc++.
|
||||
|
||||
.. _feature-status:
|
||||
|
||||
Status
|
||||
======
|
||||
|
||||
.. table:: Current Status
|
||||
:name: feature-status-table
|
||||
:widths: auto
|
||||
|
||||
================================================= =================
|
||||
Macro Name Value
|
||||
================================================= =================
|
||||
**C++ 14**
|
||||
-------------------------------------------------------------------
|
||||
``__cpp_lib_chrono_udls`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_complex_udls`` ``201309L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_exchange_function`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_generic_associative_lookup`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_integer_sequence`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_integral_constant_callable`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_final`` ``201402L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_null_pointer`` ``201309L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_make_reverse_iterator`` ``201402L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_make_unique`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_null_iterators`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_quoted_string_io`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_result_of_sfinae`` ``201210L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_robust_nonmodifying_seq_ops`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_shared_timed_mutex`` ``201402L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_string_udls`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_transformation_trait_aliases`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_transparent_operators`` ``201210L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_tuple_element_t`` ``201402L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_tuples_by_type`` ``201304L``
|
||||
------------------------------------------------- -----------------
|
||||
**C++ 17**
|
||||
-------------------------------------------------------------------
|
||||
``__cpp_lib_addressof_constexpr`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_allocator_traits_is_always_equal`` ``201411L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_any`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_apply`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_array_constexpr`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_as_const`` ``201510L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_atomic_is_always_lock_free`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_bool_constant`` ``201505L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_boyer_moore_searcher`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_byte`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_chrono`` ``201611L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_clamp`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_enable_shared_from_this`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_execution`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_filesystem`` ``201703L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_gcd_lcm`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_hardware_interference_size`` ``201703L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_has_unique_object_representations`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_hypot`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_incomplete_container_elements`` ``201505L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_invoke`` ``201411L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_aggregate`` ``201703L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_invocable`` ``201703L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_swappable`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_launder`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_logical_traits`` ``201510L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_make_from_tuple`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_map_try_emplace`` ``201411L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_math_special_functions`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_memory_resource`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_node_extract`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_nonmember_container_access`` ``201411L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_not_fn`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_optional`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_parallel_algorithm`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_raw_memory_algorithms`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_sample`` ``201603L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_scoped_lock`` ``201703L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_shared_mutex`` ``201505L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_shared_ptr_arrays`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_shared_ptr_weak_type`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_string_view`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_to_chars`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_transparent_operators`` ``201510L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_type_trait_variable_templates`` ``201510L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_uncaught_exceptions`` ``201411L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_unordered_map_try_emplace`` ``201411L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_variant`` ``201606L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_void_t`` ``201411L``
|
||||
------------------------------------------------- -----------------
|
||||
**C++ 2a**
|
||||
-------------------------------------------------------------------
|
||||
``__cpp_lib_atomic_ref`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_bind_front`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_bit_cast`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_char8_t`` ``201811L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_concepts`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_constexpr_misc`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_constexpr_swap_algorithms`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_destroying_delete`` ``201806L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_erase_if`` ``201811L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_generic_unordered_lookup`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_interpolate`` ``201902L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_constant_evaluated`` ``201811L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_list_remove_return_type`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_ranges`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_three_way_comparison`` *unimplemented*
|
||||
================================================= =================
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
# out-of-tree builds.
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS = -n -W
|
||||
SPHINXOPTS = -n -W -v
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
43
docs/ReleaseNotes.rst
Normal file
43
docs/ReleaseNotes.rst
Normal file
@ -0,0 +1,43 @@
|
||||
=========================================
|
||||
Libc++ 10.0.0 (In-Progress) Release Notes
|
||||
=========================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Written by the `Libc++ Team <https://libcxx.llvm.org>`_
|
||||
|
||||
.. warning::
|
||||
|
||||
These are in-progress notes for the upcoming libc++ 10 release.
|
||||
Release notes for previous releases can be found on
|
||||
`the Download Page <https://releases.llvm.org/download.html>`_.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document contains the release notes for the libc++ C++ Standard Library,
|
||||
part of the LLVM Compiler Infrastructure, release 10.0.0. Here we describe the
|
||||
status of libc++ in some detail, including major improvements from the previous
|
||||
release and new feature work. For the general LLVM release notes, see `the LLVM
|
||||
documentation <https://llvm.org/docs/ReleaseNotes.html>`_. All LLVM releases may
|
||||
be downloaded from the `LLVM releases web site <https://llvm.org/releases/>`_.
|
||||
|
||||
For more information about libc++, please see the `Libc++ Web Site
|
||||
<https://libcxx.llvm.org>`_ or the `LLVM Web Site <https://llvm.org>`_.
|
||||
|
||||
Note that if you are reading this file from a Subversion checkout or the
|
||||
main Libc++ web page, this document applies to the *next* release, not
|
||||
the current one. To see the release notes for a specific release, please
|
||||
see the `releases page <https://llvm.org/releases/>`_.
|
||||
|
||||
What's New in Libc++ 10.0.0?
|
||||
============================
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
API Changes
|
||||
-----------
|
||||
- ...
|
@ -8,11 +8,14 @@ Testing libc++
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
libc++ uses LIT to configure and run its tests. The primary way to run the
|
||||
libc++ tests is by using make check-libcxx. However since libc++ can be used
|
||||
in any number of possible configurations it is important to customize the way
|
||||
LIT builds and runs the tests. This guide provides information on how to use
|
||||
LIT directly to test libc++.
|
||||
libc++ uses LIT to configure and run its tests.
|
||||
|
||||
The primary way to run the libc++ tests is by using `make check-libcxx`.
|
||||
|
||||
However since libc++ can be used in any number of possible
|
||||
configurations it is important to customize the way LIT builds and runs
|
||||
the tests. This guide provides information on how to use LIT directly to
|
||||
test libc++.
|
||||
|
||||
Please see the `Lit Command Guide`_ for more information about LIT.
|
||||
|
||||
@ -112,14 +115,14 @@ configuration. Passing the option on the command line will override the default.
|
||||
|
||||
.. option:: std=<standard version>
|
||||
|
||||
**Values**: c++98, c++03, c++11, c++14, c++1z
|
||||
**Values**: c++98, c++03, c++11, c++14, c++17, c++2a
|
||||
|
||||
Change the standard version used when building the tests.
|
||||
|
||||
.. option:: libcxx_site_config=<path/to/lit.site.cfg>
|
||||
|
||||
Specify the site configuration to use when running the tests. This option
|
||||
overrides the enviroment variable LIBCXX_SITE_CONFIG.
|
||||
overrides the environment variable LIBCXX_SITE_CONFIG.
|
||||
|
||||
.. option:: cxx_headers=<path/to/headers>
|
||||
|
||||
@ -138,8 +141,7 @@ configuration. Passing the option on the command line will override the default.
|
||||
Specify the directory of the libc++ library to use at runtime. This directory
|
||||
is not added to the linkers search path. This can be used to compile tests
|
||||
against one version of libc++ and run them using another. The default value
|
||||
for this option is `cxx_library_root`. This option cannot be used
|
||||
when use_system_cxx_lib is provided.
|
||||
for this option is `cxx_library_root`.
|
||||
|
||||
.. option:: use_system_cxx_lib=<bool>
|
||||
|
||||
@ -155,14 +157,6 @@ configuration. Passing the option on the command line will override the default.
|
||||
the default value. Otherwise the default value is True on Windows and False
|
||||
on every other platform.
|
||||
|
||||
.. option:: no_default_flags=<bool>
|
||||
|
||||
**Default**: False
|
||||
|
||||
Disable all default compile and link flags from being added. When this
|
||||
option is used only flags specified using the compile_flags and link_flags
|
||||
will be used.
|
||||
|
||||
.. option:: compile_flags="<list-of-args>"
|
||||
|
||||
Specify additional compile flags as a space delimited string.
|
||||
@ -192,6 +186,14 @@ configuration. Passing the option on the command line will override the default.
|
||||
option is specified or the environment variable LIBCXX_COLOR_DIAGNOSTICS is
|
||||
present then color diagnostics will be enabled.
|
||||
|
||||
.. option:: llvm_unwinder
|
||||
|
||||
Enable the use of LLVM unwinder instead of libgcc.
|
||||
|
||||
.. option:: builtins_library
|
||||
|
||||
Path to the builtins library to use instead of libgcc.
|
||||
|
||||
|
||||
Environment Variables
|
||||
---------------------
|
||||
|
@ -15,7 +15,7 @@ If you already have libc++ installed you can use it with clang.
|
||||
$ clang++ -stdlib=libc++ test.cpp
|
||||
$ clang++ -std=c++11 -stdlib=libc++ test.cpp
|
||||
|
||||
On OS X and FreeBSD libc++ is the default standard library
|
||||
On macOS and FreeBSD libc++ is the default standard library
|
||||
and the ``-stdlib=libc++`` is not required.
|
||||
|
||||
.. _alternate libcxx:
|
||||
@ -34,7 +34,7 @@ can use the following options.
|
||||
The option ``-Wl,-rpath,<libcxx-install-prefix>/lib`` adds a runtime library
|
||||
search path. Meaning that the systems dynamic linker will look for libc++ in
|
||||
``<libcxx-install-prefix>/lib`` whenever the program is run. Alternatively the
|
||||
environment variable ``LD_LIBRARY_PATH`` (``DYLD_LIBRARY_PATH`` on OS X) can
|
||||
environment variable ``LD_LIBRARY_PATH`` (``DYLD_LIBRARY_PATH`` on macOS) can
|
||||
be used to change the dynamic linkers search paths after a program is compiled.
|
||||
|
||||
An example of using ``LD_LIBRARY_PATH``:
|
||||
@ -49,6 +49,17 @@ An example of using ``LD_LIBRARY_PATH``:
|
||||
$ export LD_LIBRARY_PATH=<libcxx-install-prefix>/lib
|
||||
$ ./a.out # Searches for libc++ along LD_LIBRARY_PATH
|
||||
|
||||
Using ``<filesystem>``
|
||||
======================
|
||||
|
||||
Prior to LLVM 9.0, libc++ provides the implementation of the filesystem library
|
||||
in a separate static library. Users of ``<filesystem>`` and ``<experimental/filesystem>``
|
||||
are required to link ``-lc++fs``. Prior to libc++ 7.0, users of
|
||||
``<experimental/filesystem>`` were required to link libc++experimental.
|
||||
|
||||
Starting with LLVM 9.0, support for ``<filesystem>`` is provided in the main
|
||||
library and nothing special is required to use ``<filesystem>``.
|
||||
|
||||
Using libc++experimental and ``<experimental/...>``
|
||||
=====================================================
|
||||
|
||||
@ -73,6 +84,9 @@ page.
|
||||
* The contents of the ``<experimental/...>`` headers and ``libc++experimental.a``
|
||||
library will not remain compatible between versions.
|
||||
* No guarantees of API or ABI stability are provided.
|
||||
* When we implement the standardized version of an experimental feature,
|
||||
the experimental feature is removed two releases after the non-experimental
|
||||
version has shipped. The full policy is explained :ref:`here <experimental features>`.
|
||||
|
||||
Using libc++ on Linux
|
||||
=====================
|
||||
@ -146,6 +160,11 @@ thread safety annotations.
|
||||
build of libc++ which does not export any symbols, which can be useful when
|
||||
building statically for inclusion into another library.
|
||||
|
||||
**_LIBCPP_DISABLE_EXTERN_TEMPLATE**:
|
||||
This macro is used to disable extern template declarations in the libc++
|
||||
headers. The intended use case is for clients who wish to use the libc++
|
||||
headers without taking a dependency on the libc++ library itself.
|
||||
|
||||
**_LIBCPP_ENABLE_TUPLE_IMPLICIT_REDUCED_ARITY_EXTENSION**:
|
||||
This macro is used to re-enable an extension in `std::tuple` which allowed
|
||||
it to be implicitly constructed from fewer initializers than contained
|
||||
@ -177,8 +196,50 @@ thread safety annotations.
|
||||
This macro disables the additional diagnostics generated by libc++ using the
|
||||
`diagnose_if` attribute. These additional diagnostics include checks for:
|
||||
|
||||
* Giving `set`, `map`, `multiset`, `multimap` a comparator which is not
|
||||
const callable.
|
||||
* Giving `set`, `map`, `multiset`, `multimap` and their `unordered_`
|
||||
counterparts a comparator which is not const callable.
|
||||
* Giving an unordered associative container a hasher that is not const
|
||||
callable.
|
||||
|
||||
**_LIBCPP_NO_VCRUNTIME**:
|
||||
Microsoft's C and C++ headers are fairly entangled, and some of their C++
|
||||
headers are fairly hard to avoid. In particular, `vcruntime_new.h` gets pulled
|
||||
in from a lot of other headers and provides definitions which clash with
|
||||
libc++ headers, such as `nothrow_t` (note that `nothrow_t` is a struct, so
|
||||
there's no way for libc++ to provide a compatible definition, since you can't
|
||||
have multiple definitions).
|
||||
|
||||
By default, libc++ solves this problem by deferring to Microsoft's vcruntime
|
||||
headers where needed. However, it may be undesirable to depend on vcruntime
|
||||
headers, since they may not always be available in cross-compilation setups,
|
||||
or they may clash with other headers. The `_LIBCPP_NO_VCRUNTIME` macro
|
||||
prevents libc++ from depending on vcruntime headers. Consequently, it also
|
||||
prevents libc++ headers from being interoperable with vcruntime headers (from
|
||||
the aforementioned clashes), so users of this macro are promising to not
|
||||
attempt to combine libc++ headers with the problematic vcruntime headers. This
|
||||
macro also currently prevents certain `operator new`/`operator delete`
|
||||
replacement scenarios from working, e.g. replacing `operator new` and
|
||||
expecting a non-replaced `operator new[]` to call the replaced `operator new`.
|
||||
|
||||
**_LIBCPP_ENABLE_NODISCARD**:
|
||||
Allow the library to add ``[[nodiscard]]`` attributes to entities not specified
|
||||
as ``[[nodiscard]]`` by the current language dialect. This includes
|
||||
backporting applications of ``[[nodiscard]]`` from newer dialects and
|
||||
additional extended applications at the discretion of the library. All
|
||||
additional applications of ``[[nodiscard]]`` are disabled by default.
|
||||
See :ref:`Extended Applications of [[nodiscard]] <nodiscard extension>` for
|
||||
more information.
|
||||
|
||||
**_LIBCPP_DISABLE_NODISCARD_EXT**:
|
||||
This macro prevents the library from applying ``[[nodiscard]]`` to entities
|
||||
purely as an extension. See :ref:`Extended Applications of [[nodiscard]] <nodiscard extension>`
|
||||
for more information.
|
||||
|
||||
**_LIBCPP_DISABLE_DEPRECATION_WARNINGS**:
|
||||
This macro disables warnings when using deprecated components. For example,
|
||||
using `std::auto_ptr` when compiling in C++11 mode will normally trigger a
|
||||
warning saying that `std::auto_ptr` is deprecated. If the macro is defined,
|
||||
no warning will be emitted. By default, this macro is not defined.
|
||||
|
||||
C++17 Specific Configuration Macros
|
||||
-----------------------------------
|
||||
@ -192,3 +253,96 @@ C++17 Specific Configuration Macros
|
||||
|
||||
**_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR**:
|
||||
This macro is used to re-enable `std::auto_ptr` in C++17.
|
||||
|
||||
C++2a Specific Configuration Macros:
|
||||
------------------------------------
|
||||
**_LIBCPP_DISABLE_NODISCARD_AFTER_CXX17**:
|
||||
This macro can be used to disable diagnostics emitted from functions marked
|
||||
``[[nodiscard]]`` in dialects after C++17. See :ref:`Extended Applications of [[nodiscard]] <nodiscard extension>`
|
||||
for more information.
|
||||
|
||||
|
||||
Libc++ Extensions
|
||||
=================
|
||||
|
||||
This section documents various extensions provided by libc++, how they're
|
||||
provided, and any information regarding how to use them.
|
||||
|
||||
.. _nodiscard extension:
|
||||
|
||||
Extended applications of ``[[nodiscard]]``
|
||||
------------------------------------------
|
||||
|
||||
The ``[[nodiscard]]`` attribute is intended to help users find bugs where
|
||||
function return values are ignored when they shouldn't be. After C++17 the
|
||||
C++ standard has started to declared such library functions as ``[[nodiscard]]``.
|
||||
However, this application is limited and applies only to dialects after C++17.
|
||||
Users who want help diagnosing misuses of STL functions may desire a more
|
||||
liberal application of ``[[nodiscard]]``.
|
||||
|
||||
For this reason libc++ provides an extension that does just that! The
|
||||
extension must be enabled by defining ``_LIBCPP_ENABLE_NODISCARD``. The extended
|
||||
applications of ``[[nodiscard]]`` takes two forms:
|
||||
|
||||
1. Backporting ``[[nodiscard]]`` to entities declared as such by the
|
||||
standard in newer dialects, but not in the present one.
|
||||
|
||||
2. Extended applications of ``[[nodiscard]]``, at the libraries discretion,
|
||||
applied to entities never declared as such by the standard.
|
||||
|
||||
Users may also opt-out of additional applications ``[[nodiscard]]`` using
|
||||
additional macros.
|
||||
|
||||
Applications of the first form, which backport ``[[nodiscard]]`` from a newer
|
||||
dialect may be disabled using macros specific to the dialect it was added. For
|
||||
example ``_LIBCPP_DISABLE_NODISCARD_AFTER_CXX17``.
|
||||
|
||||
Applications of the second form, which are pure extensions, may be disabled
|
||||
by defining ``_LIBCPP_DISABLE_NODISCARD_EXT``.
|
||||
|
||||
|
||||
Entities declared with ``_LIBCPP_NODISCARD_EXT``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This section lists all extended applications of ``[[nodiscard]]`` to entities
|
||||
which no dialect declares as such (See the second form described above).
|
||||
|
||||
* ``adjacent_find``
|
||||
* ``all_of``
|
||||
* ``any_of``
|
||||
* ``binary_search``
|
||||
* ``clamp``
|
||||
* ``count_if``
|
||||
* ``count``
|
||||
* ``equal_range``
|
||||
* ``equal``
|
||||
* ``find_end``
|
||||
* ``find_first_of``
|
||||
* ``find_if_not``
|
||||
* ``find_if``
|
||||
* ``find``
|
||||
* ``get_temporary_buffer``
|
||||
* ``includes``
|
||||
* ``is_heap_until``
|
||||
* ``is_heap``
|
||||
* ``is_partitioned``
|
||||
* ``is_permutation``
|
||||
* ``is_sorted_until``
|
||||
* ``is_sorted``
|
||||
* ``lexicographical_compare``
|
||||
* ``lower_bound``
|
||||
* ``max_element``
|
||||
* ``max``
|
||||
* ``min_element``
|
||||
* ``min``
|
||||
* ``minmax_element``
|
||||
* ``minmax``
|
||||
* ``mismatch``
|
||||
* ``none_of``
|
||||
* ``remove_if``
|
||||
* ``remove``
|
||||
* ``search_n``
|
||||
* ``search``
|
||||
* ``unique``
|
||||
* ``upper_bound``
|
||||
* ``lock_guard``'s constructors
|
||||
|
@ -40,16 +40,16 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'libc++'
|
||||
copyright = u'2011-2017, LLVM Project'
|
||||
copyright = u'2011-2018, LLVM Project'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '5.0'
|
||||
version = '10.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '5.0'
|
||||
release = '10.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@ -241,7 +241,7 @@ texinfo_documents = [
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
|
||||
# FIXME: Define intersphinx configration.
|
||||
# FIXME: Define intersphinx configuration.
|
||||
intersphinx_mapping = {}
|
||||
|
||||
|
||||
|
@ -34,11 +34,17 @@ Getting Started with libc++
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
ReleaseNotes
|
||||
UsingLibcxx
|
||||
BuildingLibcxx
|
||||
TestingLibcxx
|
||||
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
FeatureTestMacroTable
|
||||
|
||||
Current Status
|
||||
--------------
|
||||
|
||||
@ -79,15 +85,15 @@ reasons, but some of the major ones are:
|
||||
Platform and Compiler Support
|
||||
-----------------------------
|
||||
|
||||
libc++ is known to work on the following platforms, using gcc-4.2 and
|
||||
clang (lack of C++11 language support disables some functionality).
|
||||
libc++ is known to work on the following platforms, using gcc and
|
||||
clang.
|
||||
Note that functionality provided by ``<atomic>`` is only functional with clang
|
||||
and GCC.
|
||||
|
||||
============ ==================== ============ ========================
|
||||
OS Arch Compilers ABI Library
|
||||
============ ==================== ============ ========================
|
||||
Mac OS X i386, x86_64 Clang, GCC libc++abi
|
||||
macOS i386, x86_64 Clang, GCC libc++abi
|
||||
FreeBSD 10+ i386, x86_64, ARM Clang, GCC libcxxrt, libc++abi
|
||||
Linux i386, x86_64 Clang, GCC libc++abi
|
||||
============ ==================== ============ ========================
|
||||
@ -95,17 +101,18 @@ Linux i386, x86_64 Clang, GCC libc++abi
|
||||
The following minimum compiler versions are strongly recommended.
|
||||
|
||||
* Clang 3.5 and above
|
||||
* GCC 4.7 and above.
|
||||
* GCC 5.0 and above.
|
||||
|
||||
Anything older *may* work.
|
||||
The C++03 dialect is only supported for Clang compilers.
|
||||
|
||||
C++ Dialect Support
|
||||
---------------------
|
||||
|
||||
* C++11 - Complete
|
||||
* `C++14 - Complete <http://libcxx.llvm.org/cxx1y_status.html>`__
|
||||
* `C++1z - In Progress <http://libcxx.llvm.org/cxx1z_status.html>`__
|
||||
* `C++17 - In Progress <http://libcxx.llvm.org/cxx1z_status.html>`__
|
||||
* `Post C++14 Technical Specifications - In Progress <http://libcxx.llvm.org/ts1z_status.html>`__
|
||||
* :ref:`C++ Feature Test Macro Status <feature-status>`
|
||||
|
||||
Notes and Known Issues
|
||||
----------------------
|
||||
@ -114,8 +121,6 @@ This list contains known issues with libc++
|
||||
|
||||
* Building libc++ with ``-fno-rtti`` is not supported. However
|
||||
linking against it with ``-fno-rtti`` is supported.
|
||||
* On OS X v10.8 and older the CMake option ``-DLIBCXX_LIBCPPABI_VERSION=""``
|
||||
must be used during configuration.
|
||||
|
||||
|
||||
A full list of currently open libc++ bugs can be `found here`__.
|
||||
@ -128,11 +133,16 @@ Design Documents
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
DesignDocs/AvailabilityMarkup
|
||||
DesignDocs/DebugMode
|
||||
DesignDocs/CapturingConfigInfo
|
||||
DesignDocs/ABIVersioning
|
||||
DesignDocs/ExperimentalFeatures
|
||||
DesignDocs/VisibilityMacros
|
||||
DesignDocs/ThreadingSupportAPI
|
||||
DesignDocs/FileTimeType
|
||||
DesignDocs/FeatureTestMacros
|
||||
DesignDocs/ExtendedCXX03Support
|
||||
|
||||
* `<atomic> design <http://libcxx.llvm.org/atomic_design.html>`_
|
||||
* `<type_traits> design <http://libcxx.llvm.org/type_traits_design.html>`_
|
||||
@ -145,7 +155,7 @@ Build Bots and Test Coverage
|
||||
|
||||
* `LLVM Buildbot Builders <http://lab.llvm.org:8011/console>`_
|
||||
* `Apple Jenkins Builders <http://lab.llvm.org:8080/green/view/Libcxx/>`_
|
||||
* `EricWF's Nightly Builders <http://ds2.efcs.ca:8080/console>`_
|
||||
* `Windows Appveyor Builders <https://ci.appveyor.com/project/llvm-mirror/libcxx>`_
|
||||
* `Code Coverage Results <http://efcs.ca/libcxx-coverage>`_
|
||||
|
||||
Getting Involved
|
||||
@ -158,21 +168,18 @@ and `Getting started with LLVM <http://llvm.org/docs/GettingStarted.html>`__.
|
||||
|
||||
If you think you've found a bug in libc++, please report it using
|
||||
the `LLVM Bugzilla`_. If you're not sure, you
|
||||
can post a message to the `cfe-dev mailing list`_ or on IRC.
|
||||
Please include "libc++" in your subject.
|
||||
can post a message to the `libcxx-dev mailing list`_ or on IRC.
|
||||
|
||||
**Patches**
|
||||
|
||||
If you want to contribute a patch to libc++, the best place for that is
|
||||
`Phabricator <http://llvm.org/docs/Phabricator.html>`_. Please include [libcxx] in the subject and
|
||||
add `cfe-commits` as a subscriber. Also make sure you are subscribed to the
|
||||
`cfe-commits mailing list <http://lists.llvm.org/mailman/listinfo/cfe-commits>`_.
|
||||
`Phabricator <http://llvm.org/docs/Phabricator.html>`_. Please add `libcxx-commits` as a subscriber.
|
||||
Also make sure you are subscribed to the `libcxx-commits mailing list <http://lists.llvm.org/mailman/listinfo/libcxx-commits>`_.
|
||||
|
||||
**Discussion and Questions**
|
||||
|
||||
Send discussions and questions to the
|
||||
`cfe-dev mailing list <http://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
|
||||
Please include [libcxx] in the subject.
|
||||
`libcxx-dev mailing list <http://lists.llvm.org/mailman/listinfo/libcxx-dev>`_.
|
||||
|
||||
|
||||
|
||||
@ -181,7 +188,6 @@ Quick Links
|
||||
* `LLVM Homepage <http://llvm.org/>`_
|
||||
* `libc++abi Homepage <http://libcxxabi.llvm.org/>`_
|
||||
* `LLVM Bugzilla <https://bugs.llvm.org/>`_
|
||||
* `cfe-commits Mailing List`_
|
||||
* `cfe-dev Mailing List`_
|
||||
* `Browse libc++ -- SVN <http://llvm.org/svn/llvm-project/libcxx/trunk/>`_
|
||||
* `Browse libc++ -- ViewVC <http://llvm.org/viewvc/llvm-project/libcxx/trunk/>`_
|
||||
* `libcxx-commits Mailing List`_
|
||||
* `libcxx-dev Mailing List`_
|
||||
* `Browse libc++ Sources <https://github.com/llvm/llvm-project/tree/master/libcxx/>`_
|
||||
|
20
fuzzing/RoutineNames.txt
Normal file
20
fuzzing/RoutineNames.txt
Normal file
@ -0,0 +1,20 @@
|
||||
sort
|
||||
stable_sort
|
||||
partition
|
||||
partition_copy
|
||||
stable_partition
|
||||
unique
|
||||
unique_copy
|
||||
nth_element
|
||||
partial_sort
|
||||
partial_sort_copy
|
||||
make_heap
|
||||
push_heap
|
||||
pop_heap
|
||||
regex_ECMAScript
|
||||
regex_POSIX
|
||||
regex_extended
|
||||
regex_awk
|
||||
regex_grep
|
||||
regex_egrep
|
||||
search
|
194
fuzzing/fuzz_test.cpp
Normal file
194
fuzzing/fuzz_test.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------- fuzz_test.cpp ------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// A simple program for running regressions on the fuzzing routines.
|
||||
// This code is not part of any shipping product.
|
||||
//
|
||||
// To build:
|
||||
// clang++ -std=c++11 fuzz_test.cpp fuzzing.cpp
|
||||
//
|
||||
// To use:
|
||||
// fuzz_test -r partial_sort [-v] files...
|
||||
//
|
||||
// Each file should contain a test case.
|
||||
|
||||
// TODO: should add some memory tracking, too.
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
|
||||
#include "fuzzing.h"
|
||||
|
||||
// ==== Count memory allocations ====
|
||||
|
||||
struct MemoryCounters {
|
||||
size_t totalAllocationCount;
|
||||
size_t netAllocationCount;
|
||||
size_t totalBytesAllocated;
|
||||
};
|
||||
|
||||
MemoryCounters gMemoryCounters;
|
||||
|
||||
void ZeroMemoryCounters() {
|
||||
gMemoryCounters.totalAllocationCount = 0;
|
||||
gMemoryCounters.netAllocationCount = 0;
|
||||
gMemoryCounters.totalBytesAllocated = 0;
|
||||
}
|
||||
|
||||
void* operator new(std::size_t size)
|
||||
{
|
||||
if (size == 0) size = 1;
|
||||
void *p = ::malloc(size);
|
||||
if (p == NULL)
|
||||
throw std::bad_alloc();
|
||||
gMemoryCounters.totalAllocationCount += 1;
|
||||
gMemoryCounters.netAllocationCount += 1;
|
||||
gMemoryCounters.totalBytesAllocated += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
void* operator new(std::size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
try { return operator new(size); }
|
||||
catch (const std::bad_alloc &) {}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size)
|
||||
{
|
||||
return ::operator new(size);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
try { return operator new(size); }
|
||||
catch (const std::bad_alloc &) {}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void operator delete(void* ptr) noexcept
|
||||
{
|
||||
if (ptr)
|
||||
::free(ptr);
|
||||
gMemoryCounters.netAllocationCount -= 1;
|
||||
}
|
||||
|
||||
void operator delete(void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void* ptr) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
// ==== End count memory allocations ====
|
||||
|
||||
|
||||
typedef int (*FuzzProc) (const uint8_t *data, size_t size);
|
||||
|
||||
const std::map<std::string, FuzzProc> procs = {
|
||||
{"sort", fuzzing::sort},
|
||||
{"stable_sort", fuzzing::stable_sort},
|
||||
{"partition", fuzzing::partition},
|
||||
{"partition_copy", fuzzing::partition_copy},
|
||||
{"stable_partition", fuzzing::stable_partition},
|
||||
{"unique", fuzzing::unique},
|
||||
{"unique_copy", fuzzing::unique_copy},
|
||||
{"nth_element", fuzzing::nth_element},
|
||||
{"partial_sort", fuzzing::partial_sort},
|
||||
{"partial_sort_copy", fuzzing::partial_sort_copy},
|
||||
{"make_heap", fuzzing::make_heap},
|
||||
{"push_heap", fuzzing::push_heap},
|
||||
{"pop_heap", fuzzing::pop_heap},
|
||||
{"regex_ECMAScript", fuzzing::regex_ECMAScript},
|
||||
{"regex_POSIX", fuzzing::regex_POSIX},
|
||||
{"regex_extended", fuzzing::regex_extended},
|
||||
{"regex_awk", fuzzing::regex_awk},
|
||||
{"regex_grep", fuzzing::regex_grep},
|
||||
{"regex_egrep", fuzzing::regex_egrep},
|
||||
{"search", fuzzing::search}
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool verbose = false;
|
||||
|
||||
void test_one(const char *filename, FuzzProc fp)
|
||||
{
|
||||
std::vector<uint8_t> v;
|
||||
std::ifstream f (filename, std::ios::binary);
|
||||
if (!f.is_open())
|
||||
std::cerr << "## Can't open '" << filename << "'" << std::endl;
|
||||
else
|
||||
{
|
||||
typedef std::istream_iterator<uint8_t> Iter;
|
||||
std::copy(Iter(f), Iter(), std::back_inserter(v));
|
||||
if (verbose)
|
||||
std::cout << "File '" << filename << "' contains " << v.size() << " entries" << std::endl;
|
||||
ZeroMemoryCounters();
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
int ret = fp (v.data(), v.size());
|
||||
const auto finish_time = std::chrono::high_resolution_clock::now();
|
||||
MemoryCounters mc = gMemoryCounters;
|
||||
if (ret != 0)
|
||||
std::cerr << "## Failure code: " << ret << std::endl;
|
||||
if (verbose)
|
||||
{
|
||||
std::cout << "Execution time: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(finish_time - start_time).count()
|
||||
<< " milliseconds" << std::endl;
|
||||
std::cout << "Memory: "
|
||||
<< mc.totalBytesAllocated << " bytes allocated ("
|
||||
<< mc.totalAllocationCount << " allocations); "
|
||||
<< mc.netAllocationCount << " allocations remain" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usage (const char *name)
|
||||
{
|
||||
std::cout << "Usage: " << name << " -r proc [-v] files..." << std::endl;
|
||||
std::cout << "Supported routines:" << std::endl;
|
||||
for (const auto &p : procs)
|
||||
std::cout << " " << p.first << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// Poor man's command-line options
|
||||
const std::string dashR("-r");
|
||||
const std::string dashV("-v");
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 4 || dashR != argv[1] || procs.find(argv[2]) == procs.end())
|
||||
usage(argv[0]);
|
||||
else {
|
||||
FuzzProc fp = procs.find(argv[2])->second;
|
||||
int firstFile = 3;
|
||||
if (dashV == argv[firstFile])
|
||||
{
|
||||
verbose = true;
|
||||
++firstFile;
|
||||
}
|
||||
for (int i = firstFile; i < argc; ++i)
|
||||
test_one(argv[i], fp);
|
||||
}
|
||||
}
|
617
fuzzing/fuzzing.cpp
Normal file
617
fuzzing/fuzzing.cpp
Normal file
@ -0,0 +1,617 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------- fuzzing.cpp -------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// A set of routines to use when fuzzing the algorithms in libc++
|
||||
// Each one tests a single algorithm.
|
||||
//
|
||||
// They all have the form of:
|
||||
// int `algorithm`(const uint8_t *data, size_t size);
|
||||
//
|
||||
// They perform the operation, and then check to see if the results are correct.
|
||||
// If so, they return zero, and non-zero otherwise.
|
||||
//
|
||||
// For example, sort calls std::sort, then checks two things:
|
||||
// (1) The resulting vector is sorted
|
||||
// (2) The resulting vector contains the same elements as the original data.
|
||||
|
||||
|
||||
|
||||
#include "fuzzing.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <regex>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// If we had C++14, we could use the four iterator version of is_permutation and equal
|
||||
|
||||
namespace fuzzing {
|
||||
|
||||
// This is a struct we can use to test the stable_XXX algorithms.
|
||||
// perform the operation on the key, then check the order of the payload.
|
||||
|
||||
struct stable_test {
|
||||
uint8_t key;
|
||||
size_t payload;
|
||||
|
||||
stable_test(uint8_t k) : key(k), payload(0) {}
|
||||
stable_test(uint8_t k, size_t p) : key(k), payload(p) {}
|
||||
};
|
||||
|
||||
void swap(stable_test &lhs, stable_test &rhs)
|
||||
{
|
||||
using std::swap;
|
||||
swap(lhs.key, rhs.key);
|
||||
swap(lhs.payload, rhs.payload);
|
||||
}
|
||||
|
||||
struct key_less
|
||||
{
|
||||
bool operator () (const stable_test &lhs, const stable_test &rhs) const
|
||||
{
|
||||
return lhs.key < rhs.key;
|
||||
}
|
||||
};
|
||||
|
||||
struct payload_less
|
||||
{
|
||||
bool operator () (const stable_test &lhs, const stable_test &rhs) const
|
||||
{
|
||||
return lhs.payload < rhs.payload;
|
||||
}
|
||||
};
|
||||
|
||||
struct total_less
|
||||
{
|
||||
bool operator () (const stable_test &lhs, const stable_test &rhs) const
|
||||
{
|
||||
return lhs.key == rhs.key ? lhs.payload < rhs.payload : lhs.key < rhs.key;
|
||||
}
|
||||
};
|
||||
|
||||
bool operator==(const stable_test &lhs, const stable_test &rhs)
|
||||
{
|
||||
return lhs.key == rhs.key && lhs.payload == rhs.payload;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct is_even
|
||||
{
|
||||
bool operator () (const T &t) const
|
||||
{
|
||||
return t % 2 == 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct is_even<stable_test>
|
||||
{
|
||||
bool operator () (const stable_test &t) const
|
||||
{
|
||||
return t.key % 2 == 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<uint8_t> Vec;
|
||||
typedef std::vector<stable_test> StableVec;
|
||||
typedef StableVec::const_iterator SVIter;
|
||||
|
||||
// Cheap version of is_permutation
|
||||
// Builds a set of buckets for each of the key values.
|
||||
// Sums all the payloads.
|
||||
// Not 100% perfect, but _way_ faster
|
||||
bool is_permutation(SVIter first1, SVIter last1, SVIter first2)
|
||||
{
|
||||
size_t xBuckets[256] = {0};
|
||||
size_t xPayloads[256] = {0};
|
||||
size_t yBuckets[256] = {0};
|
||||
size_t yPayloads[256] = {0};
|
||||
|
||||
for (; first1 != last1; ++first1, ++first2)
|
||||
{
|
||||
xBuckets [first1->key]++;
|
||||
xPayloads[first1->key] += first1->payload;
|
||||
|
||||
yBuckets [first2->key]++;
|
||||
yPayloads[first2->key] += first2->payload;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
if (xBuckets[i] != yBuckets[i])
|
||||
return false;
|
||||
if (xPayloads[i] != yPayloads[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Iter1, typename Iter2>
|
||||
bool is_permutation(Iter1 first1, Iter1 last1, Iter2 first2)
|
||||
{
|
||||
static_assert((std::is_same<typename std::iterator_traits<Iter1>::value_type, uint8_t>::value), "");
|
||||
static_assert((std::is_same<typename std::iterator_traits<Iter2>::value_type, uint8_t>::value), "");
|
||||
|
||||
size_t xBuckets[256] = {0};
|
||||
size_t yBuckets[256] = {0};
|
||||
|
||||
for (; first1 != last1; ++first1, ++first2)
|
||||
{
|
||||
xBuckets [*first1]++;
|
||||
yBuckets [*first2]++;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
if (xBuckets[i] != yBuckets[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// == sort ==
|
||||
int sort(const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec working(data, data + size);
|
||||
std::sort(working.begin(), working.end());
|
||||
|
||||
if (!std::is_sorted(working.begin(), working.end())) return 1;
|
||||
if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// == stable_sort ==
|
||||
int stable_sort(const uint8_t *data, size_t size)
|
||||
{
|
||||
StableVec input;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
input.push_back(stable_test(data[i], i));
|
||||
StableVec working = input;
|
||||
std::stable_sort(working.begin(), working.end(), key_less());
|
||||
|
||||
if (!std::is_sorted(working.begin(), working.end(), key_less())) return 1;
|
||||
auto iter = working.begin();
|
||||
while (iter != working.end())
|
||||
{
|
||||
auto range = std::equal_range(iter, working.end(), *iter, key_less());
|
||||
if (!std::is_sorted(range.first, range.second, total_less())) return 2;
|
||||
iter = range.second;
|
||||
}
|
||||
if (!fuzzing::is_permutation(input.cbegin(), input.cend(), working.cbegin())) return 99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// == partition ==
|
||||
int partition(const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec working(data, data + size);
|
||||
auto iter = std::partition(working.begin(), working.end(), is_even<uint8_t>());
|
||||
|
||||
if (!std::all_of (working.begin(), iter, is_even<uint8_t>())) return 1;
|
||||
if (!std::none_of(iter, working.end(), is_even<uint8_t>())) return 2;
|
||||
if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// == partition_copy ==
|
||||
int partition_copy(const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec v1, v2;
|
||||
auto iter = std::partition_copy(data, data + size,
|
||||
std::back_inserter<Vec>(v1), std::back_inserter<Vec>(v2),
|
||||
is_even<uint8_t>());
|
||||
|
||||
// The two vectors should add up to the original size
|
||||
if (v1.size() + v2.size() != size) return 1;
|
||||
|
||||
// All of the even values should be in the first vector, and none in the second
|
||||
if (!std::all_of (v1.begin(), v1.end(), is_even<uint8_t>())) return 2;
|
||||
if (!std::none_of(v2.begin(), v2.end(), is_even<uint8_t>())) return 3;
|
||||
|
||||
// Every value in both vectors has to be in the original
|
||||
|
||||
// Make a copy of the input, and sort it
|
||||
Vec v0{data, data + size};
|
||||
std::sort(v0.begin(), v0.end());
|
||||
|
||||
// Sort each vector and ensure that all of the elements appear in the original input
|
||||
std::sort(v1.begin(), v1.end());
|
||||
if (!std::includes(v0.begin(), v0.end(), v1.begin(), v1.end())) return 4;
|
||||
|
||||
std::sort(v2.begin(), v2.end());
|
||||
if (!std::includes(v0.begin(), v0.end(), v2.begin(), v2.end())) return 5;
|
||||
|
||||
// This, while simple, is really slow - 20 seconds on a 500K element input.
|
||||
// for (auto v: v1)
|
||||
// if (std::find(data, data + size, v) == data + size) return 4;
|
||||
//
|
||||
// for (auto v: v2)
|
||||
// if (std::find(data, data + size, v) == data + size) return 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// == stable_partition ==
|
||||
int stable_partition (const uint8_t *data, size_t size)
|
||||
{
|
||||
StableVec input;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
input.push_back(stable_test(data[i], i));
|
||||
StableVec working = input;
|
||||
auto iter = std::stable_partition(working.begin(), working.end(), is_even<stable_test>());
|
||||
|
||||
if (!std::all_of (working.begin(), iter, is_even<stable_test>())) return 1;
|
||||
if (!std::none_of(iter, working.end(), is_even<stable_test>())) return 2;
|
||||
if (!std::is_sorted(working.begin(), iter, payload_less())) return 3;
|
||||
if (!std::is_sorted(iter, working.end(), payload_less())) return 4;
|
||||
if (!fuzzing::is_permutation(input.cbegin(), input.cend(), working.cbegin())) return 99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// == nth_element ==
|
||||
// use the first element as a position into the data
|
||||
int nth_element (const uint8_t *data, size_t size)
|
||||
{
|
||||
if (size <= 1) return 0;
|
||||
const size_t partition_point = data[0] % size;
|
||||
Vec working(data + 1, data + size);
|
||||
const auto partition_iter = working.begin() + partition_point;
|
||||
std::nth_element(working.begin(), partition_iter, working.end());
|
||||
|
||||
// nth may be the end iterator, in this case nth_element has no effect.
|
||||
if (partition_iter == working.end())
|
||||
{
|
||||
if (!std::equal(data + 1, data + size, working.begin())) return 98;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t nth = *partition_iter;
|
||||
if (!std::all_of(working.begin(), partition_iter, [=](uint8_t v) { return v <= nth; }))
|
||||
return 1;
|
||||
if (!std::all_of(partition_iter, working.end(), [=](uint8_t v) { return v >= nth; }))
|
||||
return 2;
|
||||
if (!fuzzing::is_permutation(data + 1, data + size, working.cbegin())) return 99;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// == partial_sort ==
|
||||
// use the first element as a position into the data
|
||||
int partial_sort (const uint8_t *data, size_t size)
|
||||
{
|
||||
if (size <= 1) return 0;
|
||||
const size_t sort_point = data[0] % size;
|
||||
Vec working(data + 1, data + size);
|
||||
const auto sort_iter = working.begin() + sort_point;
|
||||
std::partial_sort(working.begin(), sort_iter, working.end());
|
||||
|
||||
if (sort_iter != working.end())
|
||||
{
|
||||
const uint8_t nth = *std::min_element(sort_iter, working.end());
|
||||
if (!std::all_of(working.begin(), sort_iter, [=](uint8_t v) { return v <= nth; }))
|
||||
return 1;
|
||||
if (!std::all_of(sort_iter, working.end(), [=](uint8_t v) { return v >= nth; }))
|
||||
return 2;
|
||||
}
|
||||
if (!std::is_sorted(working.begin(), sort_iter)) return 3;
|
||||
if (!fuzzing::is_permutation(data + 1, data + size, working.cbegin())) return 99;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// == partial_sort_copy ==
|
||||
// use the first element as a count
|
||||
int partial_sort_copy (const uint8_t *data, size_t size)
|
||||
{
|
||||
if (size <= 1) return 0;
|
||||
const size_t num_results = data[0] % size;
|
||||
Vec results(num_results);
|
||||
(void) std::partial_sort_copy(data + 1, data + size, results.begin(), results.end());
|
||||
|
||||
// The results have to be sorted
|
||||
if (!std::is_sorted(results.begin(), results.end())) return 1;
|
||||
// All the values in results have to be in the original data
|
||||
for (auto v: results)
|
||||
if (std::find(data + 1, data + size, v) == data + size) return 2;
|
||||
|
||||
// The things in results have to be the smallest N in the original data
|
||||
Vec sorted(data + 1, data + size);
|
||||
std::sort(sorted.begin(), sorted.end());
|
||||
if (!std::equal(results.begin(), results.end(), sorted.begin())) return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The second sequence has been "uniqued"
|
||||
template <typename Iter1, typename Iter2>
|
||||
static bool compare_unique(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2)
|
||||
{
|
||||
assert(first1 != last1 && first2 != last2);
|
||||
if (*first1 != *first2) return false;
|
||||
|
||||
uint8_t last_value = *first1;
|
||||
++first1; ++first2;
|
||||
while(first1 != last1 && first2 != last2)
|
||||
{
|
||||
// Skip over dups in the first sequence
|
||||
while (*first1 == last_value)
|
||||
if (++first1 == last1) return false;
|
||||
if (*first1 != *first2) return false;
|
||||
last_value = *first1;
|
||||
++first1; ++first2;
|
||||
}
|
||||
|
||||
// Still stuff left in the 'uniqued' sequence - oops
|
||||
if (first1 == last1 && first2 != last2) return false;
|
||||
|
||||
// Still stuff left in the original sequence - better be all the same
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (*first1 != last_value) return false;
|
||||
++first1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// == unique ==
|
||||
int unique (const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec working(data, data + size);
|
||||
std::sort(working.begin(), working.end());
|
||||
Vec results = working;
|
||||
Vec::iterator new_end = std::unique(results.begin(), results.end());
|
||||
Vec::iterator it; // scratch iterator
|
||||
|
||||
// Check the size of the unique'd sequence.
|
||||
// it should only be zero if the input sequence was empty.
|
||||
if (results.begin() == new_end)
|
||||
return working.size() == 0 ? 0 : 1;
|
||||
|
||||
// 'results' is sorted
|
||||
if (!std::is_sorted(results.begin(), new_end)) return 2;
|
||||
|
||||
// All the elements in 'results' must be different
|
||||
it = results.begin();
|
||||
uint8_t prev_value = *it++;
|
||||
for (; it != new_end; ++it)
|
||||
{
|
||||
if (*it == prev_value) return 3;
|
||||
prev_value = *it;
|
||||
}
|
||||
|
||||
// Every element in 'results' must be in 'working'
|
||||
for (it = results.begin(); it != new_end; ++it)
|
||||
if (std::find(working.begin(), working.end(), *it) == working.end())
|
||||
return 4;
|
||||
|
||||
// Every element in 'working' must be in 'results'
|
||||
for (auto v : working)
|
||||
if (std::find(results.begin(), new_end, v) == new_end)
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// == unique_copy ==
|
||||
int unique_copy (const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec working(data, data + size);
|
||||
std::sort(working.begin(), working.end());
|
||||
Vec results;
|
||||
(void) std::unique_copy(working.begin(), working.end(),
|
||||
std::back_inserter<Vec>(results));
|
||||
Vec::iterator it; // scratch iterator
|
||||
|
||||
// Check the size of the unique'd sequence.
|
||||
// it should only be zero if the input sequence was empty.
|
||||
if (results.size() == 0)
|
||||
return working.size() == 0 ? 0 : 1;
|
||||
|
||||
// 'results' is sorted
|
||||
if (!std::is_sorted(results.begin(), results.end())) return 2;
|
||||
|
||||
// All the elements in 'results' must be different
|
||||
it = results.begin();
|
||||
uint8_t prev_value = *it++;
|
||||
for (; it != results.end(); ++it)
|
||||
{
|
||||
if (*it == prev_value) return 3;
|
||||
prev_value = *it;
|
||||
}
|
||||
|
||||
// Every element in 'results' must be in 'working'
|
||||
for (auto v : results)
|
||||
if (std::find(working.begin(), working.end(), v) == working.end())
|
||||
return 4;
|
||||
|
||||
// Every element in 'working' must be in 'results'
|
||||
for (auto v : working)
|
||||
if (std::find(results.begin(), results.end(), v) == results.end())
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// -- regex fuzzers
|
||||
static int regex_helper(const uint8_t *data, size_t size, std::regex::flag_type flag)
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string s((const char *)data, size);
|
||||
std::regex re(s, flag);
|
||||
return std::regex_match(s, re) ? 1 : 0;
|
||||
}
|
||||
catch (std::regex_error &ex) {}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int regex_ECMAScript (const uint8_t *data, size_t size)
|
||||
{
|
||||
(void) regex_helper(data, size, std::regex_constants::ECMAScript);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regex_POSIX (const uint8_t *data, size_t size)
|
||||
{
|
||||
(void) regex_helper(data, size, std::regex_constants::basic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regex_extended (const uint8_t *data, size_t size)
|
||||
{
|
||||
(void) regex_helper(data, size, std::regex_constants::extended);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regex_awk (const uint8_t *data, size_t size)
|
||||
{
|
||||
(void) regex_helper(data, size, std::regex_constants::awk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regex_grep (const uint8_t *data, size_t size)
|
||||
{
|
||||
(void) regex_helper(data, size, std::regex_constants::grep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regex_egrep (const uint8_t *data, size_t size)
|
||||
{
|
||||
(void) regex_helper(data, size, std::regex_constants::egrep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -- heap fuzzers
|
||||
int make_heap (const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec working(data, data + size);
|
||||
std::make_heap(working.begin(), working.end());
|
||||
|
||||
if (!std::is_heap(working.begin(), working.end())) return 1;
|
||||
if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int push_heap (const uint8_t *data, size_t size)
|
||||
{
|
||||
if (size < 2) return 0;
|
||||
|
||||
// Make a heap from the first half of the data
|
||||
Vec working(data, data + size);
|
||||
auto iter = working.begin() + (size / 2);
|
||||
std::make_heap(working.begin(), iter);
|
||||
if (!std::is_heap(working.begin(), iter)) return 1;
|
||||
|
||||
// Now push the rest onto the heap, one at a time
|
||||
++iter;
|
||||
for (; iter != working.end(); ++iter) {
|
||||
std::push_heap(working.begin(), iter);
|
||||
if (!std::is_heap(working.begin(), iter)) return 2;
|
||||
}
|
||||
|
||||
if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pop_heap (const uint8_t *data, size_t size)
|
||||
{
|
||||
if (size < 2) return 0;
|
||||
Vec working(data, data + size);
|
||||
std::make_heap(working.begin(), working.end());
|
||||
|
||||
// Pop things off, one at a time
|
||||
auto iter = --working.end();
|
||||
while (iter != working.begin()) {
|
||||
std::pop_heap(working.begin(), iter);
|
||||
if (!std::is_heap(working.begin(), --iter)) return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// -- search fuzzers
|
||||
int search (const uint8_t *data, size_t size)
|
||||
{
|
||||
if (size < 2) return 0;
|
||||
|
||||
const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
|
||||
assert(pat_size <= size - 1);
|
||||
const uint8_t *pat_begin = data + 1;
|
||||
const uint8_t *pat_end = pat_begin + pat_size;
|
||||
const uint8_t *data_end = data + size;
|
||||
assert(pat_end <= data_end);
|
||||
// std::cerr << "data[0] = " << size_t(data[0]) << " ";
|
||||
// std::cerr << "Pattern size = " << pat_size << "; corpus is " << size - 1 << std::endl;
|
||||
auto it = std::search(pat_end, data_end, pat_begin, pat_end);
|
||||
if (it != data_end) // not found
|
||||
if (!std::equal(pat_begin, pat_end, it))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static int search_helper (const uint8_t *data, size_t size)
|
||||
{
|
||||
if (size < 2) return 0;
|
||||
|
||||
const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
|
||||
const uint8_t *pat_begin = data + 1;
|
||||
const uint8_t *pat_end = pat_begin + pat_size;
|
||||
const uint8_t *data_end = data + size;
|
||||
|
||||
auto it = std::search(pat_end, data_end, S(pat_begin, pat_end));
|
||||
if (it != data_end) // not found
|
||||
if (!std::equal(pat_begin, pat_end, it))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// These are still in std::experimental
|
||||
// int search_boyer_moore (const uint8_t *data, size_t size)
|
||||
// {
|
||||
// return search_helper<std::boyer_moore_searcher<const uint8_t *>>(data, size);
|
||||
// }
|
||||
//
|
||||
// int search_boyer_moore_horspool (const uint8_t *data, size_t size)
|
||||
// {
|
||||
// return search_helper<std::boyer_moore_horspool_searcher<const uint8_t *>>(data, size);
|
||||
// }
|
||||
|
||||
|
||||
// -- set operation fuzzers
|
||||
template <typename S>
|
||||
static void set_helper (const uint8_t *data, size_t size, Vec &v1, Vec &v2)
|
||||
{
|
||||
assert(size > 1);
|
||||
|
||||
const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
|
||||
const uint8_t *pat_begin = data + 1;
|
||||
const uint8_t *pat_end = pat_begin + pat_size;
|
||||
const uint8_t *data_end = data + size;
|
||||
v1.assign(pat_begin, pat_end);
|
||||
v2.assign(pat_end, data_end);
|
||||
|
||||
std::sort(v1.begin(), v1.end());
|
||||
std::sort(v2.begin(), v2.end());
|
||||
}
|
||||
|
||||
} // namespace fuzzing
|
61
fuzzing/fuzzing.h
Normal file
61
fuzzing/fuzzing.h
Normal file
@ -0,0 +1,61 @@
|
||||
// -*- C++ -*-
|
||||
//===-------------------------- fuzzing.h --------------------------------===//
|
||||
//
|
||||
// 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_FUZZING
|
||||
#define _LIBCPP_FUZZING
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <cstdint> // for uint8_t
|
||||
|
||||
namespace fuzzing {
|
||||
|
||||
// These all return 0 on success; != 0 on failure
|
||||
int sort (const uint8_t *data, size_t size);
|
||||
int stable_sort (const uint8_t *data, size_t size);
|
||||
int partition (const uint8_t *data, size_t size);
|
||||
int partition_copy (const uint8_t *data, size_t size);
|
||||
int stable_partition (const uint8_t *data, size_t size);
|
||||
int unique (const uint8_t *data, size_t size);
|
||||
int unique_copy (const uint8_t *data, size_t size);
|
||||
|
||||
// partition and stable_partition take Bi-Di iterators.
|
||||
// Should test those, too
|
||||
int nth_element (const uint8_t *data, size_t size);
|
||||
int partial_sort (const uint8_t *data, size_t size);
|
||||
int partial_sort_copy (const uint8_t *data, size_t size);
|
||||
|
||||
// Heap operations
|
||||
int make_heap (const uint8_t *data, size_t size);
|
||||
int push_heap (const uint8_t *data, size_t size);
|
||||
int pop_heap (const uint8_t *data, size_t size);
|
||||
|
||||
// Various flavors of regex
|
||||
int regex_ECMAScript (const uint8_t *data, size_t size);
|
||||
int regex_POSIX (const uint8_t *data, size_t size);
|
||||
int regex_extended (const uint8_t *data, size_t size);
|
||||
int regex_awk (const uint8_t *data, size_t size);
|
||||
int regex_grep (const uint8_t *data, size_t size);
|
||||
int regex_egrep (const uint8_t *data, size_t size);
|
||||
|
||||
// Searching
|
||||
int search (const uint8_t *data, size_t size);
|
||||
// int search_boyer_moore (const uint8_t *data, size_t size);
|
||||
// int search_boyer_moore_horspool (const uint8_t *data, size_t size);
|
||||
|
||||
// Set operations
|
||||
// int includes (const uint8_t *data, size_t size);
|
||||
// int set_union (const uint8_t *data, size_t size);
|
||||
// int set_intersection (const uint8_t *data, size_t size);
|
||||
// int set_difference (const uint8_t *data, size_t size);
|
||||
// int set_symmetric_difference (const uint8_t *data, size_t size);
|
||||
// int merge (const uint8_t *data, size_t size);
|
||||
|
||||
} // namespace fuzzing
|
||||
|
||||
#endif // _LIBCPP_FUZZING
|
@ -1,66 +1,274 @@
|
||||
if (NOT LIBCXX_INSTALL_SUPPORT_HEADERS)
|
||||
set(LIBCXX_SUPPORT_HEADER_PATTERN PATTERN "support" EXCLUDE)
|
||||
endif()
|
||||
|
||||
set(LIBCXX_HEADER_PATTERN
|
||||
PATTERN "*"
|
||||
PATTERN "CMakeLists.txt" EXCLUDE
|
||||
PATTERN ".svn" EXCLUDE
|
||||
PATTERN "__config_site.in" EXCLUDE
|
||||
${LIBCXX_SUPPORT_HEADER_PATTERN}
|
||||
set(files
|
||||
__bit_reference
|
||||
__bsd_locale_defaults.h
|
||||
__bsd_locale_fallbacks.h
|
||||
__errc
|
||||
__debug
|
||||
__functional_03
|
||||
__functional_base
|
||||
__functional_base_03
|
||||
__hash_table
|
||||
__libcpp_version
|
||||
__locale
|
||||
__mutex_base
|
||||
__node_handle
|
||||
__nullptr
|
||||
__split_buffer
|
||||
__sso_allocator
|
||||
__std_stream
|
||||
__string
|
||||
__threading_support
|
||||
__tree
|
||||
__tuple
|
||||
__undef_macros
|
||||
algorithm
|
||||
any
|
||||
array
|
||||
atomic
|
||||
bit
|
||||
bitset
|
||||
cassert
|
||||
ccomplex
|
||||
cctype
|
||||
cerrno
|
||||
cfenv
|
||||
cfloat
|
||||
charconv
|
||||
chrono
|
||||
cinttypes
|
||||
ciso646
|
||||
climits
|
||||
clocale
|
||||
cmath
|
||||
codecvt
|
||||
compare
|
||||
complex
|
||||
complex.h
|
||||
condition_variable
|
||||
csetjmp
|
||||
csignal
|
||||
cstdarg
|
||||
cstdbool
|
||||
cstddef
|
||||
cstdint
|
||||
cstdio
|
||||
cstdlib
|
||||
cstring
|
||||
ctgmath
|
||||
ctime
|
||||
ctype.h
|
||||
cwchar
|
||||
cwctype
|
||||
deque
|
||||
errno.h
|
||||
exception
|
||||
execution
|
||||
experimental/__config
|
||||
experimental/__memory
|
||||
experimental/algorithm
|
||||
experimental/coroutine
|
||||
experimental/deque
|
||||
experimental/filesystem
|
||||
experimental/forward_list
|
||||
experimental/functional
|
||||
experimental/iterator
|
||||
experimental/list
|
||||
experimental/map
|
||||
experimental/memory_resource
|
||||
experimental/propagate_const
|
||||
experimental/regex
|
||||
experimental/set
|
||||
experimental/simd
|
||||
experimental/string
|
||||
experimental/type_traits
|
||||
experimental/unordered_map
|
||||
experimental/unordered_set
|
||||
experimental/utility
|
||||
experimental/vector
|
||||
ext/__hash
|
||||
ext/hash_map
|
||||
ext/hash_set
|
||||
fenv.h
|
||||
filesystem
|
||||
float.h
|
||||
forward_list
|
||||
fstream
|
||||
functional
|
||||
future
|
||||
initializer_list
|
||||
inttypes.h
|
||||
iomanip
|
||||
ios
|
||||
iosfwd
|
||||
iostream
|
||||
istream
|
||||
iterator
|
||||
limits
|
||||
limits.h
|
||||
list
|
||||
locale
|
||||
locale.h
|
||||
map
|
||||
math.h
|
||||
memory
|
||||
module.modulemap
|
||||
mutex
|
||||
new
|
||||
numeric
|
||||
optional
|
||||
ostream
|
||||
queue
|
||||
random
|
||||
ratio
|
||||
regex
|
||||
scoped_allocator
|
||||
set
|
||||
setjmp.h
|
||||
shared_mutex
|
||||
span
|
||||
sstream
|
||||
stack
|
||||
stdbool.h
|
||||
stddef.h
|
||||
stdexcept
|
||||
stdint.h
|
||||
stdio.h
|
||||
stdlib.h
|
||||
streambuf
|
||||
string
|
||||
string.h
|
||||
string_view
|
||||
strstream
|
||||
system_error
|
||||
tgmath.h
|
||||
thread
|
||||
tuple
|
||||
type_traits
|
||||
typeindex
|
||||
typeinfo
|
||||
unordered_map
|
||||
unordered_set
|
||||
utility
|
||||
valarray
|
||||
variant
|
||||
vector
|
||||
version
|
||||
wchar.h
|
||||
wctype.h
|
||||
)
|
||||
|
||||
if(NOT LIBCXX_USING_INSTALLED_LLVM AND LLVM_BINARY_DIR)
|
||||
file(COPY .
|
||||
DESTINATION "${LLVM_BINARY_DIR}/include/c++/v1"
|
||||
FILES_MATCHING
|
||||
${LIBCXX_HEADER_PATTERN}
|
||||
if(LIBCXX_INSTALL_SUPPORT_HEADERS)
|
||||
set(files
|
||||
${files}
|
||||
support/android/locale_bionic.h
|
||||
support/fuchsia/xlocale.h
|
||||
support/ibm/limits.h
|
||||
support/ibm/locale_mgmt_aix.h
|
||||
support/ibm/support.h
|
||||
support/ibm/xlocale.h
|
||||
support/musl/xlocale.h
|
||||
support/newlib/xlocale.h
|
||||
support/solaris/floatingpoint.h
|
||||
support/solaris/wchar.h
|
||||
support/solaris/xlocale.h
|
||||
support/win32/limits_msvc_win32.h
|
||||
support/win32/locale_win32.h
|
||||
support/xlocale/__nop_locale_mgmt.h
|
||||
support/xlocale/__posix_l_fallback.h
|
||||
support/xlocale/__strtonum_fallback.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_INSTALL_HEADERS)
|
||||
install(DIRECTORY .
|
||||
DESTINATION include/c++/v1
|
||||
COMPONENT cxx-headers
|
||||
FILES_MATCHING
|
||||
${LIBCXX_HEADER_PATTERN}
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
if (LIBCXX_NEEDS_SITE_CONFIG)
|
||||
# Generate a custom __config header. The new header is created
|
||||
# by prepending __config_site to the current __config header.
|
||||
add_custom_command(OUTPUT ${LIBCXX_BINARY_DIR}/__generated_config
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/cat_files.py
|
||||
${LIBCXX_BINARY_DIR}/__config_site
|
||||
${LIBCXX_SOURCE_DIR}/include/__config
|
||||
-o ${LIBCXX_BINARY_DIR}/__generated_config
|
||||
DEPENDS ${LIBCXX_SOURCE_DIR}/include/__config
|
||||
${LIBCXX_BINARY_DIR}/__config_site
|
||||
)
|
||||
# Add a target that executes the generation commands.
|
||||
add_custom_target(cxx-generated-config ALL
|
||||
DEPENDS ${LIBCXX_BINARY_DIR}/__generated_config)
|
||||
set(generated_config_deps cxx-generated-config)
|
||||
else()
|
||||
set(files
|
||||
${files}
|
||||
__config
|
||||
)
|
||||
endif()
|
||||
|
||||
# In some build configurations (like bootstrapping clang), we need to be able to
|
||||
# install the libcxx headers before the CMake configuration for libcxx runs. Making
|
||||
# the name of this target configurable allows LLVM/runtimes/CMakeLists.txt to
|
||||
# add this subdirectory to the LLVM build to put libcxx's headers in place
|
||||
# before libcxx's build configuration is run.
|
||||
if (NOT CXX_HEADER_TARGET)
|
||||
set(CXX_HEADER_TARGET cxx-headers)
|
||||
endif()
|
||||
if(NOT LIBCXX_USING_INSTALLED_LLVM AND LIBCXX_HEADER_DIR)
|
||||
set(output_dir ${LIBCXX_HEADER_DIR}/include/c++/v1)
|
||||
|
||||
set(out_files)
|
||||
foreach(f ${files})
|
||||
set(src ${CMAKE_CURRENT_SOURCE_DIR}/${f})
|
||||
set(dst ${output_dir}/${f})
|
||||
add_custom_command(OUTPUT ${dst}
|
||||
DEPENDS ${src}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
|
||||
COMMENT "Copying CXX header ${f}")
|
||||
list(APPEND out_files ${dst})
|
||||
endforeach()
|
||||
|
||||
if (LIBCXX_NEEDS_SITE_CONFIG)
|
||||
# Generate and install a custom __config header. The new header is created
|
||||
# by prepending __config_site to the current __config header.
|
||||
add_custom_command(OUTPUT ${LIBCXX_BINARY_DIR}/__generated_config
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/cat_files.py
|
||||
${LIBCXX_BINARY_DIR}/__config_site
|
||||
${LIBCXX_SOURCE_DIR}/include/__config
|
||||
-o ${LIBCXX_BINARY_DIR}/__generated_config
|
||||
DEPENDS ${LIBCXX_SOURCE_DIR}/include/__config
|
||||
${LIBCXX_BINARY_DIR}/__config_site
|
||||
# Copy the generated header as __config into build directory.
|
||||
set(src ${LIBCXX_BINARY_DIR}/__generated_config)
|
||||
set(dst ${output_dir}/__config)
|
||||
add_custom_command(OUTPUT ${dst}
|
||||
DEPENDS ${src} ${generated_config_deps}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
|
||||
COMMENT "Copying CXX __config")
|
||||
list(APPEND out_files ${dst})
|
||||
endif()
|
||||
|
||||
add_custom_target(${CXX_HEADER_TARGET} ALL DEPENDS ${out_files} ${LIBCXX_CXX_ABI_HEADER_TARGET})
|
||||
else()
|
||||
add_custom_target(${CXX_HEADER_TARGET})
|
||||
endif()
|
||||
set_target_properties(${CXX_HEADER_TARGET} PROPERTIES FOLDER "Misc")
|
||||
|
||||
if (LIBCXX_INSTALL_HEADERS)
|
||||
foreach(file ${files})
|
||||
get_filename_component(dir ${file} DIRECTORY)
|
||||
install(FILES ${file}
|
||||
DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dir}
|
||||
COMPONENT ${CXX_HEADER_TARGET}
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
)
|
||||
# Add a target that executes the generation commands.
|
||||
add_custom_target(generate_config_header ALL
|
||||
DEPENDS ${LIBCXX_BINARY_DIR}/__generated_config)
|
||||
set(generated_config_deps generate_config_header)
|
||||
endforeach()
|
||||
|
||||
if (LIBCXX_NEEDS_SITE_CONFIG)
|
||||
# Install the generated header as __config.
|
||||
install(FILES ${LIBCXX_BINARY_DIR}/__generated_config
|
||||
DESTINATION include/c++/v1
|
||||
DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
||||
RENAME __config
|
||||
COMPONENT cxx-headers)
|
||||
COMPONENT ${CXX_HEADER_TARGET})
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES)
|
||||
# this target is just needed as a placeholder for the distribution target
|
||||
add_custom_target(cxx-headers)
|
||||
add_custom_target(install-cxx-headers
|
||||
DEPENDS cxx-headers ${generated_config_deps}
|
||||
add_custom_target(install-${CXX_HEADER_TARGET}
|
||||
DEPENDS ${CXX_HEADER_TARGET} ${generated_config_deps}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=cxx-headers
|
||||
-DCMAKE_INSTALL_COMPONENT=${CXX_HEADER_TARGET}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
# Stripping is a no-op for headers
|
||||
add_custom_target(install-${CXX_HEADER_TARGET}-stripped DEPENDS install-${CXX_HEADER_TARGET})
|
||||
|
||||
add_custom_target(libcxx-headers)
|
||||
add_custom_target(install-libcxx-headers DEPENDS install-cxx-headers)
|
||||
add_custom_target(install-libcxx-headers DEPENDS install-${CXX_HEADER_TARGET})
|
||||
add_custom_target(install-libcxx-headers-stripped DEPENDS install-${CXX_HEADER_TARGET}-stripped)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -12,14 +11,17 @@
|
||||
#define _LIBCPP___BIT_REFERENCE
|
||||
|
||||
#include <__config>
|
||||
#include <bit>
|
||||
#include <algorithm>
|
||||
|
||||
#include <__undef_min_max>
|
||||
|
||||
#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 _Cp, bool _IsConst, typename _Cp::__storage_type = 0> class __bit_iterator;
|
||||
@ -66,7 +68,7 @@ public:
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void flip() _NOEXCEPT {*__seg_ ^= __mask_;}
|
||||
_LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, false> operator&() const _NOEXCEPT
|
||||
{return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(__ctz(__mask_)));}
|
||||
{return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(__libcpp_ctz(__mask_)));}
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
|
||||
@ -138,7 +140,7 @@ public:
|
||||
{return static_cast<bool>(*__seg_ & __mask_);}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, true> operator&() const _NOEXCEPT
|
||||
{return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(__ctz(__mask_)));}
|
||||
{return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(__libcpp_ctz(__mask_)));}
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR
|
||||
@ -165,7 +167,7 @@ __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
if (__n == __dn)
|
||||
return __first + __n;
|
||||
__n -= __dn;
|
||||
@ -174,14 +176,14 @@ __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
||||
// do middle whole words
|
||||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
|
||||
if (*__first.__seg_)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(*__first.__seg_)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(*__first.__seg_)));
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
{
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
}
|
||||
return _It(__first.__seg_, static_cast<unsigned>(__n));
|
||||
}
|
||||
@ -201,7 +203,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b = ~*__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
if (__n == __dn)
|
||||
return __first + __n;
|
||||
__n -= __dn;
|
||||
@ -212,7 +214,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
||||
{
|
||||
__storage_type __b = ~*__first.__seg_;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
}
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
@ -220,7 +222,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b = ~*__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
}
|
||||
return _It(__first.__seg_, static_cast<unsigned>(__n));
|
||||
}
|
||||
@ -252,18 +254,18 @@ __count_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
||||
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
|
||||
__storage_type __dn = _VSTD::min(__clz_f, __n);
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__r = _VSTD::__pop_count(*__first.__seg_ & __m);
|
||||
__r = _VSTD::__libcpp_popcount(*__first.__seg_ & __m);
|
||||
__n -= __dn;
|
||||
++__first.__seg_;
|
||||
}
|
||||
// do middle whole words
|
||||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
|
||||
__r += _VSTD::__pop_count(*__first.__seg_);
|
||||
__r += _VSTD::__libcpp_popcount(*__first.__seg_);
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
{
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__r += _VSTD::__pop_count(*__first.__seg_ & __m);
|
||||
__r += _VSTD::__libcpp_popcount(*__first.__seg_ & __m);
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
@ -283,18 +285,18 @@ __count_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_typ
|
||||
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
|
||||
__storage_type __dn = _VSTD::min(__clz_f, __n);
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__r = _VSTD::__pop_count(~*__first.__seg_ & __m);
|
||||
__r = _VSTD::__libcpp_popcount(~*__first.__seg_ & __m);
|
||||
__n -= __dn;
|
||||
++__first.__seg_;
|
||||
}
|
||||
// do middle whole words
|
||||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
|
||||
__r += _VSTD::__pop_count(~*__first.__seg_);
|
||||
__r += _VSTD::__libcpp_popcount(~*__first.__seg_);
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
{
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__r += _VSTD::__pop_count(~*__first.__seg_ & __m);
|
||||
__r += _VSTD::__libcpp_popcount(~*__first.__seg_ & __m);
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
@ -1273,4 +1275,6 @@ private:
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___BIT_REFERENCE
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------- __bsd_locale_defaults.h -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// The BSDs have lots of *_l functions. We don't want to define those symbols
|
||||
@ -15,6 +14,10 @@
|
||||
#ifndef _LIBCPP_BSD_LOCALE_DEFAULTS_H
|
||||
#define _LIBCPP_BSD_LOCALE_DEFAULTS_H
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#define __libcpp_mb_cur_max_l(loc) MB_CUR_MAX_L(loc)
|
||||
#define __libcpp_btowc_l(ch, loc) btowc_l(ch, loc)
|
||||
#define __libcpp_wctob_l(wch, loc) wctob_l(wch, loc)
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------- __bsd_locale_fallbacks.h ----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// The BSDs have lots of *_l functions. This file provides reimplementations
|
||||
@ -15,91 +14,93 @@
|
||||
#define _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <memory>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
typedef _VSTD::remove_pointer<locale_t>::type __use_locale_struct;
|
||||
typedef _VSTD::unique_ptr<__use_locale_struct, decltype(&uselocale)> __locale_raii;
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return MB_CUR_MAX;
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
wint_t __libcpp_btowc_l(int __c, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return btowc(__c);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_wctob_l(wint_t __c, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return wctob(__c);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
|
||||
size_t __len, mbstate_t *__ps, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return wcrtomb(__s, __wc, __ps);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
|
||||
size_t __len, mbstate_t *__ps, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
|
||||
mbstate_t *__ps, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return mbrtowc(__pwc, __s, __n, __ps);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return mbtowc(__pwc, __pmb, __max);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return mbrlen(__s, __n, __ps);
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
lconv *__libcpp_localeconv_l(locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return localeconv();
|
||||
}
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
|
||||
mbstate_t *__ps, locale_t __l)
|
||||
{
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return mbsrtowcs(__dest, __src, __len, __ps);
|
||||
}
|
||||
|
||||
@ -107,7 +108,7 @@ inline
|
||||
int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
|
||||
va_list __va;
|
||||
va_start(__va, __format);
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
int __res = vsnprintf(__s, __n, __format, __va);
|
||||
va_end(__va);
|
||||
return __res;
|
||||
@ -117,7 +118,7 @@ inline
|
||||
int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
|
||||
va_list __va;
|
||||
va_start(__va, __format);
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
int __res = vasprintf(__s, __format, __va);
|
||||
va_end(__va);
|
||||
return __res;
|
||||
@ -127,7 +128,7 @@ inline
|
||||
int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
|
||||
va_list __va;
|
||||
va_start(__va, __format);
|
||||
__locale_raii __current( uselocale(__l), uselocale );
|
||||
__libcpp_locale_guard __current(__l);
|
||||
int __res = vsscanf(__s, __format, __va);
|
||||
va_end(__va);
|
||||
return __res;
|
||||
|
1425
include/__config
1425
include/__config
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -12,6 +11,9 @@
|
||||
|
||||
#cmakedefine _LIBCPP_ABI_VERSION @_LIBCPP_ABI_VERSION@
|
||||
#cmakedefine _LIBCPP_ABI_UNSTABLE
|
||||
#cmakedefine _LIBCPP_ABI_FORCE_ITANIUM
|
||||
#cmakedefine _LIBCPP_ABI_FORCE_MICROSOFT
|
||||
#cmakedefine _LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT
|
||||
#cmakedefine _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
|
||||
#cmakedefine _LIBCPP_HAS_NO_STDIN
|
||||
#cmakedefine _LIBCPP_HAS_NO_STDOUT
|
||||
@ -21,7 +23,14 @@
|
||||
#cmakedefine _LIBCPP_HAS_MUSL_LIBC
|
||||
#cmakedefine _LIBCPP_HAS_THREAD_API_PTHREAD
|
||||
#cmakedefine _LIBCPP_HAS_THREAD_API_EXTERNAL
|
||||
#cmakedefine _LIBCPP_HAS_THREAD_API_WIN32
|
||||
#cmakedefine _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL
|
||||
#cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS
|
||||
#cmakedefine _LIBCPP_NO_VCRUNTIME
|
||||
#cmakedefine01 _LIBCPP_HAS_MERGED_TYPEINFO_NAMES_DEFAULT
|
||||
#cmakedefine _LIBCPP_ABI_NAMESPACE @_LIBCPP_ABI_NAMESPACE@
|
||||
#cmakedefine _LIBCPP_HAS_PARALLEL_ALGORITHMS
|
||||
|
||||
@_LIBCPP_ABI_DEFINES@
|
||||
|
||||
#endif // _LIBCPP_CONFIG_SITE
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- __debug ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -12,6 +11,7 @@
|
||||
#define _LIBCPP_DEBUG_H
|
||||
|
||||
#include <__config>
|
||||
#include <iosfwd>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -25,7 +25,6 @@
|
||||
# include <cstdlib>
|
||||
# include <cstdio>
|
||||
# include <cstddef>
|
||||
# include <exception>
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 1 && !defined(_LIBCPP_ASSERT)
|
||||
@ -50,10 +49,6 @@
|
||||
#define _LIBCPP_DEBUG_MODE(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_DEBUG_LEVEL < 1
|
||||
class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception;
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
|
||||
@ -63,6 +58,9 @@ struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
__libcpp_debug_info(const char* __f, int __l, const char* __p, const char* __m)
|
||||
: __file_(__f), __line_(__l), __pred_(__p), __msg_(__m) {}
|
||||
|
||||
_LIBCPP_FUNC_VIS std::string what() const;
|
||||
|
||||
const char* __file_;
|
||||
int __line_;
|
||||
const char* __pred_;
|
||||
@ -74,44 +72,17 @@ typedef void(*__libcpp_debug_function_type)(__libcpp_debug_info const&);
|
||||
|
||||
/// __libcpp_debug_function - The handler function called when a _LIBCPP_ASSERT
|
||||
/// fails.
|
||||
extern _LIBCPP_EXTERN_VIS __libcpp_debug_function_type __libcpp_debug_function;
|
||||
extern _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_function_type __libcpp_debug_function;
|
||||
|
||||
/// __libcpp_abort_debug_function - A debug handler that aborts when called.
|
||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS
|
||||
void __libcpp_abort_debug_function(__libcpp_debug_info const&);
|
||||
|
||||
/// __libcpp_throw_debug_function - A debug handler that throws
|
||||
/// an instance of __libcpp_debug_exception when called.
|
||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS
|
||||
void __libcpp_throw_debug_function(__libcpp_debug_info const&);
|
||||
|
||||
/// __libcpp_set_debug_function - Set the debug handler to the specified
|
||||
/// function.
|
||||
_LIBCPP_FUNC_VIS
|
||||
bool __libcpp_set_debug_function(__libcpp_debug_function_type __func);
|
||||
|
||||
// Setup the throwing debug handler during dynamic initialization.
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 1 && defined(_LIBCPP_DEBUG_USE_EXCEPTIONS)
|
||||
# if defined(_LIBCPP_NO_EXCEPTIONS)
|
||||
# error _LIBCPP_DEBUG_USE_EXCEPTIONS cannot be used when exceptions are disabled.
|
||||
# endif
|
||||
static bool __init_dummy = __libcpp_set_debug_function(__libcpp_throw_debug_function);
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 1 || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
class _LIBCPP_EXCEPTION_ABI __libcpp_debug_exception : public exception {
|
||||
public:
|
||||
__libcpp_debug_exception() _NOEXCEPT;
|
||||
explicit __libcpp_debug_exception(__libcpp_debug_info const& __i);
|
||||
__libcpp_debug_exception(__libcpp_debug_exception const&);
|
||||
~__libcpp_debug_exception() _NOEXCEPT;
|
||||
const char* what() const _NOEXCEPT;
|
||||
private:
|
||||
struct __libcpp_debug_exception_imp;
|
||||
__libcpp_debug_exception_imp *__imp_;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2 || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
|
||||
struct _LIBCPP_TYPE_VIS __c_node;
|
||||
@ -251,16 +222,22 @@ public:
|
||||
__db_c_const_iterator __c_end() const;
|
||||
__db_i_const_iterator __i_end() const;
|
||||
|
||||
typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*);
|
||||
|
||||
template <class _Cont>
|
||||
_LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) {
|
||||
return ::new(__mem) _C_node<_Cont>(__c, __next);
|
||||
}
|
||||
|
||||
template <class _Cont>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __insert_c(_Cont* __c)
|
||||
{
|
||||
__c_node* __n = __insert_c(static_cast<void*>(__c));
|
||||
::new(__n) _C_node<_Cont>(__n->__c_, __n->__next_);
|
||||
__insert_c(static_cast<void*>(__c), &__create_C_node<_Cont>);
|
||||
}
|
||||
|
||||
void __insert_i(void* __i);
|
||||
__c_node* __insert_c(void* __c);
|
||||
void __insert_c(void* __c, _InsertConstruct* __fn);
|
||||
void __erase_c(void* __c);
|
||||
|
||||
void __insert_ic(void* __i, const void* __c);
|
||||
|
217
include/__errc
Normal file
217
include/__errc
Normal file
@ -0,0 +1,217 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------------- __errc ----------------------------------===//
|
||||
//
|
||||
// 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___ERRC
|
||||
#define _LIBCPP___ERRC
|
||||
|
||||
/*
|
||||
system_error synopsis
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
enum class errc
|
||||
{
|
||||
address_family_not_supported, // EAFNOSUPPORT
|
||||
address_in_use, // EADDRINUSE
|
||||
address_not_available, // EADDRNOTAVAIL
|
||||
already_connected, // EISCONN
|
||||
argument_list_too_long, // E2BIG
|
||||
argument_out_of_domain, // EDOM
|
||||
bad_address, // EFAULT
|
||||
bad_file_descriptor, // EBADF
|
||||
bad_message, // EBADMSG
|
||||
broken_pipe, // EPIPE
|
||||
connection_aborted, // ECONNABORTED
|
||||
connection_already_in_progress, // EALREADY
|
||||
connection_refused, // ECONNREFUSED
|
||||
connection_reset, // ECONNRESET
|
||||
cross_device_link, // EXDEV
|
||||
destination_address_required, // EDESTADDRREQ
|
||||
device_or_resource_busy, // EBUSY
|
||||
directory_not_empty, // ENOTEMPTY
|
||||
executable_format_error, // ENOEXEC
|
||||
file_exists, // EEXIST
|
||||
file_too_large, // EFBIG
|
||||
filename_too_long, // ENAMETOOLONG
|
||||
function_not_supported, // ENOSYS
|
||||
host_unreachable, // EHOSTUNREACH
|
||||
identifier_removed, // EIDRM
|
||||
illegal_byte_sequence, // EILSEQ
|
||||
inappropriate_io_control_operation, // ENOTTY
|
||||
interrupted, // EINTR
|
||||
invalid_argument, // EINVAL
|
||||
invalid_seek, // ESPIPE
|
||||
io_error, // EIO
|
||||
is_a_directory, // EISDIR
|
||||
message_size, // EMSGSIZE
|
||||
network_down, // ENETDOWN
|
||||
network_reset, // ENETRESET
|
||||
network_unreachable, // ENETUNREACH
|
||||
no_buffer_space, // ENOBUFS
|
||||
no_child_process, // ECHILD
|
||||
no_link, // ENOLINK
|
||||
no_lock_available, // ENOLCK
|
||||
no_message_available, // ENODATA
|
||||
no_message, // ENOMSG
|
||||
no_protocol_option, // ENOPROTOOPT
|
||||
no_space_on_device, // ENOSPC
|
||||
no_stream_resources, // ENOSR
|
||||
no_such_device_or_address, // ENXIO
|
||||
no_such_device, // ENODEV
|
||||
no_such_file_or_directory, // ENOENT
|
||||
no_such_process, // ESRCH
|
||||
not_a_directory, // ENOTDIR
|
||||
not_a_socket, // ENOTSOCK
|
||||
not_a_stream, // ENOSTR
|
||||
not_connected, // ENOTCONN
|
||||
not_enough_memory, // ENOMEM
|
||||
not_supported, // ENOTSUP
|
||||
operation_canceled, // ECANCELED
|
||||
operation_in_progress, // EINPROGRESS
|
||||
operation_not_permitted, // EPERM
|
||||
operation_not_supported, // EOPNOTSUPP
|
||||
operation_would_block, // EWOULDBLOCK
|
||||
owner_dead, // EOWNERDEAD
|
||||
permission_denied, // EACCES
|
||||
protocol_error, // EPROTO
|
||||
protocol_not_supported, // EPROTONOSUPPORT
|
||||
read_only_file_system, // EROFS
|
||||
resource_deadlock_would_occur, // EDEADLK
|
||||
resource_unavailable_try_again, // EAGAIN
|
||||
result_out_of_range, // ERANGE
|
||||
state_not_recoverable, // ENOTRECOVERABLE
|
||||
stream_timeout, // ETIME
|
||||
text_file_busy, // ETXTBSY
|
||||
timed_out, // ETIMEDOUT
|
||||
too_many_files_open_in_system, // ENFILE
|
||||
too_many_files_open, // EMFILE
|
||||
too_many_links, // EMLINK
|
||||
too_many_symbolic_link_levels, // ELOOP
|
||||
value_too_large, // EOVERFLOW
|
||||
wrong_protocol_type // EPROTOTYPE
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <cerrno>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// Some error codes are not present on all platforms, so we provide equivalents
|
||||
// for them:
|
||||
|
||||
//enum class errc
|
||||
_LIBCPP_DECLARE_STRONG_ENUM(errc)
|
||||
{
|
||||
address_family_not_supported = EAFNOSUPPORT,
|
||||
address_in_use = EADDRINUSE,
|
||||
address_not_available = EADDRNOTAVAIL,
|
||||
already_connected = EISCONN,
|
||||
argument_list_too_long = E2BIG,
|
||||
argument_out_of_domain = EDOM,
|
||||
bad_address = EFAULT,
|
||||
bad_file_descriptor = EBADF,
|
||||
bad_message = EBADMSG,
|
||||
broken_pipe = EPIPE,
|
||||
connection_aborted = ECONNABORTED,
|
||||
connection_already_in_progress = EALREADY,
|
||||
connection_refused = ECONNREFUSED,
|
||||
connection_reset = ECONNRESET,
|
||||
cross_device_link = EXDEV,
|
||||
destination_address_required = EDESTADDRREQ,
|
||||
device_or_resource_busy = EBUSY,
|
||||
directory_not_empty = ENOTEMPTY,
|
||||
executable_format_error = ENOEXEC,
|
||||
file_exists = EEXIST,
|
||||
file_too_large = EFBIG,
|
||||
filename_too_long = ENAMETOOLONG,
|
||||
function_not_supported = ENOSYS,
|
||||
host_unreachable = EHOSTUNREACH,
|
||||
identifier_removed = EIDRM,
|
||||
illegal_byte_sequence = EILSEQ,
|
||||
inappropriate_io_control_operation = ENOTTY,
|
||||
interrupted = EINTR,
|
||||
invalid_argument = EINVAL,
|
||||
invalid_seek = ESPIPE,
|
||||
io_error = EIO,
|
||||
is_a_directory = EISDIR,
|
||||
message_size = EMSGSIZE,
|
||||
network_down = ENETDOWN,
|
||||
network_reset = ENETRESET,
|
||||
network_unreachable = ENETUNREACH,
|
||||
no_buffer_space = ENOBUFS,
|
||||
no_child_process = ECHILD,
|
||||
no_link = ENOLINK,
|
||||
no_lock_available = ENOLCK,
|
||||
#ifdef ENODATA
|
||||
no_message_available = ENODATA,
|
||||
#else
|
||||
no_message_available = ENOMSG,
|
||||
#endif
|
||||
no_message = ENOMSG,
|
||||
no_protocol_option = ENOPROTOOPT,
|
||||
no_space_on_device = ENOSPC,
|
||||
#ifdef ENOSR
|
||||
no_stream_resources = ENOSR,
|
||||
#else
|
||||
no_stream_resources = ENOMEM,
|
||||
#endif
|
||||
no_such_device_or_address = ENXIO,
|
||||
no_such_device = ENODEV,
|
||||
no_such_file_or_directory = ENOENT,
|
||||
no_such_process = ESRCH,
|
||||
not_a_directory = ENOTDIR,
|
||||
not_a_socket = ENOTSOCK,
|
||||
#ifdef ENOSTR
|
||||
not_a_stream = ENOSTR,
|
||||
#else
|
||||
not_a_stream = EINVAL,
|
||||
#endif
|
||||
not_connected = ENOTCONN,
|
||||
not_enough_memory = ENOMEM,
|
||||
not_supported = ENOTSUP,
|
||||
operation_canceled = ECANCELED,
|
||||
operation_in_progress = EINPROGRESS,
|
||||
operation_not_permitted = EPERM,
|
||||
operation_not_supported = EOPNOTSUPP,
|
||||
operation_would_block = EWOULDBLOCK,
|
||||
owner_dead = EOWNERDEAD,
|
||||
permission_denied = EACCES,
|
||||
protocol_error = EPROTO,
|
||||
protocol_not_supported = EPROTONOSUPPORT,
|
||||
read_only_file_system = EROFS,
|
||||
resource_deadlock_would_occur = EDEADLK,
|
||||
resource_unavailable_try_again = EAGAIN,
|
||||
result_out_of_range = ERANGE,
|
||||
state_not_recoverable = ENOTRECOVERABLE,
|
||||
#ifdef ETIME
|
||||
stream_timeout = ETIME,
|
||||
#else
|
||||
stream_timeout = ETIMEDOUT,
|
||||
#endif
|
||||
text_file_busy = ETXTBSY,
|
||||
timed_out = ETIMEDOUT,
|
||||
too_many_files_open_in_system = ENFILE,
|
||||
too_many_files_open = EMFILE,
|
||||
too_many_links = EMLINK,
|
||||
too_many_symbolic_link_levels = ELOOP,
|
||||
value_too_large = EOVERFLOW,
|
||||
wrong_protocol_type = EPROTOTYPE
|
||||
};
|
||||
_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(errc)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___ERRC
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -600,7 +599,10 @@ template<class _Rp>
|
||||
function<_Rp()>&
|
||||
function<_Rp()>::operator=(const function& __f)
|
||||
{
|
||||
function(__f).swap(*this);
|
||||
if (__f)
|
||||
function(__f).swap(*this);
|
||||
else
|
||||
*this = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -608,11 +610,12 @@ template<class _Rp>
|
||||
function<_Rp()>&
|
||||
function<_Rp()>::operator=(nullptr_t)
|
||||
{
|
||||
if (__f_ == (__base*)&__buf_)
|
||||
__f_->destroy();
|
||||
else if (__f_)
|
||||
__f_->destroy_deallocate();
|
||||
__base* __t = __f_;
|
||||
__f_ = 0;
|
||||
if (__t == (__base*)&__buf_)
|
||||
__t->destroy();
|
||||
else if (__t)
|
||||
__t->destroy_deallocate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -704,7 +707,7 @@ function<_Rp()>::target()
|
||||
{
|
||||
if (__f_ == 0)
|
||||
return (_Tp*)0;
|
||||
return (_Tp*)__f_->target(typeid(_Tp));
|
||||
return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
|
||||
}
|
||||
|
||||
template<class _Rp>
|
||||
@ -876,7 +879,10 @@ template<class _Rp, class _A0>
|
||||
function<_Rp(_A0)>&
|
||||
function<_Rp(_A0)>::operator=(const function& __f)
|
||||
{
|
||||
function(__f).swap(*this);
|
||||
if (__f)
|
||||
function(__f).swap(*this);
|
||||
else
|
||||
*this = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -884,11 +890,12 @@ template<class _Rp, class _A0>
|
||||
function<_Rp(_A0)>&
|
||||
function<_Rp(_A0)>::operator=(nullptr_t)
|
||||
{
|
||||
if (__f_ == (__base*)&__buf_)
|
||||
__f_->destroy();
|
||||
else if (__f_)
|
||||
__f_->destroy_deallocate();
|
||||
__base* __t = __f_;
|
||||
__f_ = 0;
|
||||
if (__t == (__base*)&__buf_)
|
||||
__t->destroy();
|
||||
else if (__t)
|
||||
__t->destroy_deallocate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -980,7 +987,7 @@ function<_Rp(_A0)>::target()
|
||||
{
|
||||
if (__f_ == 0)
|
||||
return (_Tp*)0;
|
||||
return (_Tp*)__f_->target(typeid(_Tp));
|
||||
return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
|
||||
}
|
||||
|
||||
template<class _Rp, class _A0>
|
||||
@ -1152,7 +1159,10 @@ template<class _Rp, class _A0, class _A1>
|
||||
function<_Rp(_A0, _A1)>&
|
||||
function<_Rp(_A0, _A1)>::operator=(const function& __f)
|
||||
{
|
||||
function(__f).swap(*this);
|
||||
if (__f)
|
||||
function(__f).swap(*this);
|
||||
else
|
||||
*this = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1160,11 +1170,12 @@ template<class _Rp, class _A0, class _A1>
|
||||
function<_Rp(_A0, _A1)>&
|
||||
function<_Rp(_A0, _A1)>::operator=(nullptr_t)
|
||||
{
|
||||
if (__f_ == (__base*)&__buf_)
|
||||
__f_->destroy();
|
||||
else if (__f_)
|
||||
__f_->destroy_deallocate();
|
||||
__base* __t = __f_;
|
||||
__f_ = 0;
|
||||
if (__t == (__base*)&__buf_)
|
||||
__t->destroy();
|
||||
else if (__t)
|
||||
__t->destroy_deallocate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1256,7 +1267,7 @@ function<_Rp(_A0, _A1)>::target()
|
||||
{
|
||||
if (__f_ == 0)
|
||||
return (_Tp*)0;
|
||||
return (_Tp*)__f_->target(typeid(_Tp));
|
||||
return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
|
||||
}
|
||||
|
||||
template<class _Rp, class _A0, class _A1>
|
||||
@ -1428,7 +1439,10 @@ template<class _Rp, class _A0, class _A1, class _A2>
|
||||
function<_Rp(_A0, _A1, _A2)>&
|
||||
function<_Rp(_A0, _A1, _A2)>::operator=(const function& __f)
|
||||
{
|
||||
function(__f).swap(*this);
|
||||
if (__f)
|
||||
function(__f).swap(*this);
|
||||
else
|
||||
*this = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1436,11 +1450,12 @@ template<class _Rp, class _A0, class _A1, class _A2>
|
||||
function<_Rp(_A0, _A1, _A2)>&
|
||||
function<_Rp(_A0, _A1, _A2)>::operator=(nullptr_t)
|
||||
{
|
||||
if (__f_ == (__base*)&__buf_)
|
||||
__f_->destroy();
|
||||
else if (__f_)
|
||||
__f_->destroy_deallocate();
|
||||
__base* __t = __f_;
|
||||
__f_ = 0;
|
||||
if (__t == (__base*)&__buf_)
|
||||
__t->destroy();
|
||||
else if (__t)
|
||||
__t->destroy_deallocate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1532,7 +1547,7 @@ function<_Rp(_A0, _A1, _A2)>::target()
|
||||
{
|
||||
if (__f_ == 0)
|
||||
return (_Tp*)0;
|
||||
return (_Tp*)__f_->target(typeid(_Tp));
|
||||
return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp)));
|
||||
}
|
||||
|
||||
template<class _Rp, class _A0, class _A1, class _A2>
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -50,7 +49,7 @@ template <class _Tp>
|
||||
#endif
|
||||
struct _LIBCPP_TEMPLATE_VIS less : binary_function<_Tp, _Tp, bool>
|
||||
{
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator()(const _Tp& __x, const _Tp& __y) const
|
||||
{return __x < __y;}
|
||||
};
|
||||
@ -59,7 +58,7 @@ struct _LIBCPP_TEMPLATE_VIS less : binary_function<_Tp, _Tp, bool>
|
||||
template <>
|
||||
struct _LIBCPP_TEMPLATE_VIS less<void>
|
||||
{
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2>
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
|
||||
auto operator()(_T1&& __t, _T2&& __u) const
|
||||
_NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)))
|
||||
@ -126,7 +125,7 @@ struct __weak_result_type_imp // bool is true
|
||||
: public __maybe_derive_from_unary_function<_Tp>,
|
||||
public __maybe_derive_from_binary_function<_Tp>
|
||||
{
|
||||
typedef typename _Tp::result_type result_type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE typename _Tp::result_type result_type;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
@ -147,19 +146,19 @@ struct __weak_result_type
|
||||
template <class _Rp>
|
||||
struct __weak_result_type<_Rp ()>
|
||||
{
|
||||
typedef _Rp result_type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE _Rp result_type;
|
||||
};
|
||||
|
||||
template <class _Rp>
|
||||
struct __weak_result_type<_Rp (&)()>
|
||||
{
|
||||
typedef _Rp result_type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE _Rp result_type;
|
||||
};
|
||||
|
||||
template <class _Rp>
|
||||
struct __weak_result_type<_Rp (*)()>
|
||||
{
|
||||
typedef _Rp result_type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE _Rp result_type;
|
||||
};
|
||||
|
||||
// 1 argument case
|
||||
@ -251,7 +250,7 @@ struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile>
|
||||
};
|
||||
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
// 3 or more arguments
|
||||
|
||||
template <class _Rp, class _A1, class _A2, class _A3, class ..._A4>
|
||||
@ -296,10 +295,6 @@ struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile>
|
||||
typedef _Rp result_type;
|
||||
};
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class ..._Args>
|
||||
struct __invoke_return
|
||||
{
|
||||
@ -316,7 +311,7 @@ struct __invoke_return
|
||||
template <class _Ret>
|
||||
struct __invoke_void_return_wrapper
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class ..._Args>
|
||||
static _Ret __call(_Args&&... __args) {
|
||||
return __invoke(_VSTD::forward<_Args>(__args)...);
|
||||
@ -347,7 +342,7 @@ struct __invoke_void_return_wrapper
|
||||
template <>
|
||||
struct __invoke_void_return_wrapper<void>
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class ..._Args>
|
||||
static void __call(_Args&&... __args) {
|
||||
__invoke(_VSTD::forward<_Args>(__args)...);
|
||||
@ -389,7 +384,7 @@ public:
|
||||
// construct/copy/destroy
|
||||
_LIBCPP_INLINE_VISIBILITY reference_wrapper(type& __f) _NOEXCEPT
|
||||
: __f_(_VSTD::addressof(__f)) {}
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
private: reference_wrapper(type&&); public: // = delete; // do not bind to temps
|
||||
#endif
|
||||
|
||||
@ -397,7 +392,7 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY operator type& () const _NOEXCEPT {return *__f_;}
|
||||
_LIBCPP_INLINE_VISIBILITY type& get() const _NOEXCEPT {return *__f_;}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
// invoke
|
||||
template <class... _ArgTypes>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -510,7 +505,7 @@ public:
|
||||
operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const {
|
||||
return __invoke(get(), __a0, __a1, __a2);
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
};
|
||||
|
||||
|
||||
@ -552,26 +547,23 @@ template <class _Tp> void cref(const _Tp&&) = delete;
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
template <class _Tp1, class _Tp2 = void>
|
||||
struct __is_transparent
|
||||
{
|
||||
private:
|
||||
struct __two {char __lx; char __lxx;};
|
||||
template <class _Up> static __two __test(...);
|
||||
template <class _Up> static char __test(typename _Up::is_transparent* = 0);
|
||||
public:
|
||||
static const bool value = sizeof(__test<_Tp1>(0)) == 1;
|
||||
};
|
||||
template <class _Tp, class, class = void>
|
||||
struct __is_transparent : false_type {};
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
struct __is_transparent<_Tp, _Up,
|
||||
typename __void_t<typename _Tp::is_transparent>::type>
|
||||
: true_type {};
|
||||
#endif
|
||||
|
||||
// allocator_arg_t
|
||||
|
||||
struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { };
|
||||
struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { explicit allocator_arg_t() = default; };
|
||||
|
||||
#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MEMORY)
|
||||
extern const allocator_arg_t allocator_arg;
|
||||
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg;
|
||||
#else
|
||||
constexpr allocator_arg_t allocator_arg = allocator_arg_t();
|
||||
/* _LIBCPP_INLINE_VAR */ constexpr allocator_arg_t allocator_arg = allocator_arg_t();
|
||||
#endif
|
||||
|
||||
// uses_allocator
|
||||
@ -608,17 +600,17 @@ struct _LIBCPP_TEMPLATE_VIS uses_allocator
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _Tp, class _Alloc>
|
||||
constexpr size_t uses_allocator_v = uses_allocator<_Tp, _Alloc>::value;
|
||||
_LIBCPP_INLINE_VAR constexpr size_t uses_allocator_v = uses_allocator<_Tp, _Alloc>::value;
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
// allocator construction
|
||||
|
||||
template <class _Tp, class _Alloc, class ..._Args>
|
||||
struct __uses_alloc_ctor_imp
|
||||
{
|
||||
typedef typename __uncvref<_Alloc>::type _RawAlloc;
|
||||
typedef _LIBCPP_NODEBUG_TYPE typename __uncvref<_Alloc>::type _RawAlloc;
|
||||
static const bool __ua = uses_allocator<_Tp, _RawAlloc>::value;
|
||||
static const bool __ic =
|
||||
is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value;
|
||||
@ -653,17 +645,7 @@ void __user_alloc_construct_impl (integral_constant<int, 2>, _Tp *__storage, con
|
||||
new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a);
|
||||
}
|
||||
|
||||
// FIXME: Theis should have a version which takes a non-const alloc.
|
||||
template <class _Tp, class _Allocator, class... _Args>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __user_alloc_construct (_Tp *__storage, const _Allocator &__a, _Args &&... __args)
|
||||
{
|
||||
__user_alloc_construct_impl(
|
||||
__uses_alloc_ctor<_Tp, _Allocator>(),
|
||||
__storage, __a, _VSTD::forward<_Args>(__args)...
|
||||
);
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -20,33 +19,20 @@
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include <__undef_min_max>
|
||||
|
||||
#include <__debug>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Key, class _Tp>
|
||||
union __hash_value_type;
|
||||
#else
|
||||
template <class _Key, class _Tp>
|
||||
struct __hash_value_type;
|
||||
#endif
|
||||
|
||||
template <class _Key, class _Cp, class _Hash,
|
||||
bool = is_empty<_Hash>::value && !__libcpp_is_final<_Hash>::value>
|
||||
class __unordered_map_hasher;
|
||||
|
||||
template <class _Key, class _Cp, class _Pred,
|
||||
bool = is_empty<_Pred>::value && !__libcpp_is_final<_Pred>::value
|
||||
>
|
||||
class __unordered_map_equal;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Tp>
|
||||
@ -136,7 +122,7 @@ inline _LIBCPP_INLINE_VISIBILITY
|
||||
size_t
|
||||
__next_hash_pow2(size_t __n)
|
||||
{
|
||||
return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
|
||||
return __n < 2 ? __n : (size_t(1) << (std::numeric_limits<size_t>::digits - __libcpp_clz(__n-1)));
|
||||
}
|
||||
|
||||
|
||||
@ -171,7 +157,7 @@ struct __hash_key_value_types {
|
||||
}
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v);
|
||||
}
|
||||
#endif
|
||||
@ -183,7 +169,6 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
|
||||
typedef _Tp mapped_type;
|
||||
typedef __hash_value_type<_Key, _Tp> __node_value_type;
|
||||
typedef pair<const _Key, _Tp> __container_value_type;
|
||||
typedef pair<_Key, _Tp> __nc_value_type;
|
||||
typedef __container_value_type __map_value_type;
|
||||
static const bool __is_map = true;
|
||||
|
||||
@ -197,7 +182,7 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
|
||||
static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value,
|
||||
__container_value_type const&>::type
|
||||
__get_value(_Up& __t) {
|
||||
return __t.__cc;
|
||||
return __t.__get_value();
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
@ -210,12 +195,12 @@ struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type* __get_ptr(__node_value_type& __n) {
|
||||
return _VSTD::addressof(__n.__cc);
|
||||
return _VSTD::addressof(__n.__get_value());
|
||||
}
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __nc_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v.__nc);
|
||||
static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) {
|
||||
return __v.__move();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -423,7 +408,7 @@ public:
|
||||
_LIBCPP_DEBUG_MODE(__get_db()->__insert_i(this));
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
|
||||
: __node_(__x.__node_)
|
||||
{
|
||||
@ -798,8 +783,7 @@ public:
|
||||
_NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
|
||||
: __data_(__size, __a) {}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__bucket_list_deallocator(__bucket_list_deallocator&& __x)
|
||||
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
|
||||
@ -807,8 +791,7 @@ public:
|
||||
{
|
||||
__x.size() = 0;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_type& size() _NOEXCEPT {return __data_.first();}
|
||||
@ -866,36 +849,44 @@ public:
|
||||
template <class> friend class __hash_map_node_destructor;
|
||||
};
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _NodeType, class _Alloc>
|
||||
struct __generic_container_node_destructor;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Key, class _Hash, class _Equal, class _Alloc>
|
||||
struct __diagnose_hash_table_helper {
|
||||
static constexpr bool __trigger_diagnostics()
|
||||
_LIBCPP_DIAGNOSE_WARNING(__check_hash_requirements<_Key, _Hash>::value
|
||||
&& !__invokable<_Hash const&, _Key const&>::value,
|
||||
"the specified hash functor does not provide a const call operator")
|
||||
_LIBCPP_DIAGNOSE_WARNING(is_copy_constructible<_Equal>::value
|
||||
&& !__invokable<_Equal const&, _Key const&, _Key const&>::value,
|
||||
"the specified comparator type does not provide a const call operator")
|
||||
{
|
||||
static_assert(__check_hash_requirements<_Key, _Hash>::value,
|
||||
"the specified hash does not meet the Hash requirements");
|
||||
static_assert(is_copy_constructible<_Equal>::value,
|
||||
"the specified comparator is required to be copy constructible");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Key, class _Value, class _Hash, class _Equal, class _Alloc>
|
||||
struct __diagnose_hash_table_helper<
|
||||
__hash_value_type<_Key, _Value>,
|
||||
__unordered_map_hasher<_Key, __hash_value_type<_Key, _Value>, _Hash>,
|
||||
__unordered_map_equal<_Key, __hash_value_type<_Key, _Value>, _Equal>,
|
||||
_Alloc>
|
||||
: __diagnose_hash_table_helper<_Key, _Hash, _Equal, _Alloc>
|
||||
template <class _Tp, class _VoidPtr, class _Alloc>
|
||||
struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc>
|
||||
: __hash_node_destructor<_Alloc>
|
||||
{
|
||||
using __hash_node_destructor<_Alloc>::__hash_node_destructor;
|
||||
};
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
#endif
|
||||
|
||||
template <class _Key, class _Hash, class _Equal>
|
||||
struct __enforce_unordered_container_requirements {
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
static_assert(__check_hash_requirements<_Key, _Hash>::value,
|
||||
"the specified hash does not meet the Hash requirements");
|
||||
static_assert(is_copy_constructible<_Equal>::value,
|
||||
"the specified comparator is required to be copy constructible");
|
||||
#endif
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <class _Key, class _Hash, class _Equal>
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
|
||||
"the specified comparator type does not provide a viable const call operator")
|
||||
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
|
||||
"the specified hash functor does not provide a viable const call operator")
|
||||
#endif
|
||||
typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
|
||||
__diagnose_unordered_container_requirements(int);
|
||||
|
||||
// This dummy overload is used so that the compiler won't emit a spurious
|
||||
// "no matching function for call to __diagnose_unordered_xxx" diagnostic
|
||||
// when the overload above causes a hard error.
|
||||
template <class _Key, class _Hash, class _Equal>
|
||||
int __diagnose_unordered_container_requirements(void*);
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
class __hash_table
|
||||
@ -959,10 +950,6 @@ private:
|
||||
typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
|
||||
typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
static_assert(__diagnose_hash_table_helper<_Tp, _Hash, _Equal, _Alloc>::__trigger_diagnostics(), "");
|
||||
#endif
|
||||
|
||||
// --- Member data begin ---
|
||||
__bucket_list __bucket_list_;
|
||||
__compressed_pair<__first_node, __node_allocator> __p1_;
|
||||
@ -1054,8 +1041,26 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__next_pointer __node_insert_multi_prepare(size_t __cp_hash,
|
||||
value_type& __cp_val);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __node_insert_multi_perform(__node_pointer __cp,
|
||||
__next_pointer __pn) _NOEXCEPT;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__next_pointer __node_insert_unique_prepare(size_t __nd_hash,
|
||||
value_type& __nd_val);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __node_insert_unique_perform(__node_pointer __ptr) _NOEXCEPT;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_insert_multi(__node_pointer __nd);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_insert_multi(const_iterator __p,
|
||||
__node_pointer __nd);
|
||||
|
||||
@ -1158,6 +1163,36 @@ public:
|
||||
return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _NodeHandle, class _InsertReturnType>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_handle_insert_unique(const_iterator __hint,
|
||||
_NodeHandle&& __nh);
|
||||
template <class _Table>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __node_handle_merge_unique(_Table& __source);
|
||||
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_handle_insert_multi(_NodeHandle&& __nh);
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
|
||||
template <class _Table>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __node_handle_merge_multi(_Table& __source);
|
||||
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle __node_handle_extract(key_type const& __key);
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle __node_handle_extract(const_iterator __it);
|
||||
#endif
|
||||
|
||||
void clear() _NOEXCEPT;
|
||||
void rehash(size_type __n);
|
||||
_LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
|
||||
@ -1225,7 +1260,7 @@ public:
|
||||
|
||||
void swap(__hash_table& __u)
|
||||
#if _LIBCPP_STD_VER <= 11
|
||||
_NOEXCEPT_DEBUG_(
|
||||
_NOEXCEPT_(
|
||||
__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
|
||||
&& (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
|
||||
|| __is_nothrow_swappable<__pointer_allocator>::value)
|
||||
@ -1233,7 +1268,7 @@ public:
|
||||
|| __is_nothrow_swappable<__node_allocator>::value)
|
||||
);
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value);
|
||||
_NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value);
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -1402,7 +1437,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
|
||||
const key_equal& __eql,
|
||||
const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0, __hf),
|
||||
__p3_(1.0f, __eql)
|
||||
{
|
||||
@ -1411,7 +1446,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0),
|
||||
__p3_(1.0f)
|
||||
{
|
||||
@ -1423,7 +1458,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
|
||||
__bucket_list_deleter(allocator_traits<__pointer_allocator>::
|
||||
select_on_container_copy_construction(
|
||||
__u.__bucket_list_.get_deleter().__alloc()), 0)),
|
||||
__p1_(allocator_traits<__node_allocator>::
|
||||
__p1_(__second_tag(), allocator_traits<__node_allocator>::
|
||||
select_on_container_copy_construction(__u.__node_alloc())),
|
||||
__p2_(0, __u.hash_function()),
|
||||
__p3_(__u.__p3_)
|
||||
@ -1434,7 +1469,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
|
||||
const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0, __u.hash_function()),
|
||||
__p3_(__u.__p3_)
|
||||
{
|
||||
@ -1468,7 +1503,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
|
||||
const allocator_type& __a)
|
||||
: __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
|
||||
__p1_(__node_allocator(__a)),
|
||||
__p1_(__second_tag(), __node_allocator(__a)),
|
||||
__p2_(0, _VSTD::move(__u.hash_function())),
|
||||
__p3_(_VSTD::move(__u.__p3_))
|
||||
{
|
||||
@ -1821,73 +1856,112 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Prepare the container for an insertion of the value __value with the hash
|
||||
// __hash. This does a lookup into the container to see if __value is already
|
||||
// present, and performs a rehash if necessary. Returns a pointer to the
|
||||
// existing element if it exists, otherwise nullptr.
|
||||
//
|
||||
// Note that this function does forward exceptions if key_eq() throws, and never
|
||||
// mutates __value or actually inserts into the map.
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare(
|
||||
size_t __hash, value_type& __value)
|
||||
{
|
||||
__nd->__hash_ = hash_function()(__nd->__value_);
|
||||
size_type __bc = bucket_count();
|
||||
bool __inserted = false;
|
||||
__next_pointer __ndptr;
|
||||
size_t __chash;
|
||||
|
||||
if (__bc != 0)
|
||||
{
|
||||
__chash = __constrain_hash(__nd->__hash_, __bc);
|
||||
__ndptr = __bucket_list_[__chash];
|
||||
size_t __chash = __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;
|
||||
__ndptr = __ndptr->__next_)
|
||||
{
|
||||
if (key_eq()(__ndptr->__upcast()->__value_, __nd->__value_))
|
||||
goto __done;
|
||||
if (key_eq()(__ndptr->__upcast()->__value_, __value))
|
||||
return __ndptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (size()+1 > __bc * max_load_factor() || __bc == 0)
|
||||
{
|
||||
if (size()+1 > __bc * max_load_factor() || __bc == 0)
|
||||
{
|
||||
rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
|
||||
size_type(ceil(float(size() + 1) / max_load_factor()))));
|
||||
__bc = bucket_count();
|
||||
__chash = __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)
|
||||
{
|
||||
__pn =__p1_.first().__ptr();
|
||||
__nd->__next_ = __pn->__next_;
|
||||
__pn->__next_ = __nd->__ptr();
|
||||
// fix up __bucket_list_
|
||||
__bucket_list_[__chash] = __pn;
|
||||
if (__nd->__next_ != nullptr)
|
||||
__bucket_list_[__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr();
|
||||
}
|
||||
else
|
||||
{
|
||||
__nd->__next_ = __pn->__next_;
|
||||
__pn->__next_ = __nd->__ptr();
|
||||
}
|
||||
__ndptr = __nd->__ptr();
|
||||
// increment size
|
||||
++size();
|
||||
__inserted = true;
|
||||
rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
|
||||
size_type(ceil(float(size() + 1) / max_load_factor()))));
|
||||
}
|
||||
__done:
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
return pair<iterator, bool>(iterator(__ndptr, this), __inserted);
|
||||
#else
|
||||
return pair<iterator, bool>(iterator(__ndptr), __inserted);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Insert the node __nd into the container by pushing it into the right bucket,
|
||||
// and updating size(). Assumes that __nd->__hash is up-to-date, and that
|
||||
// rehashing has already occurred and that no element with the same key exists
|
||||
// in the map.
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
__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);
|
||||
// insert_after __bucket_list_[__chash], or __first_node if bucket is null
|
||||
__next_pointer __pn = __bucket_list_[__chash];
|
||||
if (__pn == nullptr)
|
||||
{
|
||||
__pn =__p1_.first().__ptr();
|
||||
__nd->__next_ = __pn->__next_;
|
||||
__pn->__next_ = __nd->__ptr();
|
||||
// fix up __bucket_list_
|
||||
__bucket_list_[__chash] = __pn;
|
||||
if (__nd->__next_ != nullptr)
|
||||
__bucket_list_[__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr();
|
||||
}
|
||||
else
|
||||
{
|
||||
__nd->__next_ = __pn->__next_;
|
||||
__pn->__next_ = __nd->__ptr();
|
||||
}
|
||||
++size();
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
|
||||
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
|
||||
{
|
||||
__nd->__hash_ = hash_function()(__nd->__value_);
|
||||
__next_pointer __existing_node =
|
||||
__node_insert_unique_prepare(__nd->__hash(), __nd->__value_);
|
||||
|
||||
// Insert the node, unless it already exists in the container.
|
||||
bool __inserted = false;
|
||||
if (__existing_node == nullptr)
|
||||
{
|
||||
__node_insert_unique_perform(__nd);
|
||||
__existing_node = __nd->__ptr();
|
||||
__inserted = true;
|
||||
}
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
return pair<iterator, bool>(iterator(__existing_node, this), __inserted);
|
||||
#else
|
||||
return pair<iterator, bool>(iterator(__existing_node), __inserted);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Prepare the container for an insertion of the value __cp_val with the hash
|
||||
// __cp_hash. This does a lookup into the container to see if __cp_value is
|
||||
// already present, and performs a rehash if necessary. Returns a pointer to the
|
||||
// last occurance of __cp_val in the map.
|
||||
//
|
||||
// Note that this function does forward exceptions if key_eq() throws, and never
|
||||
// mutates __value or actually inserts into the map.
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare(
|
||||
size_t __cp_hash, value_type& __cp_val)
|
||||
{
|
||||
__cp->__hash_ = hash_function()(__cp->__value_);
|
||||
size_type __bc = bucket_count();
|
||||
if (size()+1 > __bc * max_load_factor() || __bc == 0)
|
||||
{
|
||||
@ -1895,8 +1969,44 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __c
|
||||
size_type(ceil(float(size() + 1) / max_load_factor()))));
|
||||
__bc = bucket_count();
|
||||
}
|
||||
size_t __chash = __constrain_hash(__cp->__hash_, __bc);
|
||||
size_t __chash = __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;
|
||||
__pn = __pn->__next_)
|
||||
{
|
||||
// __found key_eq() action
|
||||
// false false loop
|
||||
// true true loop
|
||||
// false true set __found to true
|
||||
// true false break
|
||||
if (__found != (__pn->__next_->__hash() == __cp_hash &&
|
||||
key_eq()(__pn->__next_->__upcast()->__value_, __cp_val)))
|
||||
{
|
||||
if (!__found)
|
||||
__found = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __pn;
|
||||
}
|
||||
|
||||
// Insert the node __cp into the container after __pn (which is the last node in
|
||||
// the bucket that compares equal to __cp). Rehashing, and checking for
|
||||
// uniqueness has already been performed (in __node_insert_multi_prepare), so
|
||||
// all we need to do is update the bucket and size(). Assumes that __cp->__hash
|
||||
// is up-to-date.
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
void
|
||||
__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);
|
||||
if (__pn == nullptr)
|
||||
{
|
||||
__pn =__p1_.first().__ptr();
|
||||
@ -1910,24 +2020,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __c
|
||||
}
|
||||
else
|
||||
{
|
||||
for (bool __found = false; __pn->__next_ != nullptr &&
|
||||
__constrain_hash(__pn->__next_->__hash(), __bc) == __chash;
|
||||
__pn = __pn->__next_)
|
||||
{
|
||||
// __found key_eq() action
|
||||
// false false loop
|
||||
// true true loop
|
||||
// false true set __found to true
|
||||
// true false break
|
||||
if (__found != (__pn->__next_->__hash() == __cp->__hash_ &&
|
||||
key_eq()(__pn->__next_->__upcast()->__value_, __cp->__value_)))
|
||||
{
|
||||
if (!__found)
|
||||
__found = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
__cp->__next_ = __pn->__next_;
|
||||
__pn->__next_ = __cp->__ptr();
|
||||
if (__cp->__next_ != nullptr)
|
||||
@ -1938,6 +2030,17 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __c
|
||||
}
|
||||
}
|
||||
++size();
|
||||
}
|
||||
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
|
||||
{
|
||||
__cp->__hash_ = hash_function()(__cp->__value_);
|
||||
__next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__value_);
|
||||
__node_insert_multi_perform(__cp, __pn);
|
||||
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
return iterator(__cp->__ptr(), this);
|
||||
#else
|
||||
@ -2133,9 +2236,142 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
|
||||
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _NodeHandle, class _InsertReturnType>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_InsertReturnType
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
|
||||
_NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return _InsertReturnType{end(), false, _NodeHandle()};
|
||||
pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
|
||||
if (__result.second)
|
||||
__nh.__release_ptr();
|
||||
return _InsertReturnType{__result.first, __result.second, _VSTD::move(__nh)};
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
|
||||
const_iterator, _NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return end();
|
||||
pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
|
||||
if (__result.second)
|
||||
__nh.__release_ptr();
|
||||
return __result.first;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
|
||||
key_type const& __key)
|
||||
{
|
||||
iterator __i = find(__key);
|
||||
if (__i == end())
|
||||
return _NodeHandle();
|
||||
return __node_handle_extract<_NodeHandle>(__i);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
|
||||
const_iterator __p)
|
||||
{
|
||||
allocator_type __alloc(__node_alloc());
|
||||
return _NodeHandle(remove(__p).release(), __alloc);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _Table>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique(
|
||||
_Table& __source)
|
||||
{
|
||||
static_assert(is_same<__node, typename _Table::__node>::value, "");
|
||||
|
||||
for (typename _Table::iterator __it = __source.begin();
|
||||
__it != __source.end();)
|
||||
{
|
||||
__node_pointer __src_ptr = __it.__node_->__upcast();
|
||||
size_t __hash = hash_function()(__src_ptr->__value_);
|
||||
__next_pointer __existing_node =
|
||||
__node_insert_unique_prepare(__hash, __src_ptr->__value_);
|
||||
auto __prev_iter = __it++;
|
||||
if (__existing_node == nullptr)
|
||||
{
|
||||
(void)__source.remove(__prev_iter).release();
|
||||
__src_ptr->__hash_ = __hash;
|
||||
__node_insert_unique_perform(__src_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
|
||||
_NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return end();
|
||||
iterator __result = __node_insert_multi(__nh.__ptr_);
|
||||
__nh.__release_ptr();
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
|
||||
const_iterator __hint, _NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return end();
|
||||
iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
|
||||
__nh.__release_ptr();
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
template <class _Table>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi(
|
||||
_Table& __source)
|
||||
{
|
||||
static_assert(is_same<typename _Table::__node, __node>::value, "");
|
||||
|
||||
for (typename _Table::iterator __it = __source.begin();
|
||||
__it != __source.end();)
|
||||
{
|
||||
__node_pointer __src_ptr = __it.__node_->__upcast();
|
||||
size_t __src_hash = hash_function()(__src_ptr->__value_);
|
||||
__next_pointer __pn =
|
||||
__node_insert_multi_prepare(__src_hash, __src_ptr->__value_);
|
||||
(void)__source.remove(__it++).release();
|
||||
__src_ptr->__hash_ = __src_hash;
|
||||
__node_insert_multi_perform(__src_ptr, __pn);
|
||||
}
|
||||
}
|
||||
#endif // _LIBCPP_STD_VER > 14
|
||||
|
||||
template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
void
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
|
||||
_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
|
||||
{
|
||||
if (__n == 1)
|
||||
__n = 2;
|
||||
@ -2571,7 +2807,7 @@ template <class _Tp, class _Hash, class _Equal, class _Alloc>
|
||||
void
|
||||
__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
|
||||
#if _LIBCPP_STD_VER <= 11
|
||||
_NOEXCEPT_DEBUG_(
|
||||
_NOEXCEPT_(
|
||||
__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
|
||||
&& (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
|
||||
|| __is_nothrow_swappable<__pointer_allocator>::value)
|
||||
@ -2579,7 +2815,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
|
||||
|| __is_nothrow_swappable<__node_allocator>::value)
|
||||
)
|
||||
#else
|
||||
_NOEXCEPT_DEBUG_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
|
||||
_NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
|
||||
#endif
|
||||
{
|
||||
_LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value ||
|
||||
@ -2669,6 +2905,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*,
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_DEBUG_LEVEL >= 2
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP__HASH_TABLE
|
||||
|
@ -1 +1 @@
|
||||
5000
|
||||
10000
|
||||
|
288
include/__locale
288
include/__locale
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -19,27 +18,29 @@
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
#include <locale.h>
|
||||
#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
# include <cstring>
|
||||
# include <support/win32/locale_win32.h>
|
||||
#elif defined(_AIX)
|
||||
# include <support/ibm/xlocale.h>
|
||||
#elif defined(__ANDROID__)
|
||||
// Android gained the locale aware functions in L (API level 21)
|
||||
# include <android/api-level.h>
|
||||
# if __ANDROID_API__ <= 20
|
||||
# include <support/android/locale_bionic.h>
|
||||
# endif
|
||||
# include <support/android/locale_bionic.h>
|
||||
#elif defined(__sun__)
|
||||
# include <xlocale.h>
|
||||
# include <support/solaris/xlocale.h>
|
||||
#elif defined(_NEWLIB_VERSION)
|
||||
# include <support/newlib/xlocale.h>
|
||||
#elif (defined(__GLIBC__) || defined(__APPLE__) || defined(__FreeBSD__) \
|
||||
#elif (defined(__APPLE__) || defined(__FreeBSD__) \
|
||||
|| defined(__EMSCRIPTEN__) || defined(__IBMCPP__))
|
||||
# include <xlocale.h>
|
||||
#elif defined(__Fuchsia__)
|
||||
# include <support/fuchsia/xlocale.h>
|
||||
#elif defined(__wasi__)
|
||||
// WASI libc uses musl's locales support.
|
||||
# include <support/musl/xlocale.h>
|
||||
#elif defined(_LIBCPP_HAS_MUSL_LIBC)
|
||||
# include <support/musl/xlocale.h>
|
||||
#endif // __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun__ || __EMSCRIPTEN__ || __IBMCPP__
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -47,6 +48,64 @@
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS)
|
||||
struct __libcpp_locale_guard {
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
~__libcpp_locale_guard() {
|
||||
if (__old_loc_)
|
||||
uselocale(__old_loc_);
|
||||
}
|
||||
|
||||
locale_t __old_loc_;
|
||||
private:
|
||||
__libcpp_locale_guard(__libcpp_locale_guard const&);
|
||||
__libcpp_locale_guard& operator=(__libcpp_locale_guard const&);
|
||||
};
|
||||
#elif defined(_LIBCPP_MSVCRT_LIKE)
|
||||
struct __libcpp_locale_guard {
|
||||
__libcpp_locale_guard(locale_t __l) :
|
||||
__status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
|
||||
// Setting the locale can be expensive even when the locale given is
|
||||
// already the current locale, so do an explicit check to see if the
|
||||
// current locale is already the one we want.
|
||||
const char* __lc = __setlocale(nullptr);
|
||||
// If every category is the same, the locale string will simply be the
|
||||
// locale name, otherwise it will be a semicolon-separated string listing
|
||||
// each category. In the second case, we know at least one category won't
|
||||
// be what we want, so we only have to check the first case.
|
||||
if (strcmp(__l.__get_locale(), __lc) != 0) {
|
||||
__locale_all = _strdup(__lc);
|
||||
if (__locale_all == nullptr)
|
||||
__throw_bad_alloc();
|
||||
__setlocale(__l.__get_locale());
|
||||
}
|
||||
}
|
||||
~__libcpp_locale_guard() {
|
||||
// The CRT documentation doesn't explicitly say, but setlocale() does the
|
||||
// right thing when given a semicolon-separated list of locale settings
|
||||
// for the different categories in the same format as returned by
|
||||
// setlocale(LC_ALL, nullptr).
|
||||
if (__locale_all != nullptr) {
|
||||
__setlocale(__locale_all);
|
||||
free(__locale_all);
|
||||
}
|
||||
_configthreadlocale(__status);
|
||||
}
|
||||
static const char* __setlocale(const char* __locale) {
|
||||
const char* __new_locale = setlocale(LC_ALL, __locale);
|
||||
if (__new_locale == nullptr)
|
||||
__throw_bad_alloc();
|
||||
return __new_locale;
|
||||
}
|
||||
int __status;
|
||||
char* __locale_all = nullptr;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
class _LIBCPP_TYPE_VIS locale;
|
||||
|
||||
template <class _Facet>
|
||||
@ -67,6 +126,7 @@ public:
|
||||
class _LIBCPP_TYPE_VIS id;
|
||||
|
||||
typedef int category;
|
||||
_LIBCPP_AVAILABILITY_LOCALE_CATEGORY
|
||||
static const category // values assigned here are for exposition only
|
||||
none = 0,
|
||||
collate = LC_COLLATE_MASK,
|
||||
@ -211,7 +271,10 @@ public:
|
||||
return do_compare(__lo1, __hi1, __lo2, __hi2);
|
||||
}
|
||||
|
||||
// FIXME(EricWF): The _LIBCPP_ALWAYS_INLINE is needed on Windows to work
|
||||
// around a dllimport bug that expects an external instantiation.
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
string_type transform(const char_type* __lo, const char_type* __hi) const
|
||||
{
|
||||
return do_transform(__lo, __hi);
|
||||
@ -345,7 +408,12 @@ public:
|
||||
static const mask punct = _ISpunct;
|
||||
static const mask xdigit = _ISxdigit;
|
||||
static const mask blank = _ISblank;
|
||||
#elif defined(_LIBCPP_MSVCRT)
|
||||
#if defined(__mips__)
|
||||
static const mask __regex_word = static_cast<mask>(_ISbit(15));
|
||||
#else
|
||||
static const mask __regex_word = 0x80;
|
||||
#endif
|
||||
#elif defined(_LIBCPP_MSVCRT_LIKE)
|
||||
typedef unsigned short mask;
|
||||
static const mask space = _SPACE;
|
||||
static const mask print = _BLANK|_PUNCT|_ALPHA|_DIGIT;
|
||||
@ -357,6 +425,7 @@ public:
|
||||
static const mask punct = _PUNCT;
|
||||
static const mask xdigit = _HEX;
|
||||
static const mask blank = _BLANK;
|
||||
static const mask __regex_word = 0x80;
|
||||
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
|
||||
# ifdef __APPLE__
|
||||
@ -378,8 +447,12 @@ public:
|
||||
|
||||
# if defined(__NetBSD__)
|
||||
static const mask blank = _CTYPE_BL;
|
||||
// NetBSD defines classes up to 0x2000
|
||||
// see sys/ctype_bits.h, _CTYPE_Q
|
||||
static const mask __regex_word = 0x8000;
|
||||
# else
|
||||
static const mask blank = _CTYPE_B;
|
||||
static const mask __regex_word = 0x80;
|
||||
# endif
|
||||
#elif defined(__sun__) || defined(_AIX)
|
||||
typedef unsigned int mask;
|
||||
@ -393,6 +466,7 @@ public:
|
||||
static const mask punct = _ISPUNCT;
|
||||
static const mask xdigit = _ISXDIGIT;
|
||||
static const mask blank = _ISBLANK;
|
||||
static const mask __regex_word = 0x80;
|
||||
#elif defined(_NEWLIB_VERSION)
|
||||
// Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h.
|
||||
typedef char mask;
|
||||
@ -406,6 +480,7 @@ public:
|
||||
static const mask punct = _P;
|
||||
static const mask xdigit = _X | _N;
|
||||
static const mask blank = _B;
|
||||
static const mask __regex_word = 0x80;
|
||||
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
|
||||
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
|
||||
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
|
||||
@ -421,11 +496,12 @@ public:
|
||||
static const mask punct = 1<<7;
|
||||
static const mask xdigit = 1<<8;
|
||||
static const mask blank = 1<<9;
|
||||
static const mask __regex_word = 1<<10;
|
||||
#endif
|
||||
static const mask alnum = alpha | digit;
|
||||
static const mask graph = alnum | punct;
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE ctype_base() {}
|
||||
_LIBCPP_INLINE_VISIBILITY ctype_base() {}
|
||||
};
|
||||
|
||||
template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype;
|
||||
@ -438,77 +514,77 @@ class _LIBCPP_TYPE_VIS ctype<wchar_t>
|
||||
public:
|
||||
typedef wchar_t char_type;
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit ctype(size_t __refs = 0)
|
||||
: locale::facet(__refs) {}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool is(mask __m, char_type __c) const
|
||||
{
|
||||
return do_is(__m, __c);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
|
||||
{
|
||||
return do_is(__low, __high, __vec);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const
|
||||
{
|
||||
return do_scan_is(__m, __low, __high);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
|
||||
{
|
||||
return do_scan_not(__m, __low, __high);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char_type toupper(char_type __c) const
|
||||
{
|
||||
return do_toupper(__c);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* toupper(char_type* __low, const char_type* __high) const
|
||||
{
|
||||
return do_toupper(__low, __high);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char_type tolower(char_type __c) const
|
||||
{
|
||||
return do_tolower(__c);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* tolower(char_type* __low, const char_type* __high) const
|
||||
{
|
||||
return do_tolower(__low, __high);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char_type widen(char __c) const
|
||||
{
|
||||
return do_widen(__c);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char* widen(const char* __low, const char* __high, char_type* __to) const
|
||||
{
|
||||
return do_widen(__low, __high, __to);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char narrow(char_type __c, char __dfault) const
|
||||
{
|
||||
return do_narrow(__c, __dfault);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
|
||||
{
|
||||
return do_narrow(__low, __high, __dfault, __to);
|
||||
@ -543,13 +619,13 @@ public:
|
||||
|
||||
explicit ctype(const mask* __tab = 0, bool __del = false, size_t __refs = 0);
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool is(mask __m, char_type __c) const
|
||||
{
|
||||
return isascii(__c) ? (__tab_[static_cast<int>(__c)] & __m) !=0 : false;
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
|
||||
{
|
||||
for (; __low != __high; ++__low, ++__vec)
|
||||
@ -557,7 +633,7 @@ public:
|
||||
return __low;
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const
|
||||
{
|
||||
for (; __low != __high; ++__low)
|
||||
@ -566,7 +642,7 @@ public:
|
||||
return __low;
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
|
||||
{
|
||||
for (; __low != __high; ++__low)
|
||||
@ -575,49 +651,49 @@ public:
|
||||
return __low;
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char_type toupper(char_type __c) const
|
||||
{
|
||||
return do_toupper(__c);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* toupper(char_type* __low, const char_type* __high) const
|
||||
{
|
||||
return do_toupper(__low, __high);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char_type tolower(char_type __c) const
|
||||
{
|
||||
return do_tolower(__c);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char_type* tolower(char_type* __low, const char_type* __high) const
|
||||
{
|
||||
return do_tolower(__low, __high);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char_type widen(char __c) const
|
||||
{
|
||||
return do_widen(__c);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char* widen(const char* __low, const char* __high, char_type* __to) const
|
||||
{
|
||||
return do_widen(__low, __high, __to);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
char narrow(char_type __c, char __dfault) const
|
||||
{
|
||||
return do_narrow(__c, __dfault);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
|
||||
{
|
||||
return do_narrow(__low, __high, __dfault, __to);
|
||||
@ -630,7 +706,7 @@ public:
|
||||
#else
|
||||
static const size_t table_size = 256; // FIXME: Don't hardcode this.
|
||||
#endif
|
||||
_LIBCPP_ALWAYS_INLINE const mask* table() const _NOEXCEPT {return __tab_;}
|
||||
_LIBCPP_INLINE_VISIBILITY const mask* table() const _NOEXCEPT {return __tab_;}
|
||||
static const mask* classic_table() _NOEXCEPT;
|
||||
#if defined(__GLIBC__) || defined(__EMSCRIPTEN__)
|
||||
static const int* __classic_upper_table() _NOEXCEPT;
|
||||
@ -810,7 +886,7 @@ tolower(_CharT __c, const locale& __loc)
|
||||
class _LIBCPP_TYPE_VIS codecvt_base
|
||||
{
|
||||
public:
|
||||
_LIBCPP_ALWAYS_INLINE codecvt_base() {}
|
||||
_LIBCPP_INLINE_VISIBILITY codecvt_base() {}
|
||||
enum result {ok, partial, error, noconv};
|
||||
};
|
||||
|
||||
@ -830,11 +906,11 @@ public:
|
||||
typedef char extern_type;
|
||||
typedef mbstate_t state_type;
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt(size_t __refs = 0)
|
||||
: locale::facet(__refs) {}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result out(state_type& __st,
|
||||
const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
@ -842,14 +918,14 @@ public:
|
||||
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result unshift(state_type& __st,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
{
|
||||
return do_unshift(__st, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result in(state_type& __st,
|
||||
const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
|
||||
intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
|
||||
@ -857,25 +933,25 @@ public:
|
||||
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int encoding() const _NOEXCEPT
|
||||
{
|
||||
return do_encoding();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool always_noconv() const _NOEXCEPT
|
||||
{
|
||||
return do_always_noconv();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
|
||||
{
|
||||
return do_length(__st, __frm, __end, __mx);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int max_length() const _NOEXCEPT
|
||||
{
|
||||
return do_max_length();
|
||||
@ -884,7 +960,7 @@ public:
|
||||
static locale::id id;
|
||||
|
||||
protected:
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt(const char*, size_t __refs = 0)
|
||||
: locale::facet(__refs) {}
|
||||
|
||||
@ -919,7 +995,7 @@ public:
|
||||
|
||||
explicit codecvt(size_t __refs = 0);
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result out(state_type& __st,
|
||||
const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
@ -927,14 +1003,14 @@ public:
|
||||
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result unshift(state_type& __st,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
{
|
||||
return do_unshift(__st, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result in(state_type& __st,
|
||||
const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
|
||||
intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
|
||||
@ -942,25 +1018,25 @@ public:
|
||||
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int encoding() const _NOEXCEPT
|
||||
{
|
||||
return do_encoding();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool always_noconv() const _NOEXCEPT
|
||||
{
|
||||
return do_always_noconv();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
|
||||
{
|
||||
return do_length(__st, __frm, __end, __mx);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int max_length() const _NOEXCEPT
|
||||
{
|
||||
return do_max_length();
|
||||
@ -999,11 +1075,11 @@ public:
|
||||
typedef char extern_type;
|
||||
typedef mbstate_t state_type;
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt(size_t __refs = 0)
|
||||
: locale::facet(__refs) {}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result out(state_type& __st,
|
||||
const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
@ -1011,14 +1087,14 @@ public:
|
||||
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result unshift(state_type& __st,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
{
|
||||
return do_unshift(__st, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result in(state_type& __st,
|
||||
const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
|
||||
intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
|
||||
@ -1026,25 +1102,25 @@ public:
|
||||
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int encoding() const _NOEXCEPT
|
||||
{
|
||||
return do_encoding();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool always_noconv() const _NOEXCEPT
|
||||
{
|
||||
return do_always_noconv();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
|
||||
{
|
||||
return do_length(__st, __frm, __end, __mx);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int max_length() const _NOEXCEPT
|
||||
{
|
||||
return do_max_length();
|
||||
@ -1053,7 +1129,7 @@ public:
|
||||
static locale::id id;
|
||||
|
||||
protected:
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt(const char*, size_t __refs = 0)
|
||||
: locale::facet(__refs) {}
|
||||
|
||||
@ -1085,11 +1161,11 @@ public:
|
||||
typedef char extern_type;
|
||||
typedef mbstate_t state_type;
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt(size_t __refs = 0)
|
||||
: locale::facet(__refs) {}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result out(state_type& __st,
|
||||
const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
@ -1097,14 +1173,14 @@ public:
|
||||
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result unshift(state_type& __st,
|
||||
extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
|
||||
{
|
||||
return do_unshift(__st, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
result in(state_type& __st,
|
||||
const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
|
||||
intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
|
||||
@ -1112,25 +1188,25 @@ public:
|
||||
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int encoding() const _NOEXCEPT
|
||||
{
|
||||
return do_encoding();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool always_noconv() const _NOEXCEPT
|
||||
{
|
||||
return do_always_noconv();
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
|
||||
{
|
||||
return do_length(__st, __frm, __end, __mx);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
int max_length() const _NOEXCEPT
|
||||
{
|
||||
return do_max_length();
|
||||
@ -1139,7 +1215,7 @@ public:
|
||||
static locale::id id;
|
||||
|
||||
protected:
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt(const char*, size_t __refs = 0)
|
||||
: locale::facet(__refs) {}
|
||||
|
||||
@ -1166,10 +1242,10 @@ class _LIBCPP_TEMPLATE_VIS codecvt_byname
|
||||
: public codecvt<_InternT, _ExternT, _StateT>
|
||||
{
|
||||
public:
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt_byname(const char* __nm, size_t __refs = 0)
|
||||
: codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {}
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit codecvt_byname(const string& __nm, size_t __refs = 0)
|
||||
: codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {}
|
||||
protected:
|
||||
@ -1186,8 +1262,6 @@ _LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<w
|
||||
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char, mbstate_t>)
|
||||
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char, mbstate_t>)
|
||||
|
||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_runtime_error(const char*);
|
||||
|
||||
template <size_t _Np>
|
||||
struct __narrow_to_utf8
|
||||
{
|
||||
@ -1200,7 +1274,7 @@ template <>
|
||||
struct __narrow_to_utf8<8>
|
||||
{
|
||||
template <class _OutputIterator, class _CharT>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_OutputIterator
|
||||
operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
|
||||
{
|
||||
@ -1211,16 +1285,16 @@ struct __narrow_to_utf8<8>
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __narrow_to_utf8<16>
|
||||
struct _LIBCPP_TEMPLATE_VIS __narrow_to_utf8<16>
|
||||
: public codecvt<char16_t, char, mbstate_t>
|
||||
{
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__narrow_to_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
|
||||
|
||||
~__narrow_to_utf8();
|
||||
_LIBCPP_EXPORTED_FROM_ABI ~__narrow_to_utf8();
|
||||
|
||||
template <class _OutputIterator, class _CharT>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_OutputIterator
|
||||
operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
|
||||
{
|
||||
@ -1245,16 +1319,16 @@ struct __narrow_to_utf8<16>
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __narrow_to_utf8<32>
|
||||
struct _LIBCPP_TEMPLATE_VIS __narrow_to_utf8<32>
|
||||
: public codecvt<char32_t, char, mbstate_t>
|
||||
{
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__narrow_to_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
|
||||
|
||||
~__narrow_to_utf8();
|
||||
_LIBCPP_EXPORTED_FROM_ABI ~__narrow_to_utf8();
|
||||
|
||||
template <class _OutputIterator, class _CharT>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_OutputIterator
|
||||
operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
|
||||
{
|
||||
@ -1290,7 +1364,7 @@ template <>
|
||||
struct __widen_from_utf8<8>
|
||||
{
|
||||
template <class _OutputIterator>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_OutputIterator
|
||||
operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
|
||||
{
|
||||
@ -1301,16 +1375,16 @@ struct __widen_from_utf8<8>
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __widen_from_utf8<16>
|
||||
struct _LIBCPP_TEMPLATE_VIS __widen_from_utf8<16>
|
||||
: public codecvt<char16_t, char, mbstate_t>
|
||||
{
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__widen_from_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
|
||||
|
||||
~__widen_from_utf8();
|
||||
_LIBCPP_EXPORTED_FROM_ABI ~__widen_from_utf8();
|
||||
|
||||
template <class _OutputIterator>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_OutputIterator
|
||||
operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
|
||||
{
|
||||
@ -1335,16 +1409,16 @@ struct __widen_from_utf8<16>
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __widen_from_utf8<32>
|
||||
struct _LIBCPP_TEMPLATE_VIS __widen_from_utf8<32>
|
||||
: public codecvt<char32_t, char, mbstate_t>
|
||||
{
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__widen_from_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
|
||||
|
||||
~__widen_from_utf8();
|
||||
_LIBCPP_EXPORTED_FROM_ABI ~__widen_from_utf8();
|
||||
|
||||
template <class _OutputIterator>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_OutputIterator
|
||||
operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
|
||||
{
|
||||
@ -1382,11 +1456,11 @@ public:
|
||||
|
||||
explicit numpunct(size_t __refs = 0);
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
|
||||
_LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
|
||||
_LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
|
||||
_LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();}
|
||||
_LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();}
|
||||
_LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
|
||||
_LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
|
||||
_LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();}
|
||||
_LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();}
|
||||
_LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();}
|
||||
|
||||
static locale::id id;
|
||||
|
||||
@ -1413,11 +1487,11 @@ public:
|
||||
|
||||
explicit numpunct(size_t __refs = 0);
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
|
||||
_LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
|
||||
_LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
|
||||
_LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();}
|
||||
_LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();}
|
||||
_LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
|
||||
_LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
|
||||
_LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();}
|
||||
_LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();}
|
||||
_LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();}
|
||||
|
||||
static locale::id id;
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -16,10 +15,16 @@
|
||||
#include <system_error>
|
||||
#include <__threading_support>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
@ -32,28 +37,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
# endif
|
||||
#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION
|
||||
|
||||
|
||||
class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
__libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
|
||||
#else
|
||||
__libcpp_mutex_t __m_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
constexpr mutex() _NOEXCEPT = default;
|
||||
_LIBCPP_CONSTEXPR mutex() = default;
|
||||
|
||||
mutex(const mutex&) = delete;
|
||||
mutex& operator=(const mutex&) = delete;
|
||||
|
||||
#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION)
|
||||
~mutex() = default;
|
||||
#else
|
||||
mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;}
|
||||
~mutex() _NOEXCEPT;
|
||||
#endif
|
||||
~mutex();
|
||||
|
||||
private:
|
||||
mutex(const mutex&);// = delete;
|
||||
mutex& operator=(const mutex&);// = delete;
|
||||
|
||||
public:
|
||||
void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
|
||||
bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
|
||||
void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
|
||||
@ -62,21 +63,24 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
|
||||
};
|
||||
|
||||
struct _LIBCPP_TYPE_VIS defer_lock_t {};
|
||||
struct _LIBCPP_TYPE_VIS try_to_lock_t {};
|
||||
struct _LIBCPP_TYPE_VIS adopt_lock_t {};
|
||||
static_assert(is_nothrow_default_constructible<mutex>::value,
|
||||
"the default constructor for std::mutex must be nothrow");
|
||||
|
||||
#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX)
|
||||
struct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; };
|
||||
struct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; };
|
||||
struct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; };
|
||||
|
||||
extern const defer_lock_t defer_lock;
|
||||
extern const try_to_lock_t try_to_lock;
|
||||
extern const adopt_lock_t adopt_lock;
|
||||
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
|
||||
extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock;
|
||||
extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
|
||||
extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock;
|
||||
|
||||
#else
|
||||
|
||||
constexpr defer_lock_t defer_lock = defer_lock_t();
|
||||
constexpr try_to_lock_t try_to_lock = try_to_lock_t();
|
||||
constexpr adopt_lock_t adopt_lock = adopt_lock_t();
|
||||
/* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t defer_lock = defer_lock_t();
|
||||
/* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
|
||||
/* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t adopt_lock = adopt_lock_t();
|
||||
|
||||
#endif
|
||||
|
||||
@ -91,10 +95,11 @@ private:
|
||||
mutex_type& __m_;
|
||||
public:
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
|
||||
explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
|
||||
: __m_(__m) {__m_.lock();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY
|
||||
lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
|
||||
: __m_(__m) {}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -150,7 +155,7 @@ private:
|
||||
unique_lock& operator=(unique_lock const&); // = delete;
|
||||
|
||||
public:
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
unique_lock(unique_lock&& __u) _NOEXCEPT
|
||||
: __m_(__u.__m_), __owns_(__u.__owns_)
|
||||
@ -167,7 +172,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
@ -279,26 +284,20 @@ _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
|
||||
|
||||
class _LIBCPP_TYPE_VIS condition_variable
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
__libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
#else
|
||||
__libcpp_condvar_t __cv_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
constexpr condition_variable() _NOEXCEPT = default;
|
||||
_LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
|
||||
|
||||
#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
|
||||
~condition_variable() = default;
|
||||
#else
|
||||
condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;}
|
||||
#endif
|
||||
~condition_variable();
|
||||
#endif
|
||||
|
||||
private:
|
||||
condition_variable(const condition_variable&); // = delete;
|
||||
condition_variable& operator=(const condition_variable&); // = delete;
|
||||
condition_variable(const condition_variable&) = delete;
|
||||
condition_variable& operator=(const condition_variable&) = delete;
|
||||
|
||||
public:
|
||||
void notify_one() _NOEXCEPT;
|
||||
void notify_all() _NOEXCEPT;
|
||||
|
||||
@ -339,23 +338,75 @@ public:
|
||||
private:
|
||||
void __do_timed_wait(unique_lock<mutex>& __lk,
|
||||
chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
|
||||
void __do_timed_wait(unique_lock<mutex>& __lk,
|
||||
chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
#endif
|
||||
template <class _Clock>
|
||||
void __do_timed_wait(unique_lock<mutex>& __lk,
|
||||
chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
};
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
template <class _To, class _Rep, class _Period>
|
||||
template <class _Rep, class _Period>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if
|
||||
<
|
||||
chrono::__is_duration<_To>::value,
|
||||
_To
|
||||
is_floating_point<_Rep>::value,
|
||||
chrono::nanoseconds
|
||||
>::type
|
||||
__ceil(chrono::duration<_Rep, _Period> __d)
|
||||
__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
|
||||
{
|
||||
using namespace chrono;
|
||||
_To __r = duration_cast<_To>(__d);
|
||||
if (__r < __d)
|
||||
++__r;
|
||||
return __r;
|
||||
using __ratio = ratio_divide<_Period, nano>;
|
||||
using __ns_rep = nanoseconds::rep;
|
||||
_Rep __result_float = __d.count() * __ratio::num / __ratio::den;
|
||||
|
||||
_Rep __result_max = numeric_limits<__ns_rep>::max();
|
||||
if (__result_float >= __result_max) {
|
||||
return nanoseconds::max();
|
||||
}
|
||||
|
||||
_Rep __result_min = numeric_limits<__ns_rep>::min();
|
||||
if (__result_float <= __result_min) {
|
||||
return nanoseconds::min();
|
||||
}
|
||||
|
||||
return nanoseconds(static_cast<__ns_rep>(__result_float));
|
||||
}
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if
|
||||
<
|
||||
!is_floating_point<_Rep>::value,
|
||||
chrono::nanoseconds
|
||||
>::type
|
||||
__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d)
|
||||
{
|
||||
using namespace chrono;
|
||||
if (__d.count() == 0) {
|
||||
return nanoseconds(0);
|
||||
}
|
||||
|
||||
using __ratio = ratio_divide<_Period, nano>;
|
||||
using __ns_rep = nanoseconds::rep;
|
||||
__ns_rep __result_max = std::numeric_limits<__ns_rep>::max();
|
||||
if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) {
|
||||
return nanoseconds::max();
|
||||
}
|
||||
|
||||
__ns_rep __result_min = std::numeric_limits<__ns_rep>::min();
|
||||
if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) {
|
||||
return nanoseconds::min();
|
||||
}
|
||||
|
||||
__ns_rep __result = __d.count() * __ratio::num / __ratio::den;
|
||||
if (__result == 0) {
|
||||
return nanoseconds(1);
|
||||
}
|
||||
|
||||
return nanoseconds(__result);
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
@ -373,7 +424,15 @@ condition_variable::wait_until(unique_lock<mutex>& __lk,
|
||||
const chrono::time_point<_Clock, _Duration>& __t)
|
||||
{
|
||||
using namespace chrono;
|
||||
wait_for(__lk, __t - _Clock::now());
|
||||
using __clock_tp_ns = time_point<_Clock, nanoseconds>;
|
||||
|
||||
typename _Clock::time_point __now = _Clock::now();
|
||||
if (__t <= __now)
|
||||
return cv_status::timeout;
|
||||
|
||||
__clock_tp_ns __t_ns = __clock_tp_ns(__safe_nanosecond_cast(__t.time_since_epoch()));
|
||||
|
||||
__do_timed_wait(__lk, __t_ns);
|
||||
return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
|
||||
@ -399,15 +458,25 @@ condition_variable::wait_for(unique_lock<mutex>& __lk,
|
||||
using namespace chrono;
|
||||
if (__d <= __d.zero())
|
||||
return cv_status::timeout;
|
||||
typedef time_point<system_clock, duration<long double, nano> > __sys_tpf;
|
||||
typedef time_point<system_clock, nanoseconds> __sys_tpi;
|
||||
__sys_tpf _Max = __sys_tpi::max();
|
||||
using __ns_rep = nanoseconds::rep;
|
||||
steady_clock::time_point __c_now = steady_clock::now();
|
||||
system_clock::time_point __s_now = system_clock::now();
|
||||
if (_Max - __d > __s_now)
|
||||
__do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d));
|
||||
else
|
||||
__do_timed_wait(__lk, __sys_tpi::max());
|
||||
|
||||
#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
|
||||
using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
|
||||
__ns_rep __now_count_ns = __safe_nanosecond_cast(__c_now.time_since_epoch()).count();
|
||||
#else
|
||||
using __clock_tp_ns = time_point<system_clock, nanoseconds>;
|
||||
__ns_rep __now_count_ns = __safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
|
||||
#endif
|
||||
|
||||
__ns_rep __d_ns_count = __safe_nanosecond_cast(__d).count();
|
||||
|
||||
if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
|
||||
__do_timed_wait(__lk, __clock_tp_ns::max());
|
||||
} else {
|
||||
__do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
|
||||
}
|
||||
|
||||
return steady_clock::now() - __c_now < __d ? cv_status::no_timeout :
|
||||
cv_status::timeout;
|
||||
}
|
||||
@ -423,8 +492,50 @@ condition_variable::wait_for(unique_lock<mutex>& __lk,
|
||||
_VSTD::move(__pred));
|
||||
}
|
||||
|
||||
#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
|
||||
inline
|
||||
void
|
||||
condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
|
||||
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT
|
||||
{
|
||||
using namespace chrono;
|
||||
if (!__lk.owns_lock())
|
||||
__throw_system_error(EPERM,
|
||||
"condition_variable::timed wait: mutex not locked");
|
||||
nanoseconds __d = __tp.time_since_epoch();
|
||||
timespec __ts;
|
||||
seconds __s = duration_cast<seconds>(__d);
|
||||
using __ts_sec = decltype(__ts.tv_sec);
|
||||
const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max();
|
||||
if (__s.count() < __ts_sec_max)
|
||||
{
|
||||
__ts.tv_sec = static_cast<__ts_sec>(__s.count());
|
||||
__ts.tv_nsec = (__d - __s).count();
|
||||
}
|
||||
else
|
||||
{
|
||||
__ts.tv_sec = __ts_sec_max;
|
||||
__ts.tv_nsec = giga::num - 1;
|
||||
}
|
||||
int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
|
||||
if (__ec != 0 && __ec != ETIMEDOUT)
|
||||
__throw_system_error(__ec, "condition_variable timed_wait failed");
|
||||
}
|
||||
#endif // _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
|
||||
template <class _Clock>
|
||||
inline
|
||||
void
|
||||
condition_variable::__do_timed_wait(unique_lock<mutex>& __lk,
|
||||
chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT
|
||||
{
|
||||
wait_for(__lk, __tp - _Clock::now());
|
||||
}
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___MUTEX_BASE
|
||||
|
208
include/__node_handle
Normal file
208
include/__node_handle
Normal file
@ -0,0 +1,208 @@
|
||||
// -*- 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___NODE_HANDLE
|
||||
#define _LIBCPP___NODE_HANDLE
|
||||
|
||||
#include <__config>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
|
||||
// Specialized in __tree & __hash_table for their _NodeType.
|
||||
template <class _NodeType, class _Alloc>
|
||||
struct __generic_container_node_destructor;
|
||||
|
||||
template <class _NodeType, class _Alloc,
|
||||
template <class, class> class _MapOrSetSpecifics>
|
||||
class _LIBCPP_TEMPLATE_VIS __basic_node_handle
|
||||
: public _MapOrSetSpecifics<
|
||||
_NodeType,
|
||||
__basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>
|
||||
{
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
friend class __tree;
|
||||
template <class _Tp, class _Hash, class _Equal, class _Allocator>
|
||||
friend class __hash_table;
|
||||
friend struct _MapOrSetSpecifics<
|
||||
_NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>;
|
||||
|
||||
typedef allocator_traits<_Alloc> __alloc_traits;
|
||||
typedef typename __rebind_pointer<typename __alloc_traits::void_pointer,
|
||||
_NodeType>::type
|
||||
__node_pointer_type;
|
||||
|
||||
public:
|
||||
typedef _Alloc allocator_type;
|
||||
|
||||
private:
|
||||
__node_pointer_type __ptr_ = nullptr;
|
||||
optional<allocator_type> __alloc_;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __release_ptr()
|
||||
{
|
||||
__ptr_ = nullptr;
|
||||
__alloc_ = _VSTD::nullopt;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __destroy_node_pointer()
|
||||
{
|
||||
if (__ptr_ != nullptr)
|
||||
{
|
||||
typedef typename __allocator_traits_rebind<
|
||||
allocator_type, _NodeType>::type __node_alloc_type;
|
||||
__node_alloc_type __alloc(*__alloc_);
|
||||
__generic_container_node_destructor<_NodeType, __node_alloc_type>(
|
||||
__alloc, true)(__ptr_);
|
||||
__ptr_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__basic_node_handle(__node_pointer_type __ptr,
|
||||
allocator_type const& __alloc)
|
||||
: __ptr_(__ptr), __alloc_(__alloc)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__basic_node_handle() = default;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__basic_node_handle(__basic_node_handle&& __other) noexcept
|
||||
: __ptr_(__other.__ptr_),
|
||||
__alloc_(_VSTD::move(__other.__alloc_))
|
||||
{
|
||||
__other.__ptr_ = nullptr;
|
||||
__other.__alloc_ = _VSTD::nullopt;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__basic_node_handle& operator=(__basic_node_handle&& __other)
|
||||
{
|
||||
_LIBCPP_ASSERT(
|
||||
__alloc_ == _VSTD::nullopt ||
|
||||
__alloc_traits::propagate_on_container_move_assignment::value ||
|
||||
__alloc_ == __other.__alloc_,
|
||||
"node_type with incompatible allocator passed to "
|
||||
"node_type::operator=(node_type&&)");
|
||||
|
||||
__destroy_node_pointer();
|
||||
__ptr_ = __other.__ptr_;
|
||||
|
||||
if (__alloc_traits::propagate_on_container_move_assignment::value ||
|
||||
__alloc_ == _VSTD::nullopt)
|
||||
__alloc_ = _VSTD::move(__other.__alloc_);
|
||||
|
||||
__other.__ptr_ = nullptr;
|
||||
__other.__alloc_ = _VSTD::nullopt;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
allocator_type get_allocator() const { return *__alloc_; }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit operator bool() const { return __ptr_ != nullptr; }
|
||||
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
||||
bool empty() const { return __ptr_ == nullptr; }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(__basic_node_handle& __other) noexcept(
|
||||
__alloc_traits::propagate_on_container_swap::value ||
|
||||
__alloc_traits::is_always_equal::value)
|
||||
{
|
||||
using _VSTD::swap;
|
||||
swap(__ptr_, __other.__ptr_);
|
||||
if (__alloc_traits::propagate_on_container_swap::value ||
|
||||
__alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt)
|
||||
swap(__alloc_, __other.__alloc_);
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
friend void swap(__basic_node_handle& __a, __basic_node_handle& __b)
|
||||
noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); }
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
~__basic_node_handle()
|
||||
{
|
||||
__destroy_node_pointer();
|
||||
}
|
||||
};
|
||||
|
||||
template <class _NodeType, class _Derived>
|
||||
struct __set_node_handle_specifics
|
||||
{
|
||||
typedef typename _NodeType::__node_value_type value_type;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
value_type& value() const
|
||||
{
|
||||
return static_cast<_Derived const*>(this)->__ptr_->__value_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _NodeType, class _Derived>
|
||||
struct __map_node_handle_specifics
|
||||
{
|
||||
typedef typename _NodeType::__node_value_type::key_type key_type;
|
||||
typedef typename _NodeType::__node_value_type::mapped_type mapped_type;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
key_type& key() const
|
||||
{
|
||||
return static_cast<_Derived const*>(this)->
|
||||
__ptr_->__value_.__ref().first;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
mapped_type& mapped() const
|
||||
{
|
||||
return static_cast<_Derived const*>(this)->
|
||||
__ptr_->__value_.__ref().second;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _NodeType, class _Alloc>
|
||||
using __set_node_handle =
|
||||
__basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>;
|
||||
|
||||
template <class _NodeType, class _Alloc>
|
||||
using __map_node_handle =
|
||||
__basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>;
|
||||
|
||||
template <class _Iterator, class _NodeType>
|
||||
struct _LIBCPP_TEMPLATE_VIS __insert_return_type
|
||||
{
|
||||
_Iterator position;
|
||||
bool inserted;
|
||||
_NodeType node;
|
||||
};
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 14
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- __nullptr --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -27,24 +26,24 @@ struct _LIBCPP_TEMPLATE_VIS nullptr_t
|
||||
|
||||
struct __nat {int __for_bool_;};
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
|
||||
_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
operator _Tp* () const {return 0;}
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
operator _Tp _Up::* () const {return 0;}
|
||||
|
||||
friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}
|
||||
friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}
|
||||
friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}
|
||||
friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}
|
||||
};
|
||||
|
||||
inline _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}
|
||||
|
||||
#define nullptr _VSTD::__get_nullptr_t()
|
||||
|
||||
|
@ -6,12 +6,14 @@
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
|
||||
#include <__undef_min_max>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <bool>
|
||||
@ -66,7 +68,7 @@ public:
|
||||
__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
|
||||
~__split_buffer();
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
__split_buffer(__split_buffer&& __c)
|
||||
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
|
||||
__split_buffer(__split_buffer&& __c, const __alloc_rr& __a);
|
||||
@ -74,7 +76,7 @@ public:
|
||||
_NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value) ||
|
||||
!__alloc_traits::propagate_on_container_move_assignment::value);
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __begin_;}
|
||||
_LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __begin_;}
|
||||
@ -99,14 +101,12 @@ public:
|
||||
void shrink_to_fit() _NOEXCEPT;
|
||||
void push_front(const_reference __x);
|
||||
_LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x);
|
||||
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
void push_front(value_type&& __x);
|
||||
void push_back(value_type&& __x);
|
||||
#if !defined(_LIBCPP_HAS_NO_VARIADICS)
|
||||
template <class... _Args>
|
||||
void emplace_back(_Args&&... __args);
|
||||
#endif // !defined(_LIBCPP_HAS_NO_VARIADICS)
|
||||
#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
|
||||
#endif // !defined(_LIBCPP_CXX03_LANG)
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY void pop_front() {__destruct_at_begin(__begin_+1);}
|
||||
_LIBCPP_INLINE_VISIBILITY void pop_back() {__destruct_at_end(__end_-1);}
|
||||
@ -161,6 +161,19 @@ private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT
|
||||
{}
|
||||
|
||||
struct _ConstructTransaction {
|
||||
explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT
|
||||
: __pos_(*__p), __end_(*__p + __n), __dest_(__p) {
|
||||
}
|
||||
~_ConstructTransaction() {
|
||||
*__dest_ = __pos_;
|
||||
}
|
||||
pointer __pos_;
|
||||
const pointer __end_;
|
||||
private:
|
||||
pointer *__dest_;
|
||||
};
|
||||
};
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
@ -197,13 +210,10 @@ template <class _Tp, class _Allocator>
|
||||
void
|
||||
__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n)
|
||||
{
|
||||
__alloc_rr& __a = this->__alloc();
|
||||
do
|
||||
{
|
||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_));
|
||||
++this->__end_;
|
||||
--__n;
|
||||
} while (__n > 0);
|
||||
_ConstructTransaction __tx(&this->__end_, __n);
|
||||
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
|
||||
__alloc_traits::construct(this->__alloc(), _VSTD::__to_raw_pointer(__tx.__pos_));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy constructs __n objects starting at __end_ from __x
|
||||
@ -216,13 +226,11 @@ template <class _Tp, class _Allocator>
|
||||
void
|
||||
__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
|
||||
{
|
||||
__alloc_rr& __a = this->__alloc();
|
||||
do
|
||||
{
|
||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), __x);
|
||||
++this->__end_;
|
||||
--__n;
|
||||
} while (__n > 0);
|
||||
_ConstructTransaction __tx(&this->__end_, __n);
|
||||
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
|
||||
__alloc_traits::construct(this->__alloc(),
|
||||
_VSTD::__to_raw_pointer(__tx.__pos_), __x);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
@ -262,11 +270,10 @@ typename enable_if
|
||||
>::type
|
||||
__split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last)
|
||||
{
|
||||
__alloc_rr& __a = this->__alloc();
|
||||
for (; __first != __last; ++__first)
|
||||
{
|
||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first);
|
||||
++this->__end_;
|
||||
_ConstructTransaction __tx(&this->__end_, std::distance(__first, __last));
|
||||
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, ++__first) {
|
||||
__alloc_traits::construct(this->__alloc(),
|
||||
_VSTD::__to_raw_pointer(__tx.__pos_), *__first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,7 +350,7 @@ __split_buffer<_Tp, _Allocator>::~__split_buffer()
|
||||
__alloc_traits::deallocate(__alloc(), __first_, capacity());
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c)
|
||||
@ -361,7 +368,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c)
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
|
||||
: __end_cap_(__a)
|
||||
: __end_cap_(__second_tag(), __a)
|
||||
{
|
||||
if (__a == __c.__alloc())
|
||||
{
|
||||
@ -405,7 +412,7 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void
|
||||
@ -492,7 +499,7 @@ __split_buffer<_Tp, _Allocator>::push_front(const_reference __x)
|
||||
--__begin_;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void
|
||||
@ -524,7 +531,7 @@ __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x)
|
||||
--__begin_;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -556,7 +563,7 @@ __split_buffer<_Tp, _Allocator>::push_back(const_reference __x)
|
||||
++__end_;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
void
|
||||
@ -588,8 +595,6 @@ __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x)
|
||||
++__end_;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
template <class... _Args>
|
||||
void
|
||||
@ -621,9 +626,7 @@ __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args)
|
||||
++__end_;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -634,7 +637,8 @@ swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y)
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_SPLIT_BUFFER
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -55,14 +54,14 @@ public:
|
||||
__allocated_ = true;
|
||||
return (pointer)&buf_;
|
||||
}
|
||||
return static_cast<pointer>(_VSTD::__allocate(__n * sizeof(_Tp)));
|
||||
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type)
|
||||
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n)
|
||||
{
|
||||
if (__p == (pointer)&buf_)
|
||||
__allocated_ = false;
|
||||
else
|
||||
_VSTD::__libcpp_deallocate(__p);
|
||||
_VSTD::__libcpp_deallocate(__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);}
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -17,12 +16,14 @@
|
||||
#include <__locale>
|
||||
#include <cstdio>
|
||||
|
||||
#include <__undef_min_max>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
static const int __limit = 8;
|
||||
@ -355,4 +356,6 @@ __stdoutbuf<_CharT>::imbue(const locale& __loc)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___STD_STREAM
|
||||
|
134
include/__string
134
include/__string
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===-------------------------- __string ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -47,6 +46,7 @@ struct char_traits
|
||||
|
||||
template <> struct char_traits<char>;
|
||||
template <> struct char_traits<wchar_t>;
|
||||
template <> struct char_traits<char8_t>; // c++20
|
||||
|
||||
} // std
|
||||
|
||||
@ -57,14 +57,16 @@ template <> struct char_traits<wchar_t>;
|
||||
#include <cstdio> // For EOF.
|
||||
#include <memory> // for __murmur2_or_cityhash
|
||||
|
||||
#include <__undef_min_max>
|
||||
|
||||
#include <__debug>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// char_traits
|
||||
@ -264,7 +266,7 @@ const char*
|
||||
char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
|
||||
{
|
||||
if (__n == 0)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_char_memchr(__s, to_int_type(__a), __n);
|
||||
#elif _LIBCPP_STD_VER <= 14
|
||||
@ -276,7 +278,7 @@ char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a)
|
||||
return __s;
|
||||
++__s;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -349,6 +351,18 @@ char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <class _Traits>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR
|
||||
inline size_t __char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT {
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 1
|
||||
return __s ? _Traits::length(__s) : (_VSTD::__libcpp_debug_function(_VSTD::__libcpp_debug_info(__FILE__, __LINE__, "p == nullptr", "null pointer pass to non-null argument of char_traits<...>::length")), 0);
|
||||
#else
|
||||
return _Traits::length(__s);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
size_t
|
||||
char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
|
||||
@ -370,9 +384,9 @@ const wchar_t*
|
||||
char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
|
||||
{
|
||||
if (__n == 0)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_wmemchr(__s, __a, __n);
|
||||
return __builtin_wmemchr(__s, __a, __n);
|
||||
#elif _LIBCPP_STD_VER <= 14
|
||||
return wmemchr(__s, __a, __n);
|
||||
#else
|
||||
@ -382,11 +396,107 @@ char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __
|
||||
return __s;
|
||||
++__s;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef _LIBCPP_NO_HAS_CHAR8_T
|
||||
|
||||
template <>
|
||||
struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
|
||||
{
|
||||
typedef char8_t char_type;
|
||||
typedef unsigned int int_type;
|
||||
typedef streamoff off_type;
|
||||
typedef u8streampos pos_type;
|
||||
typedef mbstate_t state_type;
|
||||
|
||||
static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
|
||||
{__c1 = __c2;}
|
||||
static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
|
||||
{return __c1 == __c2;}
|
||||
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 constexpr
|
||||
size_t length(const char_type* __s) _NOEXCEPT;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY static constexpr
|
||||
const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
|
||||
|
||||
static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
|
||||
{return __n == 0 ? __s1 : (char_type*) memmove(__s1, __s2, __n);}
|
||||
|
||||
static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
|
||||
{
|
||||
_LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
|
||||
return __n == 0 ? __s1 : (char_type*)memcpy(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
|
||||
{return __n == 0 ? __s : (char_type*)memset(__s, to_int_type(__a), __n);}
|
||||
|
||||
static inline constexpr int_type not_eof(int_type __c) noexcept
|
||||
{return eq_int_type(__c, eof()) ? ~eof() : __c;}
|
||||
static inline constexpr char_type to_char_type(int_type __c) noexcept
|
||||
{return char_type(__c);}
|
||||
static inline constexpr int_type to_int_type(char_type __c) noexcept
|
||||
{return int_type(__c);}
|
||||
static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
|
||||
{return __c1 == __c2;}
|
||||
static inline constexpr int_type eof() noexcept
|
||||
{return int_type(EOF);}
|
||||
};
|
||||
|
||||
// TODO use '__builtin_strlen' if it ever supports char8_t ??
|
||||
inline constexpr
|
||||
size_t
|
||||
char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
|
||||
{
|
||||
size_t __len = 0;
|
||||
for (; !eq(*__s, char_type(0)); ++__s)
|
||||
++__len;
|
||||
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*
|
||||
char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
|
||||
{
|
||||
for (; __n; --__n)
|
||||
{
|
||||
if (eq(*__s, __a))
|
||||
return __s;
|
||||
++__s;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // #_LIBCPP_NO_HAS_CHAR8_T
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
|
||||
template <>
|
||||
@ -870,4 +980,6 @@ struct __quoted_output_proxy
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___STRING
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -13,6 +12,7 @@
|
||||
|
||||
#include <__config>
|
||||
#include <chrono>
|
||||
#include <iosfwd>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
@ -26,14 +26,11 @@
|
||||
#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
|
||||
# include <pthread.h>
|
||||
# include <sched.h>
|
||||
#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
|
||||
#include <Windows.h>
|
||||
#include <process.h>
|
||||
#include <fibersapi.h>
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
|
||||
defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
|
||||
defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \
|
||||
defined(_LIBCPP_HAS_THREAD_API_WIN32)
|
||||
#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
|
||||
#else
|
||||
#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -45,8 +42,16 @@
|
||||
#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
|
||||
#endif
|
||||
|
||||
typedef ::timespec __libcpp_timespec_t;
|
||||
#endif // !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
|
||||
#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
|
||||
// Mutex
|
||||
typedef pthread_mutex_t __libcpp_mutex_t;
|
||||
@ -70,39 +75,46 @@ typedef pthread_t __libcpp_thread_id;
|
||||
|
||||
typedef pthread_t __libcpp_thread_t;
|
||||
|
||||
// Thrad Local Storage
|
||||
// Thread Local Storage
|
||||
typedef pthread_key_t __libcpp_tls_key;
|
||||
|
||||
#define _LIBCPP_TLS_DESTRUCTOR_CC
|
||||
#else
|
||||
#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
|
||||
// Mutex
|
||||
typedef SRWLOCK __libcpp_mutex_t;
|
||||
#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
|
||||
typedef void* __libcpp_mutex_t;
|
||||
#define _LIBCPP_MUTEX_INITIALIZER 0
|
||||
|
||||
typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
|
||||
#if defined(_M_IX86) || defined(__i386__) || defined(_M_ARM) || defined(__arm__)
|
||||
typedef void* __libcpp_recursive_mutex_t[6];
|
||||
#elif defined(_M_AMD64) || defined(__x86_64__) || defined(_M_ARM64) || defined(__aarch64__)
|
||||
typedef void* __libcpp_recursive_mutex_t[5];
|
||||
#else
|
||||
# error Unsupported architecture
|
||||
#endif
|
||||
|
||||
// Condition Variable
|
||||
typedef CONDITION_VARIABLE __libcpp_condvar_t;
|
||||
#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
|
||||
typedef void* __libcpp_condvar_t;
|
||||
#define _LIBCPP_CONDVAR_INITIALIZER 0
|
||||
|
||||
// Execute Once
|
||||
typedef INIT_ONCE __libcpp_exec_once_flag;
|
||||
#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
|
||||
typedef void* __libcpp_exec_once_flag;
|
||||
#define _LIBCPP_EXEC_ONCE_INITIALIZER 0
|
||||
|
||||
// Thread ID
|
||||
typedef DWORD __libcpp_thread_id;
|
||||
typedef long __libcpp_thread_id;
|
||||
|
||||
// Thread
|
||||
#define _LIBCPP_NULL_THREAD 0U
|
||||
|
||||
typedef HANDLE __libcpp_thread_t;
|
||||
typedef void* __libcpp_thread_t;
|
||||
|
||||
// Thread Local Storage
|
||||
typedef DWORD __libcpp_tls_key;
|
||||
typedef long __libcpp_tls_key;
|
||||
|
||||
#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
|
||||
#endif
|
||||
#define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall
|
||||
#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
|
||||
|
||||
#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
|
||||
// Mutex
|
||||
_LIBCPP_THREAD_ABI_VISIBILITY
|
||||
int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
|
||||
@ -143,7 +155,7 @@ int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
|
||||
|
||||
_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
|
||||
int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
|
||||
timespec *__ts);
|
||||
__libcpp_timespec_t *__ts);
|
||||
|
||||
_LIBCPP_THREAD_ABI_VISIBILITY
|
||||
int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
|
||||
@ -151,7 +163,7 @@ int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
|
||||
// Execute once
|
||||
_LIBCPP_THREAD_ABI_VISIBILITY
|
||||
int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
|
||||
void (*init_routine)(void));
|
||||
void (*init_routine)());
|
||||
|
||||
// Thread id
|
||||
_LIBCPP_THREAD_ABI_VISIBILITY
|
||||
@ -197,10 +209,11 @@ void *__libcpp_tls_get(__libcpp_tls_key __key);
|
||||
_LIBCPP_THREAD_ABI_VISIBILITY
|
||||
int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
|
||||
|
||||
#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
|
||||
defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
|
||||
#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
|
||||
|
||||
#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
|
||||
#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
|
||||
defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \
|
||||
defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
|
||||
|
||||
int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
|
||||
{
|
||||
@ -283,7 +296,7 @@ int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
|
||||
}
|
||||
|
||||
int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
|
||||
timespec *__ts)
|
||||
__libcpp_timespec_t *__ts)
|
||||
{
|
||||
return pthread_cond_timedwait(__cv, __m, __ts);
|
||||
}
|
||||
@ -295,7 +308,7 @@ int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
|
||||
|
||||
// Execute once
|
||||
int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
|
||||
void (*init_routine)(void)) {
|
||||
void (*init_routine)()) {
|
||||
return pthread_once(flag, init_routine);
|
||||
}
|
||||
|
||||
@ -352,7 +365,7 @@ void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
|
||||
{
|
||||
using namespace chrono;
|
||||
seconds __s = duration_cast<seconds>(__ns);
|
||||
timespec __ts;
|
||||
__libcpp_timespec_t __ts;
|
||||
typedef decltype(__ts.tv_sec) ts_sec;
|
||||
_LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
|
||||
|
||||
@ -386,245 +399,92 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
|
||||
return pthread_setspecific(__key, __p);
|
||||
}
|
||||
|
||||
#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
|
||||
|
||||
// Mutex
|
||||
int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
|
||||
{
|
||||
InitializeCriticalSection(__m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
|
||||
{
|
||||
EnterCriticalSection(__m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
|
||||
{
|
||||
return TryEnterCriticalSection(__m) != 0;
|
||||
}
|
||||
|
||||
int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
|
||||
{
|
||||
LeaveCriticalSection(__m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
|
||||
{
|
||||
DeleteCriticalSection(__m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
|
||||
{
|
||||
AcquireSRWLockExclusive(__m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
|
||||
{
|
||||
return TryAcquireSRWLockExclusive(__m) != 0;
|
||||
}
|
||||
|
||||
int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
|
||||
{
|
||||
ReleaseSRWLockExclusive(__m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
|
||||
{
|
||||
static_cast<void>(__m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Condition Variable
|
||||
int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
|
||||
{
|
||||
WakeConditionVariable(__cv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
|
||||
{
|
||||
WakeAllConditionVariable(__cv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
|
||||
{
|
||||
SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
|
||||
timespec *__ts)
|
||||
{
|
||||
using namespace _VSTD::chrono;
|
||||
|
||||
auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
|
||||
auto abstime =
|
||||
system_clock::time_point(duration_cast<system_clock::duration>(duration));
|
||||
auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
|
||||
|
||||
if (!SleepConditionVariableSRW(__cv, __m,
|
||||
timeout_ms.count() > 0 ? timeout_ms.count()
|
||||
: 0,
|
||||
0))
|
||||
return GetLastError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
|
||||
{
|
||||
static_cast<void>(__cv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Execute Once
|
||||
static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
|
||||
__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
|
||||
PVOID *__context)
|
||||
{
|
||||
static_cast<void>(__init_once);
|
||||
static_cast<void>(__context);
|
||||
|
||||
void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
|
||||
init_routine();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
|
||||
void (*__init_routine)(void))
|
||||
{
|
||||
if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
|
||||
reinterpret_cast<void *>(__init_routine), NULL))
|
||||
return GetLastError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Thread ID
|
||||
bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
|
||||
__libcpp_thread_id __rhs)
|
||||
{
|
||||
return __lhs == __rhs;
|
||||
}
|
||||
|
||||
bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
|
||||
{
|
||||
return __lhs < __rhs;
|
||||
}
|
||||
|
||||
// Thread
|
||||
struct __libcpp_beginthreadex_thunk_data
|
||||
{
|
||||
void *(*__func)(void *);
|
||||
void *__arg;
|
||||
};
|
||||
|
||||
static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
|
||||
__libcpp_beginthreadex_thunk(void *__raw_data)
|
||||
{
|
||||
auto *__data =
|
||||
static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
|
||||
auto *__func = __data->__func;
|
||||
void *__arg = __data->__arg;
|
||||
delete __data;
|
||||
return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
|
||||
}
|
||||
|
||||
bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
|
||||
return *__t == 0;
|
||||
}
|
||||
|
||||
int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
|
||||
void *__arg)
|
||||
{
|
||||
auto *__data = new __libcpp_beginthreadex_thunk_data;
|
||||
__data->__func = __func;
|
||||
__data->__arg = __arg;
|
||||
|
||||
*__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
|
||||
__libcpp_beginthreadex_thunk,
|
||||
__data, 0, nullptr));
|
||||
|
||||
if (*__t)
|
||||
return 0;
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
__libcpp_thread_id __libcpp_thread_get_current_id()
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
|
||||
{
|
||||
return GetThreadId(*__t);
|
||||
}
|
||||
|
||||
int __libcpp_thread_join(__libcpp_thread_t *__t)
|
||||
{
|
||||
if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
|
||||
return GetLastError();
|
||||
if (!CloseHandle(*__t))
|
||||
return GetLastError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __libcpp_thread_detach(__libcpp_thread_t *__t)
|
||||
{
|
||||
if (!CloseHandle(*__t))
|
||||
return GetLastError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __libcpp_thread_yield()
|
||||
{
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
|
||||
{
|
||||
using namespace chrono;
|
||||
// round-up to the nearest milisecond
|
||||
milliseconds __ms =
|
||||
duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999));
|
||||
// FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
|
||||
Sleep(__ms.count());
|
||||
}
|
||||
|
||||
// Thread Local Storage
|
||||
int __libcpp_tls_create(__libcpp_tls_key* __key,
|
||||
void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
|
||||
{
|
||||
*__key = FlsAlloc(__at_exit);
|
||||
if (*__key == FLS_OUT_OF_INDEXES)
|
||||
return GetLastError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *__libcpp_tls_get(__libcpp_tls_key __key)
|
||||
{
|
||||
return FlsGetValue(__key);
|
||||
}
|
||||
|
||||
int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
|
||||
{
|
||||
if (!FlsSetValue(__key, __p))
|
||||
return GetLastError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
|
||||
|
||||
#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
class _LIBCPP_TYPE_VIS thread;
|
||||
class _LIBCPP_TYPE_VIS __thread_id;
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
|
||||
|
||||
} // this_thread
|
||||
|
||||
template<> struct hash<__thread_id>;
|
||||
|
||||
class _LIBCPP_TEMPLATE_VIS __thread_id
|
||||
{
|
||||
// FIXME: pthread_t is a pointer on Darwin but a long on Linux.
|
||||
// NULL is the no-thread value on Darwin. Someone needs to check
|
||||
// on other platforms. We assume 0 works everywhere for now.
|
||||
__libcpp_thread_id __id_;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id() _NOEXCEPT : __id_(0) {}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{ // don't pass id==0 to underlying routines
|
||||
if (__x.__id_ == 0) return __y.__id_ == 0;
|
||||
if (__y.__id_ == 0) return false;
|
||||
return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__x == __y);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{ // id==0 is always less than any other thread_id
|
||||
if (__x.__id_ == 0) return __y.__id_ != 0;
|
||||
if (__y.__id_ == 0) return false;
|
||||
return __libcpp_thread_id_less(__x.__id_, __y.__id_);
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__y < __x);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return __y < __x ;}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__x < __y);}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __reset() { __id_ = 0; }
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
friend
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
|
||||
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id(__libcpp_thread_id __id) : __id_(__id) {}
|
||||
|
||||
friend __thread_id this_thread::get_id() _NOEXCEPT;
|
||||
friend class _LIBCPP_TYPE_VIS thread;
|
||||
friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
|
||||
};
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id
|
||||
get_id() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_thread_get_current_id();
|
||||
}
|
||||
|
||||
} // this_thread
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_THREADING_SUPPORT
|
||||
|
527
include/__tree
527
include/__tree
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -17,14 +16,23 @@
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#include <__undef_min_max>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__) // gcc.gnu.org/PR37804
|
||||
template <class, class, class, class> class _LIBCPP_TEMPLATE_VIS map;
|
||||
template <class, class, class, class> class _LIBCPP_TEMPLATE_VIS multimap;
|
||||
template <class, class, class> class _LIBCPP_TEMPLATE_VIS set;
|
||||
template <class, class, class> class _LIBCPP_TEMPLATE_VIS multiset;
|
||||
#endif
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator> class __tree;
|
||||
template <class _Tp, class _NodePtr, class _DiffType>
|
||||
class _LIBCPP_TEMPLATE_VIS __tree_iterator;
|
||||
@ -35,17 +43,8 @@ template <class _Pointer> class __tree_end_node;
|
||||
template <class _VoidPtr> class __tree_node_base;
|
||||
template <class _Tp, class _VoidPtr> class __tree_node;
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Key, class _Value>
|
||||
union __value_type;
|
||||
#else
|
||||
template <class _Key, class _Value>
|
||||
struct __value_type;
|
||||
#endif
|
||||
|
||||
template <class _Key, class _CP, class _Compare,
|
||||
bool = is_empty<_Compare>::value && !__libcpp_is_final<_Compare>::value>
|
||||
class __map_value_compare;
|
||||
|
||||
template <class _Allocator> class __map_node_destructor;
|
||||
template <class _TreeIterator> class _LIBCPP_TEMPLATE_VIS __map_iterator;
|
||||
@ -82,7 +81,7 @@ __tree_is_left_child(_NodePtr __x) _NOEXCEPT
|
||||
return __x == __x->__parent_->__left_;
|
||||
}
|
||||
|
||||
// Determintes if the subtree rooted at __x is a proper red black subtree. If
|
||||
// Determines if the subtree rooted at __x is a proper red black subtree. If
|
||||
// __x is a proper subtree, returns the black height (null counts as 1). If
|
||||
// __x is an improper subtree, returns 0.
|
||||
template <class _NodePtr>
|
||||
@ -117,7 +116,7 @@ __tree_sub_invariant(_NodePtr __x)
|
||||
return __h + __x->__is_black_; // return black height of this node
|
||||
}
|
||||
|
||||
// Determintes if the red black tree rooted at __root is a proper red black tree.
|
||||
// Determines if the red black tree rooted at __root is a proper red black tree.
|
||||
// __root == nullptr is a proper tree. Returns true is __root is a proper
|
||||
// red black tree, else returns false.
|
||||
template <class _NodePtr>
|
||||
@ -567,10 +566,9 @@ struct __tree_key_value_types {
|
||||
static __container_value_type* __get_ptr(__node_value_type& __n) {
|
||||
return _VSTD::addressof(__n);
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
static __container_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v);
|
||||
}
|
||||
#endif
|
||||
@ -582,14 +580,13 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
|
||||
typedef _Tp mapped_type;
|
||||
typedef __value_type<_Key, _Tp> __node_value_type;
|
||||
typedef pair<const _Key, _Tp> __container_value_type;
|
||||
typedef pair<_Key, _Tp> __nc_value_type;
|
||||
typedef __container_value_type __map_value_type;
|
||||
static const bool __is_map = true;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static key_type const&
|
||||
__get_key(__node_value_type const& __t) {
|
||||
return __t.__cc.first;
|
||||
return __t.__get_value().first;
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
@ -603,7 +600,7 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type const&
|
||||
__get_value(__node_value_type const& __t) {
|
||||
return __t.__cc;
|
||||
return __t.__get_value();
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
@ -616,13 +613,13 @@ struct __tree_key_value_types<__value_type<_Key, _Tp> > {
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __container_value_type* __get_ptr(__node_value_type& __n) {
|
||||
return _VSTD::addressof(__n.__cc);
|
||||
return _VSTD::addressof(__n.__get_value());
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __nc_value_type&& __move(__node_value_type& __v) {
|
||||
return _VSTD::move(__v.__nc);
|
||||
static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) {
|
||||
return __v.__move();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@ -801,6 +798,16 @@ public:
|
||||
template <class> friend class __map_node_destructor;
|
||||
};
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _NodeType, class _Alloc>
|
||||
struct __generic_container_node_destructor;
|
||||
template <class _Tp, class _VoidPtr, class _Alloc>
|
||||
struct __generic_container_node_destructor<__tree_node<_Tp, _VoidPtr>, _Alloc>
|
||||
: __tree_node_destructor<_Alloc>
|
||||
{
|
||||
using __tree_node_destructor<_Alloc>::__tree_node_destructor;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class _Tp, class _NodePtr, class _DiffType>
|
||||
class _LIBCPP_TEMPLATE_VIS __tree_iterator
|
||||
@ -852,7 +859,7 @@ public:
|
||||
__tree_iterator operator--(int)
|
||||
{__tree_iterator __t(*this); --(*this); return __t;}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator==(const __tree_iterator& __x, const __tree_iterator& __y)
|
||||
{return __x.__ptr_ == __y.__ptr_;}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
@ -961,24 +968,12 @@ private:
|
||||
|
||||
};
|
||||
|
||||
template<class _Tp, class _Compare>
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
struct __diagnose_tree_helper {
|
||||
static constexpr bool __trigger_diagnostics()
|
||||
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Compare const&, _Tp const&, _Tp const&>::value,
|
||||
"the specified comparator type does not provide a const call operator")
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
template <class _Key, class _Value, class _KeyComp, class _Alloc>
|
||||
struct __diagnose_tree_helper<
|
||||
__value_type<_Key, _Value>,
|
||||
__map_value_compare<_Key, __value_type<_Key, _Value>, _KeyComp>,
|
||||
_Alloc
|
||||
> : __diagnose_tree_helper<_Key, _KeyComp, _Alloc>
|
||||
{
|
||||
};
|
||||
#endif // !_LIBCPP_CXX03_LANG
|
||||
_LIBCPP_DIAGNOSE_WARNING(!std::__invokable<_Compare const&, _Tp const&, _Tp const&>::value,
|
||||
"the specified comparator type does not provide a viable const call operator")
|
||||
#endif
|
||||
int __diagnose_non_const_comparator();
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
class __tree
|
||||
@ -1101,11 +1096,11 @@ public:
|
||||
__tree(const value_compare& __comp, const allocator_type& __a);
|
||||
__tree(const __tree& __t);
|
||||
__tree& operator=(const __tree& __t);
|
||||
template <class _InputIterator>
|
||||
void __assign_unique(_InputIterator __first, _InputIterator __last);
|
||||
template <class _ForwardIterator>
|
||||
void __assign_unique(_ForwardIterator __first, _ForwardIterator __last);
|
||||
template <class _InputIterator>
|
||||
void __assign_multi(_InputIterator __first, _InputIterator __last);
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
__tree(__tree&& __t)
|
||||
_NOEXCEPT_(
|
||||
is_nothrow_move_constructible<__node_allocator>::value &&
|
||||
@ -1116,7 +1111,7 @@ public:
|
||||
__node_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<value_compare>::value &&
|
||||
is_nothrow_move_assignable<__node_allocator>::value);
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
~__tree();
|
||||
|
||||
@ -1336,13 +1331,48 @@ public:
|
||||
|
||||
#endif // !_LIBCPP_CXX03_LANG
|
||||
|
||||
pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
|
||||
iterator __node_insert_unique(const_iterator __p,
|
||||
__node_pointer __nd);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair<iterator, bool> __node_assign_unique(const __container_value_type& __v, __node_pointer __dest);
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_insert_multi(__node_pointer __nd);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
|
||||
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY iterator
|
||||
__remove_node_pointer(__node_pointer) _NOEXCEPT;
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _NodeHandle, class _InsertReturnType>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_InsertReturnType __node_handle_insert_unique(_NodeHandle&&);
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_handle_insert_unique(const_iterator, _NodeHandle&&);
|
||||
template <class _Tree>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __node_handle_merge_unique(_Tree& __source);
|
||||
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_handle_insert_multi(_NodeHandle&&);
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_handle_insert_multi(const_iterator, _NodeHandle&&);
|
||||
template <class _Tree>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __node_handle_merge_multi(_Tree& __source);
|
||||
|
||||
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle __node_handle_extract(key_type const&);
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle __node_handle_extract(const_iterator);
|
||||
#endif
|
||||
|
||||
iterator erase(const_iterator __p);
|
||||
iterator erase(const_iterator __f, const_iterator __l);
|
||||
template <class _Key>
|
||||
@ -1352,7 +1382,7 @@ public:
|
||||
|
||||
void __insert_node_at(__parent_pointer __parent,
|
||||
__node_base_pointer& __child,
|
||||
__node_base_pointer __new_node);
|
||||
__node_base_pointer __new_node) _NOEXCEPT;
|
||||
|
||||
template <class _Key>
|
||||
iterator find(const _Key& __v);
|
||||
@ -1456,7 +1486,7 @@ private:
|
||||
void __copy_assign_alloc(const __tree& __t, true_type)
|
||||
{
|
||||
if (__node_alloc() != __t.__node_alloc())
|
||||
clear();
|
||||
clear();
|
||||
__node_alloc() = __t.__node_alloc();
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -1482,8 +1512,50 @@ private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __move_assign_alloc(__tree&, false_type) _NOEXCEPT {}
|
||||
|
||||
__node_pointer __detach();
|
||||
static __node_pointer __detach(__node_pointer);
|
||||
struct _DetachedTreeCache {
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit _DetachedTreeCache(__tree *__t) _NOEXCEPT : __t_(__t),
|
||||
__cache_root_(__detach_from_tree(__t)) {
|
||||
__advance();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__node_pointer __get() const _NOEXCEPT {
|
||||
return __cache_elem_;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __advance() _NOEXCEPT {
|
||||
__cache_elem_ = __cache_root_;
|
||||
if (__cache_root_) {
|
||||
__cache_root_ = __detach_next(__cache_root_);
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
~_DetachedTreeCache() {
|
||||
__t_->destroy(__cache_elem_);
|
||||
if (__cache_root_) {
|
||||
while (__cache_root_->__parent_ != nullptr)
|
||||
__cache_root_ = static_cast<__node_pointer>(__cache_root_->__parent_);
|
||||
__t_->destroy(__cache_root_);
|
||||
}
|
||||
}
|
||||
|
||||
_DetachedTreeCache(_DetachedTreeCache const&) = delete;
|
||||
_DetachedTreeCache& operator=(_DetachedTreeCache const&) = delete;
|
||||
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __node_pointer __detach_from_tree(__tree *__t) _NOEXCEPT;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static __node_pointer __detach_next(__node_pointer) _NOEXCEPT;
|
||||
|
||||
__tree *__t_;
|
||||
__node_pointer __cache_root_;
|
||||
__node_pointer __cache_elem_;
|
||||
};
|
||||
|
||||
|
||||
template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS map;
|
||||
template <class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS multimap;
|
||||
@ -1502,7 +1574,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp)
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a)
|
||||
: __begin_node_(__iter_pointer()),
|
||||
__pair1_(__node_allocator(__a)),
|
||||
__pair1_(__second_tag(), __node_allocator(__a)),
|
||||
__pair3_(0)
|
||||
{
|
||||
__begin_node() = __end_node();
|
||||
@ -1512,7 +1584,7 @@ template <class _Tp, class _Compare, class _Allocator>
|
||||
__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
|
||||
const allocator_type& __a)
|
||||
: __begin_node_(__iter_pointer()),
|
||||
__pair1_(__node_allocator(__a)),
|
||||
__pair1_(__second_tag(), __node_allocator(__a)),
|
||||
__pair3_(0, __comp)
|
||||
{
|
||||
__begin_node() = __end_node();
|
||||
@ -1521,13 +1593,13 @@ __tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp,
|
||||
// Precondition: size() != 0
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
|
||||
__tree<_Tp, _Compare, _Allocator>::__detach()
|
||||
__tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_from_tree(__tree *__t) _NOEXCEPT
|
||||
{
|
||||
__node_pointer __cache = static_cast<__node_pointer>(__begin_node());
|
||||
__begin_node() = __end_node();
|
||||
__end_node()->__left_->__parent_ = nullptr;
|
||||
__end_node()->__left_ = nullptr;
|
||||
size() = 0;
|
||||
__node_pointer __cache = static_cast<__node_pointer>(__t->__begin_node());
|
||||
__t->__begin_node() = __t->__end_node();
|
||||
__t->__end_node()->__left_->__parent_ = nullptr;
|
||||
__t->__end_node()->__left_ = nullptr;
|
||||
__t->size() = 0;
|
||||
// __cache->__left_ == nullptr
|
||||
if (__cache->__right_ != nullptr)
|
||||
__cache = static_cast<__node_pointer>(__cache->__right_);
|
||||
@ -1542,7 +1614,7 @@ __tree<_Tp, _Compare, _Allocator>::__detach()
|
||||
// This is no longer a red-black tree
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
typename __tree<_Tp, _Compare, _Allocator>::__node_pointer
|
||||
__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache)
|
||||
__tree<_Tp, _Compare, _Allocator>::_DetachedTreeCache::__detach_next(__node_pointer __cache) _NOEXCEPT
|
||||
{
|
||||
if (__cache->__parent_ == nullptr)
|
||||
return nullptr;
|
||||
@ -1576,45 +1648,23 @@ __tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t)
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _InputIterator>
|
||||
template <class _ForwardIterator>
|
||||
void
|
||||
__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last)
|
||||
__tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first, _ForwardIterator __last)
|
||||
{
|
||||
typedef iterator_traits<_InputIterator> _ITraits;
|
||||
typedef iterator_traits<_ForwardIterator> _ITraits;
|
||||
typedef typename _ITraits::value_type _ItValueType;
|
||||
static_assert((is_same<_ItValueType, __container_value_type>::value),
|
||||
"__assign_unique may only be called with the containers value type");
|
||||
|
||||
static_assert(__is_forward_iterator<_ForwardIterator>::value,
|
||||
"__assign_unique requires a forward iterator");
|
||||
if (size() != 0)
|
||||
{
|
||||
__node_pointer __cache = __detach();
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
for (; __cache != nullptr && __first != __last; ++__first)
|
||||
{
|
||||
__cache->__value_ = *__first;
|
||||
__node_pointer __next = __detach(__cache);
|
||||
__node_insert_unique(__cache);
|
||||
__cache = __next;
|
||||
_DetachedTreeCache __cache(this);
|
||||
for (; __cache.__get() != nullptr && __first != __last; ++__first) {
|
||||
if (__node_assign_unique(*__first, __cache.__get()).second)
|
||||
__cache.__advance();
|
||||
}
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
while (__cache->__parent_ != nullptr)
|
||||
__cache = static_cast<__node_pointer>(__cache->__parent_);
|
||||
destroy(__cache);
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
if (__cache != nullptr)
|
||||
{
|
||||
while (__cache->__parent_ != nullptr)
|
||||
__cache = static_cast<__node_pointer>(__cache->__parent_);
|
||||
destroy(__cache);
|
||||
}
|
||||
}
|
||||
for (; __first != __last; ++__first)
|
||||
__insert_unique(*__first);
|
||||
@ -1633,33 +1683,11 @@ __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _Input
|
||||
" or the nodes value type");
|
||||
if (size() != 0)
|
||||
{
|
||||
__node_pointer __cache = __detach();
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
for (; __cache != nullptr && __first != __last; ++__first)
|
||||
{
|
||||
__cache->__value_ = *__first;
|
||||
__node_pointer __next = __detach(__cache);
|
||||
__node_insert_multi(__cache);
|
||||
__cache = __next;
|
||||
}
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
while (__cache->__parent_ != nullptr)
|
||||
__cache = static_cast<__node_pointer>(__cache->__parent_);
|
||||
destroy(__cache);
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
if (__cache != nullptr)
|
||||
{
|
||||
while (__cache->__parent_ != nullptr)
|
||||
__cache = static_cast<__node_pointer>(__cache->__parent_);
|
||||
destroy(__cache);
|
||||
_DetachedTreeCache __cache(this);
|
||||
for (; __cache.__get() && __first != __last; ++__first) {
|
||||
__cache.__get()->__value_ = *__first;
|
||||
__node_insert_multi(__cache.__get());
|
||||
__cache.__advance();
|
||||
}
|
||||
}
|
||||
for (; __first != __last; ++__first)
|
||||
@ -1669,13 +1697,13 @@ __tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _Input
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t)
|
||||
: __begin_node_(__iter_pointer()),
|
||||
__pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())),
|
||||
__pair1_(__second_tag(), __node_traits::select_on_container_copy_construction(__t.__node_alloc())),
|
||||
__pair3_(0, __t.value_comp())
|
||||
{
|
||||
__begin_node() = __end_node();
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t)
|
||||
@ -1699,7 +1727,7 @@ __tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t)
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a)
|
||||
: __pair1_(__node_allocator(__a)),
|
||||
: __pair1_(__second_tag(), __node_allocator(__a)),
|
||||
__pair3_(0, _VSTD::move(__t.value_comp()))
|
||||
{
|
||||
if (__a == __t.__alloc())
|
||||
@ -1757,33 +1785,11 @@ __tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type)
|
||||
const_iterator __e = end();
|
||||
if (size() != 0)
|
||||
{
|
||||
__node_pointer __cache = __detach();
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
while (__cache != nullptr && __t.size() != 0)
|
||||
{
|
||||
__cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
|
||||
__node_pointer __next = __detach(__cache);
|
||||
__node_insert_multi(__cache);
|
||||
__cache = __next;
|
||||
}
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
while (__cache->__parent_ != nullptr)
|
||||
__cache = static_cast<__node_pointer>(__cache->__parent_);
|
||||
destroy(__cache);
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
if (__cache != nullptr)
|
||||
{
|
||||
while (__cache->__parent_ != nullptr)
|
||||
__cache = static_cast<__node_pointer>(__cache->__parent_);
|
||||
destroy(__cache);
|
||||
_DetachedTreeCache __cache(this);
|
||||
while (__cache.__get() != nullptr && __t.size() != 0) {
|
||||
__cache.__get()->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_);
|
||||
__node_insert_multi(__cache.__get());
|
||||
__cache.__advance();
|
||||
}
|
||||
}
|
||||
while (__t.size() != 0)
|
||||
@ -1798,24 +1804,20 @@ __tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t)
|
||||
__node_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<value_compare>::value &&
|
||||
is_nothrow_move_assignable<__node_allocator>::value)
|
||||
|
||||
|
||||
{
|
||||
__move_assign(__t, integral_constant<bool,
|
||||
__node_traits::propagate_on_container_move_assignment::value>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
__tree<_Tp, _Compare, _Allocator>::~__tree()
|
||||
{
|
||||
static_assert((is_copy_constructible<value_compare>::value),
|
||||
"Comparator must be copy-constructible.");
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
static_assert((__diagnose_tree_helper<_Tp, _Compare, _Allocator>::
|
||||
__trigger_diagnostics()), "");
|
||||
#endif
|
||||
destroy(__root());
|
||||
}
|
||||
|
||||
@ -2097,10 +2099,9 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint,
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
void
|
||||
__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__parent_pointer __parent,
|
||||
__node_base_pointer& __child,
|
||||
__node_base_pointer __new_node)
|
||||
void __tree<_Tp, _Compare, _Allocator>::__insert_node_at(
|
||||
__parent_pointer __parent, __node_base_pointer& __child,
|
||||
__node_base_pointer __new_node) _NOEXCEPT
|
||||
{
|
||||
__new_node->__left_ = nullptr;
|
||||
__new_node->__right_ = nullptr;
|
||||
@ -2297,14 +2298,15 @@ __tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const __co
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const __container_value_type& __v, __node_pointer __nd)
|
||||
{
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer& __child = __find_equal(__parent, __nd->__value_);
|
||||
__node_base_pointer& __child = __find_equal(__parent, _NodeTypes::__get_key(__v));
|
||||
__node_pointer __r = static_cast<__node_pointer>(__child);
|
||||
bool __inserted = false;
|
||||
if (__child == nullptr)
|
||||
{
|
||||
__nd->__value_ = __v;
|
||||
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
|
||||
__r = __nd;
|
||||
__inserted = true;
|
||||
@ -2312,22 +2314,6 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd)
|
||||
return pair<iterator, bool>(iterator(__r), __inserted);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p,
|
||||
__node_pointer __nd)
|
||||
{
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer __dummy;
|
||||
__node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_);
|
||||
__node_pointer __r = static_cast<__node_pointer>(__child);
|
||||
if (__child == nullptr)
|
||||
{
|
||||
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
|
||||
__r = __nd;
|
||||
}
|
||||
return iterator(__r);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
@ -2350,19 +2336,186 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
|
||||
return iterator(__nd);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
__tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _NOEXCEPT
|
||||
{
|
||||
iterator __r(__ptr);
|
||||
++__r;
|
||||
if (__begin_node() == __ptr)
|
||||
__begin_node() = __r.__ptr_;
|
||||
--size();
|
||||
__tree_remove(__end_node()->__left_,
|
||||
static_cast<__node_base_pointer>(__ptr));
|
||||
return __r;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _NodeHandle, class _InsertReturnType>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_InsertReturnType
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(
|
||||
_NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return _InsertReturnType{end(), false, _NodeHandle()};
|
||||
|
||||
__node_pointer __ptr = __nh.__ptr_;
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer& __child = __find_equal(__parent,
|
||||
__ptr->__value_);
|
||||
if (__child != nullptr)
|
||||
return _InsertReturnType{
|
||||
iterator(static_cast<__node_pointer>(__child)),
|
||||
false, _VSTD::move(__nh)};
|
||||
|
||||
__insert_node_at(__parent, __child,
|
||||
static_cast<__node_base_pointer>(__ptr));
|
||||
__nh.__release_ptr();
|
||||
return _InsertReturnType{iterator(__ptr), true, _NodeHandle()};
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(
|
||||
const_iterator __hint, _NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return end();
|
||||
|
||||
__node_pointer __ptr = __nh.__ptr_;
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer __dummy;
|
||||
__node_base_pointer& __child = __find_equal(__hint, __parent, __dummy,
|
||||
__ptr->__value_);
|
||||
__node_pointer __r = static_cast<__node_pointer>(__child);
|
||||
if (__child == nullptr)
|
||||
{
|
||||
__insert_node_at(__parent, __child,
|
||||
static_cast<__node_base_pointer>(__ptr));
|
||||
__r = __ptr;
|
||||
__nh.__release_ptr();
|
||||
}
|
||||
return iterator(__r);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key)
|
||||
{
|
||||
iterator __it = find(__key);
|
||||
if (__it == end())
|
||||
return _NodeHandle();
|
||||
return __node_handle_extract<_NodeHandle>(__it);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_NodeHandle
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p)
|
||||
{
|
||||
__node_pointer __np = __p.__get_np();
|
||||
__remove_node_pointer(__np);
|
||||
return _NodeHandle(__np, __alloc());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _Tree>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(_Tree& __source)
|
||||
{
|
||||
static_assert(is_same<typename _Tree::__node_pointer, __node_pointer>::value, "");
|
||||
|
||||
for (typename _Tree::iterator __i = __source.begin();
|
||||
__i != __source.end();)
|
||||
{
|
||||
__node_pointer __src_ptr = __i.__get_np();
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer& __child =
|
||||
__find_equal(__parent, _NodeTypes::__get_key(__src_ptr->__value_));
|
||||
++__i;
|
||||
if (__child != nullptr)
|
||||
continue;
|
||||
__source.__remove_node_pointer(__src_ptr);
|
||||
__insert_node_at(__parent, __child,
|
||||
static_cast<__node_base_pointer>(__src_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return end();
|
||||
__node_pointer __ptr = __nh.__ptr_;
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer& __child = __find_leaf_high(
|
||||
__parent, _NodeTypes::__get_key(__ptr->__value_));
|
||||
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
|
||||
__nh.__release_ptr();
|
||||
return iterator(__ptr);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _NodeHandle>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(
|
||||
const_iterator __hint, _NodeHandle&& __nh)
|
||||
{
|
||||
if (__nh.empty())
|
||||
return end();
|
||||
|
||||
__node_pointer __ptr = __nh.__ptr_;
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer& __child = __find_leaf(__hint, __parent,
|
||||
_NodeTypes::__get_key(__ptr->__value_));
|
||||
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
|
||||
__nh.__release_ptr();
|
||||
return iterator(__ptr);
|
||||
}
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
template <class _Tree>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(_Tree& __source)
|
||||
{
|
||||
static_assert(is_same<typename _Tree::__node_pointer, __node_pointer>::value, "");
|
||||
|
||||
for (typename _Tree::iterator __i = __source.begin();
|
||||
__i != __source.end();)
|
||||
{
|
||||
__node_pointer __src_ptr = __i.__get_np();
|
||||
__parent_pointer __parent;
|
||||
__node_base_pointer& __child = __find_leaf_high(
|
||||
__parent, _NodeTypes::__get_key(__src_ptr->__value_));
|
||||
++__i;
|
||||
__source.__remove_node_pointer(__src_ptr);
|
||||
__insert_node_at(__parent, __child,
|
||||
static_cast<__node_base_pointer>(__src_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 14
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p)
|
||||
{
|
||||
__node_pointer __np = __p.__get_np();
|
||||
iterator __r(__p.__ptr_);
|
||||
++__r;
|
||||
if (__begin_node() == __p.__ptr_)
|
||||
__begin_node() = __r.__ptr_;
|
||||
--size();
|
||||
iterator __r = __remove_node_pointer(__np);
|
||||
__node_allocator& __na = __node_alloc();
|
||||
__tree_remove(__end_node()->__left_,
|
||||
static_cast<__node_base_pointer>(__np));
|
||||
__node_traits::destroy(__na, _NodeTypes::__get_ptr(
|
||||
const_cast<__node_value_type&>(*__p)));
|
||||
__node_traits::deallocate(__na, __np, 1);
|
||||
@ -2685,4 +2838,6 @@ swap(__tree<_Tp, _Compare, _Allocator>& __x,
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___TREE
|
||||
|
108
include/__tuple
108
include/__tuple
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -22,59 +21,56 @@
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Tp> class _LIBCPP_TEMPLATE_VIS tuple_size;
|
||||
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size;
|
||||
|
||||
#if !defined(_LIBCPP_CXX03_LANG)
|
||||
template <class _Tp, class...>
|
||||
using __enable_if_tuple_size_imp = _Tp;
|
||||
|
||||
template <class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
|
||||
const _Tp,
|
||||
typename enable_if<!is_volatile<_Tp>::value>::type,
|
||||
integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
|
||||
: public integral_constant<size_t, tuple_size<_Tp>::value> {};
|
||||
|
||||
template <class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
|
||||
volatile _Tp,
|
||||
typename enable_if<!is_const<_Tp>::value>::type,
|
||||
integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
|
||||
: public integral_constant<size_t, tuple_size<_Tp>::value> {};
|
||||
|
||||
template <class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp<
|
||||
const volatile _Tp,
|
||||
integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
|
||||
: public integral_constant<size_t, tuple_size<_Tp>::value> {};
|
||||
|
||||
#else
|
||||
template <class _Tp> class _LIBCPP_TEMPLATE_VIS tuple_size<const _Tp> : public tuple_size<_Tp> {};
|
||||
template <class _Tp> class _LIBCPP_TEMPLATE_VIS tuple_size<volatile _Tp> : public tuple_size<_Tp> {};
|
||||
template <class _Tp> class _LIBCPP_TEMPLATE_VIS tuple_size<const volatile _Tp> : public tuple_size<_Tp> {};
|
||||
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size<const _Tp> : public tuple_size<_Tp> {};
|
||||
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size<volatile _Tp> : public tuple_size<_Tp> {};
|
||||
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size<const volatile _Tp> : public tuple_size<_Tp> {};
|
||||
#endif
|
||||
|
||||
template <size_t _Ip, class _Tp> class _LIBCPP_TEMPLATE_VIS tuple_element;
|
||||
template <size_t _Ip, class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_element;
|
||||
|
||||
template <size_t _Ip, class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp>
|
||||
{
|
||||
public:
|
||||
typedef typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type;
|
||||
};
|
||||
|
||||
template <size_t _Ip, class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp>
|
||||
{
|
||||
public:
|
||||
typedef typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type;
|
||||
};
|
||||
|
||||
template <size_t _Ip, class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp>
|
||||
{
|
||||
public:
|
||||
typedef typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type;
|
||||
};
|
||||
|
||||
template <class _Tp> struct __tuple_like : false_type {};
|
||||
@ -85,7 +81,7 @@ template <class _Tp> struct __tuple_like<const volatile _Tp> : public __tuple_li
|
||||
|
||||
// tuple specializations
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_VARIADICS)
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <size_t...> struct __tuple_indices {};
|
||||
|
||||
@ -103,7 +99,7 @@ namespace __detail {
|
||||
|
||||
template<typename _Tp, size_t ..._Extra> struct __repeat;
|
||||
template<typename _Tp, _Tp ..._Np, size_t ..._Extra> struct __repeat<__integer_sequence<_Tp, _Np...>, _Extra...> {
|
||||
typedef __integer_sequence<_Tp,
|
||||
typedef _LIBCPP_NODEBUG_TYPE __integer_sequence<_Tp,
|
||||
_Np...,
|
||||
sizeof...(_Np) + _Np...,
|
||||
2 * sizeof...(_Np) + _Np...,
|
||||
@ -165,7 +161,7 @@ template <class ..._Tp> class _LIBCPP_TEMPLATE_VIS tuple;
|
||||
template <class... _Tp> struct __tuple_like<tuple<_Tp...> > : true_type {};
|
||||
|
||||
template <class ..._Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_size<tuple<_Tp...> >
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_size<tuple<_Tp...> >
|
||||
: public integral_constant<size_t, sizeof...(_Tp)>
|
||||
{
|
||||
};
|
||||
@ -189,7 +185,8 @@ template <size_t _Ip, class ..._Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const typename tuple_element<_Ip, tuple<_Tp...> >::type&&
|
||||
get(const tuple<_Tp...>&&) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
#endif // !defined(_LIBCPP_CXX03_LANG)
|
||||
|
||||
// pair specializations
|
||||
|
||||
@ -205,7 +202,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
|
||||
get(const pair<_T1, _T2>&) _NOEXCEPT;
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <size_t _Ip, class _T1, class _T2>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
|
||||
@ -233,7 +230,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const _Tp&
|
||||
get(const array<_Tp, _Size>&) _NOEXCEPT;
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <size_t _Ip, class _Tp, size_t _Size>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_Tp&&
|
||||
@ -245,8 +242,7 @@ const _Tp&&
|
||||
get(const array<_Tp, _Size>&&) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_VARIADICS)
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
// __tuple_types
|
||||
|
||||
@ -257,7 +253,7 @@ template <class ..._Tp> struct __tuple_types {};
|
||||
namespace __indexer_detail {
|
||||
|
||||
template <size_t _Idx, class _Tp>
|
||||
struct __indexed { using type = _Tp; };
|
||||
struct __indexed { using type _LIBCPP_NODEBUG_TYPE = _Tp; };
|
||||
|
||||
template <class _Types, class _Indexes> struct __indexer;
|
||||
|
||||
@ -272,7 +268,7 @@ __indexed<_Idx, _Tp> __at_index(__indexed<_Idx, _Tp> const&);
|
||||
} // namespace __indexer_detail
|
||||
|
||||
template <size_t _Idx, class ..._Types>
|
||||
using __type_pack_element = typename decltype(
|
||||
using __type_pack_element _LIBCPP_NODEBUG_TYPE = typename decltype(
|
||||
__indexer_detail::__at_index<_Idx>(
|
||||
__indexer_detail::__indexer<
|
||||
__tuple_types<_Types...>,
|
||||
@ -282,16 +278,15 @@ using __type_pack_element = typename decltype(
|
||||
#endif
|
||||
|
||||
template <size_t _Ip, class ..._Types>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, __tuple_types<_Types...>>
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, __tuple_types<_Types...>>
|
||||
{
|
||||
public:
|
||||
static_assert(_Ip < sizeof...(_Types), "tuple_element index out of range");
|
||||
typedef __type_pack_element<_Ip, _Types...> type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE __type_pack_element<_Ip, _Types...> type;
|
||||
};
|
||||
|
||||
|
||||
template <class ..._Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_size<__tuple_types<_Tp...> >
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_size<__tuple_types<_Tp...> >
|
||||
: public integral_constant<size_t, sizeof...(_Tp)>
|
||||
{
|
||||
};
|
||||
@ -306,34 +301,34 @@ struct __apply_cv_mf<false, false, false> {
|
||||
};
|
||||
template <>
|
||||
struct __apply_cv_mf<false, true, false> {
|
||||
template <class _Tp> using __apply = const _Tp;
|
||||
template <class _Tp> using __apply _LIBCPP_NODEBUG_TYPE = const _Tp;
|
||||
};
|
||||
template <>
|
||||
struct __apply_cv_mf<false, false, true> {
|
||||
template <class _Tp> using __apply = volatile _Tp;
|
||||
template <class _Tp> using __apply _LIBCPP_NODEBUG_TYPE = volatile _Tp;
|
||||
};
|
||||
template <>
|
||||
struct __apply_cv_mf<false, true, true> {
|
||||
template <class _Tp> using __apply = const volatile _Tp;
|
||||
template <class _Tp> using __apply _LIBCPP_NODEBUG_TYPE = const volatile _Tp;
|
||||
};
|
||||
template <>
|
||||
struct __apply_cv_mf<true, false, false> {
|
||||
template <class _Tp> using __apply = _Tp&;
|
||||
template <class _Tp> using __apply _LIBCPP_NODEBUG_TYPE = _Tp&;
|
||||
};
|
||||
template <>
|
||||
struct __apply_cv_mf<true, true, false> {
|
||||
template <class _Tp> using __apply = const _Tp&;
|
||||
template <class _Tp> using __apply _LIBCPP_NODEBUG_TYPE = const _Tp&;
|
||||
};
|
||||
template <>
|
||||
struct __apply_cv_mf<true, false, true> {
|
||||
template <class _Tp> using __apply = volatile _Tp&;
|
||||
template <class _Tp> using __apply _LIBCPP_NODEBUG_TYPE = volatile _Tp&;
|
||||
};
|
||||
template <>
|
||||
struct __apply_cv_mf<true, true, true> {
|
||||
template <class _Tp> using __apply = const volatile _Tp&;
|
||||
template <class _Tp> using __apply _LIBCPP_NODEBUG_TYPE = const volatile _Tp&;
|
||||
};
|
||||
template <class _Tp, class _RawTp = typename remove_reference<_Tp>::type>
|
||||
using __apply_cv_t = __apply_cv_mf<
|
||||
using __apply_cv_t _LIBCPP_NODEBUG_TYPE = __apply_cv_mf<
|
||||
is_lvalue_reference<_Tp>::value,
|
||||
is_const<_RawTp>::value,
|
||||
is_volatile<_RawTp>::value>;
|
||||
@ -352,7 +347,7 @@ template <template <class...> class _Tuple, class ..._Types, size_t ..._Idx>
|
||||
struct __make_tuple_types_flat<_Tuple<_Types...>, __tuple_indices<_Idx...>> {
|
||||
// Specialization for pair, tuple, and __tuple_types
|
||||
template <class _Tp, class _ApplyFn = __apply_cv_t<_Tp>>
|
||||
using __apply_quals = __tuple_types<
|
||||
using __apply_quals _LIBCPP_NODEBUG_TYPE = __tuple_types<
|
||||
typename _ApplyFn::template __apply<__type_pack_element<_Idx, _Types...>>...
|
||||
>;
|
||||
};
|
||||
@ -380,19 +375,19 @@ struct __make_tuple_types
|
||||
|
||||
template <class ..._Types, size_t _Ep>
|
||||
struct __make_tuple_types<tuple<_Types...>, _Ep, 0, true> {
|
||||
typedef __tuple_types<_Types...> type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE __tuple_types<_Types...> type;
|
||||
};
|
||||
|
||||
template <class ..._Types, size_t _Ep>
|
||||
struct __make_tuple_types<__tuple_types<_Types...>, _Ep, 0, true> {
|
||||
typedef __tuple_types<_Types...> type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE __tuple_types<_Types...> type;
|
||||
};
|
||||
|
||||
template <bool ..._Preds>
|
||||
struct __all_dummy;
|
||||
|
||||
template <bool ..._Pred>
|
||||
using __all = is_same<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...>>;
|
||||
using __all = _IsSame<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...>>;
|
||||
|
||||
struct __tuple_sfinae_base {
|
||||
template <template <class, class...> class _Trait,
|
||||
@ -457,20 +452,16 @@ struct __tuple_assignable<_Tp, _Up, true, true>
|
||||
|
||||
|
||||
template <size_t _Ip, class ..._Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, tuple<_Tp...> >
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, tuple<_Tp...> >
|
||||
{
|
||||
public:
|
||||
typedef typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type;
|
||||
typedef _LIBCPP_NODEBUG_TYPE typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type;
|
||||
};
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
template <size_t _Ip, class ..._Tp>
|
||||
using tuple_element_t = typename tuple_element <_Ip, _Tp...>::type;
|
||||
using tuple_element_t _LIBCPP_NODEBUG_TYPE = typename tuple_element <_Ip, _Tp...>::type;
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <bool _IsTuple, class _SizeTrait, size_t _Expected>
|
||||
struct __tuple_like_with_size_imp : false_type {};
|
||||
|
||||
@ -480,14 +471,15 @@ struct __tuple_like_with_size_imp<true, _SizeTrait, _Expected>
|
||||
|
||||
template <class _Tuple, size_t _ExpectedSize,
|
||||
class _RawTuple = typename __uncvref<_Tuple>::type>
|
||||
using __tuple_like_with_size = __tuple_like_with_size_imp<
|
||||
using __tuple_like_with_size _LIBCPP_NODEBUG_TYPE = __tuple_like_with_size_imp<
|
||||
__tuple_like<_RawTuple>::value,
|
||||
tuple_size<_RawTuple>, _ExpectedSize
|
||||
>;
|
||||
|
||||
struct _LIBCPP_TYPE_VIS __check_tuple_constructor_fail {
|
||||
template <class ...>
|
||||
static constexpr bool __enable_default() { return false; }
|
||||
|
||||
static constexpr bool __enable_explicit_default() { return false; }
|
||||
static constexpr bool __enable_implicit_default() { return false; }
|
||||
template <class ...>
|
||||
static constexpr bool __enable_explicit() { return false; }
|
||||
template <class ...>
|
||||
@ -495,7 +487,7 @@ struct _LIBCPP_TYPE_VIS __check_tuple_constructor_fail {
|
||||
template <class ...>
|
||||
static constexpr bool __enable_assign() { return false; }
|
||||
};
|
||||
#endif
|
||||
#endif // !defined(_LIBCPP_CXX03_LANG)
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//===------------------------ __undef_macros ------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifdef min
|
||||
#if !defined(_LIBCPP_DISABLE_MACRO_CONFLICT_WARNINGS)
|
||||
#if defined(_LIBCPP_MSVC)
|
||||
#if defined(_LIBCPP_WARNING)
|
||||
_LIBCPP_WARNING("macro min is incompatible with C++. Try #define NOMINMAX "
|
||||
"before any Windows header. #undefing min")
|
||||
#else
|
||||
@ -22,7 +22,7 @@ _LIBCPP_WARNING("macro min is incompatible with C++. Try #define NOMINMAX "
|
||||
|
||||
#ifdef max
|
||||
#if !defined(_LIBCPP_DISABLE_MACRO_CONFLICT_WARNINGS)
|
||||
#if defined(_LIBCPP_MSVC)
|
||||
#if defined(_LIBCPP_WARNING)
|
||||
_LIBCPP_WARNING("macro max is incompatible with C++. Try #define NOMINMAX "
|
||||
"before any Windows header. #undefing max")
|
||||
#else
|
1099
include/algorithm
1099
include/algorithm
File diff suppressed because it is too large
Load Diff
52
include/any
52
include/any
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------------ any -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -45,6 +44,10 @@ namespace std {
|
||||
any& operator=(ValueType&& rhs);
|
||||
|
||||
// 6.3.3 any modifiers
|
||||
template <class ValueType, class... Args>
|
||||
decay_t<ValueType>& emplace(Args&&... args);
|
||||
template <class ValueType, class U, class... Args>
|
||||
decay_t<ValueType>& emplace(initializer_list<U>, Args&&...);
|
||||
void reset() noexcept;
|
||||
void swap(any& rhs) noexcept;
|
||||
|
||||
@ -73,8 +76,6 @@ namespace std {
|
||||
template<class ValueType>
|
||||
ValueType* any_cast(any* operand) noexcept;
|
||||
|
||||
} // namespace fundamentals_v1
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
*/
|
||||
@ -85,13 +86,14 @@ namespace std {
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
#include <cstdlib>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
class _LIBCPP_EXCEPTION_ABI bad_any_cast : public bad_cast
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast
|
||||
{
|
||||
public:
|
||||
virtual const char* what() const _NOEXCEPT;
|
||||
@ -102,13 +104,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
|
||||
_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
|
||||
void __throw_bad_any_cast()
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw bad_any_cast();
|
||||
#else
|
||||
_VSTD::abort();
|
||||
_VSTD::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -258,7 +261,7 @@ public:
|
||||
is_copy_constructible<_Tp>::value>
|
||||
>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void emplace(_Args&&... args);
|
||||
_Tp& emplace(_Args&&... args);
|
||||
|
||||
template <class _ValueType, class _Up, class ..._Args,
|
||||
class _Tp = decay_t<_ValueType>,
|
||||
@ -267,7 +270,7 @@ public:
|
||||
is_copy_constructible<_Tp>::value>
|
||||
>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void emplace(initializer_list<_Up>, _Args&&...);
|
||||
_Tp& emplace(initializer_list<_Up>, _Args&&...);
|
||||
|
||||
// 6.3.3 any modifiers
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -302,7 +305,7 @@ private:
|
||||
__any_imp::_Buffer __buf;
|
||||
};
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void * __call(_Action __a, any * __other = nullptr,
|
||||
type_info const * __info = nullptr,
|
||||
const void* __fallback_info = nullptr) const
|
||||
@ -310,7 +313,7 @@ private:
|
||||
return __h(__a, this, __other, __info, __fallback_info);
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void * __call(_Action __a, any * __other = nullptr,
|
||||
type_info const * __info = nullptr,
|
||||
const void* __fallback_info = nullptr)
|
||||
@ -364,9 +367,10 @@ namespace __any_imp
|
||||
|
||||
template <class ..._Args>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static void __create(any & __dest, _Args&&... __args) {
|
||||
::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...);
|
||||
static _Tp& __create(any & __dest, _Args&&... __args) {
|
||||
_Tp* __ret = ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...);
|
||||
__dest.__h = &_SmallHandler::__handle;
|
||||
return *__ret;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -439,14 +443,15 @@ namespace __any_imp
|
||||
|
||||
template <class ..._Args>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static void __create(any & __dest, _Args&&... __args) {
|
||||
static _Tp& __create(any & __dest, _Args&&... __args) {
|
||||
typedef allocator<_Tp> _Alloc;
|
||||
typedef __allocator_destructor<_Alloc> _Dp;
|
||||
_Alloc __a;
|
||||
unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
|
||||
::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...);
|
||||
_Tp* __ret = ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...);
|
||||
__dest.__s.__ptr = __hold.release();
|
||||
__dest.__h = &_LargeHandler::__handle;
|
||||
return *__ret;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -502,7 +507,7 @@ any::any(_ValueType && __v) : __h(nullptr)
|
||||
template <class _ValueType, class ..._Args, class _Tp, class>
|
||||
any::any(in_place_type_t<_ValueType>, _Args&&... __args) {
|
||||
__any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
|
||||
};
|
||||
}
|
||||
|
||||
template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
|
||||
any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) {
|
||||
@ -519,16 +524,16 @@ any & any::operator=(_ValueType && __v)
|
||||
|
||||
template <class _ValueType, class ..._Args, class _Tp, class>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void any::emplace(_Args&&... __args) {
|
||||
_Tp& any::emplace(_Args&&... __args) {
|
||||
reset();
|
||||
__any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
|
||||
return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
|
||||
_Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
|
||||
reset();
|
||||
__any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
|
||||
return __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -572,6 +577,7 @@ any make_any(initializer_list<_Up> __il, _Args&&... __args) {
|
||||
|
||||
template <class _ValueType>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
|
||||
_ValueType any_cast(any const & __v)
|
||||
{
|
||||
using _RawValueType = __uncvref_t<_ValueType>;
|
||||
@ -586,6 +592,7 @@ _ValueType any_cast(any const & __v)
|
||||
|
||||
template <class _ValueType>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
|
||||
_ValueType any_cast(any & __v)
|
||||
{
|
||||
using _RawValueType = __uncvref_t<_ValueType>;
|
||||
@ -600,6 +607,7 @@ _ValueType any_cast(any & __v)
|
||||
|
||||
template <class _ValueType>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
|
||||
_ValueType any_cast(any && __v)
|
||||
{
|
||||
using _RawValueType = __uncvref_t<_ValueType>;
|
||||
|
227
include/array
227
include/array
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------------- array -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -72,6 +71,9 @@ struct array
|
||||
const T* data() const noexcept;
|
||||
};
|
||||
|
||||
template <class T, class... U>
|
||||
array(T, U...) -> array<T, 1 + sizeof...(U)>;
|
||||
|
||||
template <class T, size_t N>
|
||||
bool operator==(const array<T,N>& x, const array<T,N>& y);
|
||||
template <class T, size_t N>
|
||||
@ -86,10 +88,10 @@ template <class T, size_t N>
|
||||
bool operator>=(const array<T,N>& x, const array<T,N>& y);
|
||||
|
||||
template <class T, size_t N >
|
||||
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y)));
|
||||
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // C++17
|
||||
|
||||
template <class T> class tuple_size;
|
||||
template <size_t I, class T> class tuple_element;
|
||||
template <class T> struct tuple_size;
|
||||
template <size_t I, class T> struct tuple_element;
|
||||
template <class T, size_t N> struct tuple_size<array<T, N>>;
|
||||
template <size_t I, class T, size_t N> struct tuple_element<I, array<T, N>>;
|
||||
template <size_t I, class T, size_t N> T& get(array<T, N>&) noexcept; // constexpr in C++14
|
||||
@ -108,13 +110,19 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib> // for _LIBCPP_UNREACHABLE
|
||||
#include <version>
|
||||
#include <__debug>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
struct _LIBCPP_TEMPLATE_VIS array
|
||||
{
|
||||
@ -132,31 +140,27 @@ struct _LIBCPP_TEMPLATE_VIS array
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
value_type __elems_[_Size > 0 ? _Size : 1];
|
||||
_Tp __elems_[_Size];
|
||||
|
||||
// No explicit construct/copy/destroy for aggregate type
|
||||
_LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u)
|
||||
{_VSTD::fill_n(__elems_, _Size, __u);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(array& __a) _NOEXCEPT_(_Size == 0 || __is_nothrow_swappable<_Tp>::value)
|
||||
{ __swap_dispatch((std::integral_constant<bool, _Size == 0>()), __a); }
|
||||
_LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u) {
|
||||
_VSTD::fill_n(__elems_, _Size, __u);
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_dispatch(std::true_type, array&) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_dispatch(std::false_type, array& __a)
|
||||
{ _VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);}
|
||||
void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
|
||||
std::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);
|
||||
}
|
||||
|
||||
// iterators:
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
iterator begin() _NOEXCEPT {return iterator(__elems_);}
|
||||
iterator begin() _NOEXCEPT {return iterator(data());}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
const_iterator begin() const _NOEXCEPT {return const_iterator(__elems_);}
|
||||
const_iterator begin() const _NOEXCEPT {return const_iterator(data());}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
iterator end() _NOEXCEPT {return iterator(__elems_ + _Size);}
|
||||
iterator end() _NOEXCEPT {return iterator(data() + _Size);}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
const_iterator end() const _NOEXCEPT {return const_iterator(__elems_ + _Size);}
|
||||
const_iterator end() const _NOEXCEPT {return const_iterator(data() + _Size);}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
|
||||
@ -181,22 +185,22 @@ struct _LIBCPP_TEMPLATE_VIS array
|
||||
_LIBCPP_CONSTEXPR size_type size() const _NOEXCEPT {return _Size;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return _Size;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return _Size == 0;}
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return false; }
|
||||
|
||||
// element access:
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
reference operator[](size_type __n) {return __elems_[__n];}
|
||||
reference operator[](size_type __n) _NOEXCEPT {return __elems_[__n];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const_reference operator[](size_type __n) const {return __elems_[__n];}
|
||||
const_reference operator[](size_type __n) const _NOEXCEPT {return __elems_[__n];}
|
||||
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX14 reference at(size_type __n);
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference at(size_type __n) const;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference front() {return __elems_[0];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const {return __elems_[0];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference back() {return __elems_[_Size > 0 ? _Size-1 : 0];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const {return __elems_[_Size > 0 ? _Size-1 : 0];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference front() _NOEXCEPT {return __elems_[0];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const _NOEXCEPT {return __elems_[0];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference back() _NOEXCEPT {return __elems_[_Size - 1];}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const _NOEXCEPT {return __elems_[_Size - 1];}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
value_type* data() _NOEXCEPT {return __elems_;}
|
||||
@ -204,6 +208,7 @@ struct _LIBCPP_TEMPLATE_VIS array
|
||||
const value_type* data() const _NOEXCEPT {return __elems_;}
|
||||
};
|
||||
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
typename array<_Tp, _Size>::reference
|
||||
@ -225,17 +230,152 @@ array<_Tp, _Size>::at(size_type __n) const
|
||||
return __elems_[__n];
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
|
||||
{
|
||||
// types:
|
||||
typedef array __self;
|
||||
typedef _Tp value_type;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
typedef typename conditional<is_const<_Tp>::value, const char,
|
||||
char>::type _CharType;
|
||||
|
||||
struct _ArrayInStructT { _Tp __data_[1]; };
|
||||
_ALIGNAS_TYPE(_ArrayInStructT) _CharType __elems_[sizeof(_ArrayInStructT)];
|
||||
|
||||
// No explicit construct/copy/destroy for aggregate type
|
||||
_LIBCPP_INLINE_VISIBILITY void fill(const value_type&) {
|
||||
static_assert(!is_const<_Tp>::value,
|
||||
"cannot fill zero-sized array of type 'const T'");
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(array&) _NOEXCEPT {
|
||||
static_assert(!is_const<_Tp>::value,
|
||||
"cannot swap zero-sized array of type 'const T'");
|
||||
}
|
||||
|
||||
// iterators:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator begin() _NOEXCEPT {return iterator(data());}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_iterator begin() const _NOEXCEPT {return const_iterator(data());}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator end() _NOEXCEPT {return iterator(data());}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_iterator end() const _NOEXCEPT {return const_iterator(data());}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_iterator cbegin() const _NOEXCEPT {return begin();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_iterator cend() const _NOEXCEPT {return end();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_reverse_iterator crend() const _NOEXCEPT {return rend();}
|
||||
|
||||
// capacity:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR size_type size() const _NOEXCEPT {return 0; }
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return 0;}
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return true;}
|
||||
|
||||
// element access:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference operator[](size_type) _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
const_reference operator[](size_type) const _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference at(size_type) {
|
||||
__throw_out_of_range("array<T, 0>::at");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_reference at(size_type) const {
|
||||
__throw_out_of_range("array<T, 0>::at");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference front() _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_reference front() const _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
reference back() _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const_reference back() const _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
value_type* data() _NOEXCEPT {return reinterpret_cast<value_type*>(__elems_);}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
const value_type* data() const _NOEXCEPT {return reinterpret_cast<const value_type*>(__elems_);}
|
||||
};
|
||||
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
|
||||
template<class _Tp, class... _Args,
|
||||
class = typename enable_if<(is_same_v<_Tp, _Args> && ...), void>::type
|
||||
>
|
||||
array(_Tp, _Args...)
|
||||
-> array<_Tp, 1 + sizeof...(_Args)>;
|
||||
#endif
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
|
||||
operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
{
|
||||
return _VSTD::equal(__x.__elems_, __x.__elems_ + _Size, __y.__elems_);
|
||||
return _VSTD::equal(__x.begin(), __x.end(), __y.begin());
|
||||
}
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
|
||||
operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
{
|
||||
return !(__x == __y);
|
||||
@ -243,15 +383,16 @@ operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
|
||||
operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
{
|
||||
return _VSTD::lexicographical_compare(__x.__elems_, __x.__elems_ + _Size, __y.__elems_, __y.__elems_ + _Size);
|
||||
return _VSTD::lexicographical_compare(__x.begin(), __x.end(),
|
||||
__y.begin(), __y.end());
|
||||
}
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
|
||||
operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
{
|
||||
return __y < __x;
|
||||
@ -259,7 +400,7 @@ operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
|
||||
operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
{
|
||||
return !(__y < __x);
|
||||
@ -267,7 +408,7 @@ operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
|
||||
operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||
{
|
||||
return !(__x < __y);
|
||||
@ -288,13 +429,13 @@ swap(array<_Tp, _Size>& __x, array<_Tp, _Size>& __y)
|
||||
}
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_size<array<_Tp, _Size> >
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_size<array<_Tp, _Size> >
|
||||
: public integral_constant<size_t, _Size> {};
|
||||
|
||||
template <size_t _Ip, class _Tp, size_t _Size>
|
||||
class _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, array<_Tp, _Size> >
|
||||
struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, array<_Tp, _Size> >
|
||||
{
|
||||
public:
|
||||
static_assert(_Ip < _Size, "Index out of bounds in std::tuple_element<> (std::array)");
|
||||
typedef _Tp type;
|
||||
};
|
||||
|
||||
@ -316,7 +457,7 @@ get(const array<_Tp, _Size>& __a) _NOEXCEPT
|
||||
return __a.__elems_[_Ip];
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <size_t _Ip, class _Tp, size_t _Size>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
@ -336,7 +477,7 @@ get(const array<_Tp, _Size>&& __a) _NOEXCEPT
|
||||
return _VSTD::move(__a.__elems_[_Ip]);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#endif // !_LIBCPP_CXX03_LANG
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
1117
include/atomic
1117
include/atomic
File diff suppressed because it is too large
Load Diff
486
include/bit
Normal file
486
include/bit
Normal file
@ -0,0 +1,486 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------------ bit ----------------------------------===//
|
||||
//
|
||||
// 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
|
||||
#define _LIBCPP_BIT
|
||||
|
||||
/*
|
||||
bit synopsis
|
||||
|
||||
namespace std {
|
||||
|
||||
template <class T>
|
||||
constexpr bool ispow2(T x) noexcept; // C++20
|
||||
template <class T>
|
||||
constexpr T ceil2(T x); // C++20
|
||||
template <class T>
|
||||
constexpr T floor2(T x) noexcept; // C++20
|
||||
template <class T>
|
||||
constexpr T log2p1(T x) noexcept; // C++20
|
||||
|
||||
// 23.20.2, rotating
|
||||
template<class T>
|
||||
constexpr T rotl(T x, unsigned int s) noexcept; // C++20
|
||||
template<class T>
|
||||
constexpr T rotr(T x, unsigned int s) noexcept; // C++20
|
||||
|
||||
// 23.20.3, counting
|
||||
template<class T>
|
||||
constexpr int countl_zero(T x) noexcept; // C++20
|
||||
template<class T>
|
||||
constexpr int countl_one(T x) noexcept; // C++20
|
||||
template<class T>
|
||||
constexpr int countr_zero(T x) noexcept; // C++20
|
||||
template<class T>
|
||||
constexpr int countr_one(T x) noexcept; // C++20
|
||||
template<class T>
|
||||
constexpr int popcount(T x) noexcept; // C++20
|
||||
|
||||
// 20.15.9, endian
|
||||
enum class endian {
|
||||
little = see below, // C++20
|
||||
big = see below, // C++20
|
||||
native = see below // C++20
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <version>
|
||||
#include <__debug>
|
||||
|
||||
#if defined(__IBMCPP__)
|
||||
#include "support/ibm/support.h"
|
||||
#endif
|
||||
#if defined(_LIBCPP_COMPILER_MSVC)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
|
||||
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); }
|
||||
|
||||
|
||||
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); }
|
||||
|
||||
#else // _LIBCPP_COMPILER_MSVC
|
||||
|
||||
// Precondition: __x != 0
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_ctz(unsigned __x) {
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
unsigned long __where;
|
||||
if (_BitScanForward(&__where, __x))
|
||||
return static_cast<int>(__where);
|
||||
return 32;
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_ctz(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned long) == sizeof(unsigned), "");
|
||||
return __ctz(static_cast<unsigned>(__x));
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_ctz(unsigned long long __x) {
|
||||
unsigned long __where;
|
||||
#if defined(_LIBCPP_HAS_BITSCAN64)
|
||||
(defined(_M_AMD64) || defined(__x86_64__))
|
||||
if (_BitScanForward64(&__where, __x))
|
||||
return static_cast<int>(__where);
|
||||
#else
|
||||
// Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
|
||||
if (_BitScanForward(&__where, static_cast<unsigned long>(__x)))
|
||||
return static_cast<int>(__where);
|
||||
if (_BitScanForward(&__where, static_cast<unsigned long>(__x >> 32)))
|
||||
return static_cast<int>(__where + 32);
|
||||
#endif
|
||||
return 64;
|
||||
}
|
||||
|
||||
// Precondition: __x != 0
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_clz(unsigned __x) {
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
unsigned long __where;
|
||||
if (_BitScanReverse(&__where, __x))
|
||||
return static_cast<int>(31 - __where);
|
||||
return 32; // Undefined Behavior.
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_clz(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
return __libcpp_clz(static_cast<unsigned>(__x));
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __libcpp_clz(unsigned long long __x) {
|
||||
unsigned long __where;
|
||||
#if defined(_LIBCPP_HAS_BITSCAN64)
|
||||
if (_BitScanReverse64(&__where, __x))
|
||||
return static_cast<int>(63 - __where);
|
||||
#else
|
||||
// Win32 doesn't have _BitScanReverse64 so emulate it with two 32 bit calls.
|
||||
if (_BitScanReverse(&__where, static_cast<unsigned long>(__x >> 32)))
|
||||
return static_cast<int>(63 - (__where + 32));
|
||||
if (_BitScanReverse(&__where, static_cast<unsigned long>(__x)))
|
||||
return static_cast<int>(63 - __where);
|
||||
#endif
|
||||
return 64; // Undefined Behavior.
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned __x) {
|
||||
static_assert(sizeof(unsigned) == 4, "");
|
||||
return __popcnt(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
return __popcnt(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long long __x) {
|
||||
static_assert(sizeof(unsigned long long) == 8, "");
|
||||
return __popcnt64(__x);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_COMPILER_MSVC
|
||||
|
||||
template <class _Tp>
|
||||
using __bitop_unsigned_integer _LIBCPP_NODEBUG_TYPE = integral_constant<bool,
|
||||
is_integral<_Tp>::value &&
|
||||
is_unsigned<_Tp>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, bool>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, signed char>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, wchar_t>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, char16_t>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, char32_t>::value
|
||||
>;
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_Tp __rotl(_Tp __t, unsigned int __cnt) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__rotl requires unsigned");
|
||||
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_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__rotr requires unsigned");
|
||||
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_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countr_zero(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countr_zero requires unsigned");
|
||||
if (__t == 0)
|
||||
return numeric_limits<_Tp>::digits;
|
||||
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __libcpp_ctz(static_cast<unsigned int>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __libcpp_ctz(static_cast<unsigned long>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __libcpp_ctz(static_cast<unsigned long long>(__t));
|
||||
else
|
||||
{
|
||||
int __ret = 0;
|
||||
int __iter = 0;
|
||||
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
|
||||
while ((__iter = __libcpp_ctz(static_cast<unsigned long long>(__t))) == __ulldigits)
|
||||
{
|
||||
__ret += __iter;
|
||||
__t >>= __ulldigits;
|
||||
}
|
||||
return __ret + __iter;
|
||||
}
|
||||
}
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countl_zero(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countl_zero requires unsigned");
|
||||
if (__t == 0)
|
||||
return numeric_limits<_Tp>::digits;
|
||||
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __libcpp_clz(static_cast<unsigned int>(__t))
|
||||
- (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits);
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __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 __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 = __rotr(__t, __ulldigits);
|
||||
if ((__iter = __countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits)
|
||||
break;
|
||||
__ret += __iter;
|
||||
}
|
||||
return __ret + __iter;
|
||||
}
|
||||
}
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countl_one(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countl_one requires unsigned");
|
||||
return __t != numeric_limits<_Tp>::max()
|
||||
? __countl_zero(static_cast<_Tp>(~__t))
|
||||
: numeric_limits<_Tp>::digits;
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countr_one(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countr_one requires unsigned");
|
||||
return __t != numeric_limits<_Tp>::max()
|
||||
? __countr_zero(static_cast<_Tp>(~__t))
|
||||
: numeric_limits<_Tp>::digits;
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int
|
||||
__popcount(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__libcpp_popcount requires unsigned");
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __libcpp_popcount(static_cast<unsigned int>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __libcpp_popcount(static_cast<unsigned long>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __libcpp_popcount(static_cast<unsigned long long>(__t));
|
||||
else
|
||||
{
|
||||
int __ret = 0;
|
||||
while (__t != 0)
|
||||
{
|
||||
__ret += __libcpp_popcount(static_cast<unsigned long long>(__t));
|
||||
__t >>= numeric_limits<unsigned long long>::digits;
|
||||
}
|
||||
return __ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// integral log base 2
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
unsigned __bit_log2(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__bit_log2 requires unsigned");
|
||||
return std::numeric_limits<_Tp>::digits - 1 - __countl_zero(__t);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
bool __ispow2(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__ispow2 requires unsigned");
|
||||
return __t != 0 && (((__t & (__t - 1)) == 0));
|
||||
}
|
||||
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
rotl(_Tp __t, unsigned int __cnt) noexcept
|
||||
{
|
||||
return __rotl(__t, __cnt);
|
||||
}
|
||||
|
||||
|
||||
// rotr
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
rotr(_Tp __t, unsigned int __cnt) noexcept
|
||||
{
|
||||
return __rotr(__t, __cnt);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countl_zero(_Tp __t) noexcept
|
||||
{
|
||||
return __countl_zero(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countl_one(_Tp __t) noexcept
|
||||
{
|
||||
return __countl_one(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countr_zero(_Tp __t) noexcept
|
||||
{
|
||||
return __countr_zero(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countr_one(_Tp __t) noexcept
|
||||
{
|
||||
return __countr_one(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
popcount(_Tp __t) noexcept
|
||||
{
|
||||
return __popcount(__t);
|
||||
}
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, bool>
|
||||
ispow2(_Tp __t) noexcept
|
||||
{
|
||||
return __ispow2(__t);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
floor2(_Tp __t) noexcept
|
||||
{
|
||||
return __t == 0 ? 0 : _Tp{1} << __bit_log2(__t);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
ceil2(_Tp __t) noexcept
|
||||
{
|
||||
if (__t < 2) return 1;
|
||||
const unsigned __n = numeric_limits<_Tp>::digits - countl_zero((_Tp)(__t - 1u));
|
||||
_LIBCPP_DEBUG_ASSERT(__libcpp_is_constant_evaluated() || __n != numeric_limits<_Tp>::digits, "Bad input to ceil2");
|
||||
|
||||
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 <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
log2p1(_Tp __t) noexcept
|
||||
{
|
||||
return __t == 0 ? 0 : __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
|
||||
|
||||
#endif // _LIBCPP_BIT
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------------- bitset ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -113,10 +112,6 @@ template <size_t N> struct hash<std::bitset<N>>;
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include <__config>
|
||||
#include <__bit_reference>
|
||||
#include <cstddef>
|
||||
@ -126,7 +121,13 @@ template <size_t N> struct hash<std::bitset<N>>;
|
||||
#include <iosfwd>
|
||||
#include <__functional_base>
|
||||
|
||||
#include <__undef_min_max>
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
@ -197,11 +198,11 @@ protected:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
size_t __hash_code() const _NOEXCEPT;
|
||||
private:
|
||||
#ifdef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#ifdef _LIBCPP_CXX03_LANG
|
||||
void __init(unsigned long long __v, false_type) _NOEXCEPT;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __init(unsigned long long __v, true_type) _NOEXCEPT;
|
||||
#endif // _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
unsigned long to_ulong(false_type) const;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
unsigned long to_ulong(true_type) const;
|
||||
@ -217,24 +218,29 @@ template <size_t _N_words, size_t _Size>
|
||||
inline
|
||||
_LIBCPP_CONSTEXPR
|
||||
__bitset<_N_words, _Size>::__bitset() _NOEXCEPT
|
||||
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
: __first_{0}
|
||||
#endif
|
||||
{
|
||||
#ifdef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#ifdef _LIBCPP_CXX03_LANG
|
||||
_VSTD::fill_n(__first_, _N_words, __storage_type(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#ifdef _LIBCPP_CXX03_LANG
|
||||
|
||||
template <size_t _N_words, size_t _Size>
|
||||
void
|
||||
__bitset<_N_words, _Size>::__init(unsigned long long __v, false_type) _NOEXCEPT
|
||||
{
|
||||
__storage_type __t[sizeof(unsigned long long) / sizeof(__storage_type)];
|
||||
for (size_t __i = 0; __i < sizeof(__t)/sizeof(__t[0]); ++__i, __v >>= __bits_per_word)
|
||||
__t[__i] = static_cast<__storage_type>(__v);
|
||||
size_t __sz = _Size;
|
||||
for (size_t __i = 0; __i < sizeof(__t)/sizeof(__t[0]); ++__i, __v >>= __bits_per_word, __sz -= __bits_per_word )
|
||||
if ( __sz < __bits_per_word)
|
||||
__t[__i] = static_cast<__storage_type>(__v) & ( 1ULL << __sz ) - 1;
|
||||
else
|
||||
__t[__i] = static_cast<__storage_type>(__v);
|
||||
|
||||
_VSTD::copy(__t, __t + sizeof(__t)/sizeof(__t[0]), __first_);
|
||||
_VSTD::fill(__first_ + sizeof(__t)/sizeof(__t[0]), __first_ + sizeof(__first_)/sizeof(__first_[0]),
|
||||
__storage_type(0));
|
||||
@ -246,26 +252,31 @@ void
|
||||
__bitset<_N_words, _Size>::__init(unsigned long long __v, true_type) _NOEXCEPT
|
||||
{
|
||||
__first_[0] = __v;
|
||||
if (_Size < __bits_per_word)
|
||||
__first_[0] &= ( 1ULL << _Size ) - 1;
|
||||
|
||||
_VSTD::fill(__first_ + 1, __first_ + sizeof(__first_)/sizeof(__first_[0]), __storage_type(0));
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
template <size_t _N_words, size_t _Size>
|
||||
inline
|
||||
_LIBCPP_CONSTEXPR
|
||||
__bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
|
||||
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
#if __SIZEOF_SIZE_T__ == 8
|
||||
: __first_{__v}
|
||||
#elif __SIZEOF_SIZE_T__ == 4
|
||||
: __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
|
||||
: __first_{static_cast<__storage_type>(__v),
|
||||
_Size >= 2 * __bits_per_word ? static_cast<__storage_type>(__v >> __bits_per_word)
|
||||
: static_cast<__storage_type>((__v >> __bits_per_word) & (__storage_type(1) << (_Size - __bits_per_word)) - 1)}
|
||||
#else
|
||||
#error This constructor has not been ported to this platform
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#ifdef _LIBCPP_HAS_NO_CONSTEXPR
|
||||
#ifdef _LIBCPP_CXX03_LANG
|
||||
__init(__v, integral_constant<bool, sizeof(unsigned long long) == sizeof(__storage_type)>());
|
||||
#endif
|
||||
}
|
||||
@ -501,7 +512,10 @@ template <size_t _Size>
|
||||
inline
|
||||
_LIBCPP_CONSTEXPR
|
||||
__bitset<1, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
|
||||
: __first_(static_cast<__storage_type>(__v))
|
||||
: __first_(
|
||||
_Size == __bits_per_word ? static_cast<__storage_type>(__v)
|
||||
: static_cast<__storage_type>(__v) & ((__storage_type(1) << _Size) - 1)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
@ -665,7 +679,7 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bitset() _NOEXCEPT {}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
bitset(unsigned long long __v) _NOEXCEPT : base(__v) {}
|
||||
template<class _CharT>
|
||||
template<class _CharT, class = _EnableIf<_IsCharLikeType<_CharT>::value> >
|
||||
explicit bitset(const _CharT* __str,
|
||||
typename basic_string<_CharT>::size_type __n = basic_string<_CharT>::npos,
|
||||
_CharT __zero = _CharT('0'), _CharT __one = _CharT('1'));
|
||||
@ -746,7 +760,7 @@ private:
|
||||
};
|
||||
|
||||
template <size_t _Size>
|
||||
template<class _CharT>
|
||||
template<class _CharT, class>
|
||||
bitset<_Size>::bitset(const _CharT* __str,
|
||||
typename basic_string<_CharT>::size_type __n,
|
||||
_CharT __zero, _CharT __one)
|
||||
@ -976,7 +990,7 @@ inline
|
||||
size_t
|
||||
bitset<_Size>::count() const _NOEXCEPT
|
||||
{
|
||||
return static_cast<size_t>(_VSTD::count(base::__make_iter(0), base::__make_iter(_Size), true));
|
||||
return static_cast<size_t>(__count_bool_true(base::__make_iter(0), _Size));
|
||||
}
|
||||
|
||||
template <size_t _Size>
|
||||
@ -1090,4 +1104,6 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x);
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_BITSET
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===-------------------------- cassert -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- ccomplex ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------------- cctype ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===-------------------------- cerrno ------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------------- cfenv -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- cfloat -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -20,11 +19,18 @@ Macros:
|
||||
FLT_EVAL_METHOD // C99
|
||||
FLT_RADIX
|
||||
|
||||
FLT_HAS_SUBNORM // C11
|
||||
DBL_HAS_SUBNORM // C11
|
||||
LDBL_HAS_SUBNORM // C11
|
||||
|
||||
FLT_MANT_DIG
|
||||
DBL_MANT_DIG
|
||||
LDBL_MANT_DIG
|
||||
|
||||
DECIMAL_DIG // C99
|
||||
FLT_DECIMAL_DIG // C11
|
||||
DBL_DECIMAL_DIG // C11
|
||||
LDBL_DECIMAL_DIG // C11
|
||||
|
||||
FLT_DIG
|
||||
DBL_DIG
|
||||
@ -58,6 +64,9 @@ Macros:
|
||||
DBL_MIN
|
||||
LDBL_MIN
|
||||
|
||||
FLT_TRUE_MIN // C11
|
||||
DBL_TRUE_MIN // C11
|
||||
LDBL_TRUE_MIN // C11
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
|
616
include/charconv
Normal file
616
include/charconv
Normal file
@ -0,0 +1,616 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------------ charconv ------------------------------===//
|
||||
//
|
||||
// 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_CHARCONV
|
||||
#define _LIBCPP_CHARCONV
|
||||
|
||||
/*
|
||||
charconv synopsis
|
||||
|
||||
namespace std {
|
||||
|
||||
// floating-point format for primitive numerical conversion
|
||||
enum class chars_format {
|
||||
scientific = unspecified,
|
||||
fixed = unspecified,
|
||||
hex = unspecified,
|
||||
general = fixed | scientific
|
||||
};
|
||||
|
||||
// 23.20.2, primitive numerical output conversion
|
||||
struct to_chars_result {
|
||||
char* ptr;
|
||||
errc ec;
|
||||
};
|
||||
|
||||
to_chars_result to_chars(char* first, char* last, see below value,
|
||||
int base = 10);
|
||||
|
||||
to_chars_result to_chars(char* first, char* last, float value);
|
||||
to_chars_result to_chars(char* first, char* last, double value);
|
||||
to_chars_result to_chars(char* first, char* last, long double value);
|
||||
|
||||
to_chars_result to_chars(char* first, char* last, float value,
|
||||
chars_format fmt);
|
||||
to_chars_result to_chars(char* first, char* last, double value,
|
||||
chars_format fmt);
|
||||
to_chars_result to_chars(char* first, char* last, long double value,
|
||||
chars_format fmt);
|
||||
|
||||
to_chars_result to_chars(char* first, char* last, float value,
|
||||
chars_format fmt, int precision);
|
||||
to_chars_result to_chars(char* first, char* last, double value,
|
||||
chars_format fmt, int precision);
|
||||
to_chars_result to_chars(char* first, char* last, long double value,
|
||||
chars_format fmt, int precision);
|
||||
|
||||
// 23.20.3, primitive numerical input conversion
|
||||
struct from_chars_result {
|
||||
const char* ptr;
|
||||
errc ec;
|
||||
};
|
||||
|
||||
from_chars_result from_chars(const char* first, const char* last,
|
||||
see below& value, int base = 10);
|
||||
|
||||
from_chars_result from_chars(const char* first, const char* last,
|
||||
float& value,
|
||||
chars_format fmt = chars_format::general);
|
||||
from_chars_result from_chars(const char* first, const char* last,
|
||||
double& value,
|
||||
chars_format fmt = chars_format::general);
|
||||
from_chars_result from_chars(const char* first, const char* last,
|
||||
long double& value,
|
||||
chars_format fmt = chars_format::general);
|
||||
|
||||
} // namespace std
|
||||
|
||||
*/
|
||||
|
||||
#include <__errc>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <__debug>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace __itoa {
|
||||
_LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer);
|
||||
_LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer);
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
enum class _LIBCPP_ENUM_VIS chars_format
|
||||
{
|
||||
scientific = 0x1,
|
||||
fixed = 0x2,
|
||||
hex = 0x4,
|
||||
general = fixed | scientific
|
||||
};
|
||||
|
||||
struct _LIBCPP_TYPE_VIS to_chars_result
|
||||
{
|
||||
char* ptr;
|
||||
errc ec;
|
||||
};
|
||||
|
||||
struct _LIBCPP_TYPE_VIS from_chars_result
|
||||
{
|
||||
const char* ptr;
|
||||
errc ec;
|
||||
};
|
||||
|
||||
void to_chars(char*, char*, bool, int = 10) = delete;
|
||||
void from_chars(const char*, const char*, bool, int = 10) = delete;
|
||||
|
||||
namespace __itoa
|
||||
{
|
||||
|
||||
static _LIBCPP_CONSTEXPR uint64_t __pow10_64[] = {
|
||||
UINT64_C(0),
|
||||
UINT64_C(10),
|
||||
UINT64_C(100),
|
||||
UINT64_C(1000),
|
||||
UINT64_C(10000),
|
||||
UINT64_C(100000),
|
||||
UINT64_C(1000000),
|
||||
UINT64_C(10000000),
|
||||
UINT64_C(100000000),
|
||||
UINT64_C(1000000000),
|
||||
UINT64_C(10000000000),
|
||||
UINT64_C(100000000000),
|
||||
UINT64_C(1000000000000),
|
||||
UINT64_C(10000000000000),
|
||||
UINT64_C(100000000000000),
|
||||
UINT64_C(1000000000000000),
|
||||
UINT64_C(10000000000000000),
|
||||
UINT64_C(100000000000000000),
|
||||
UINT64_C(1000000000000000000),
|
||||
UINT64_C(10000000000000000000),
|
||||
};
|
||||
|
||||
static _LIBCPP_CONSTEXPR uint32_t __pow10_32[] = {
|
||||
UINT32_C(0), UINT32_C(10), UINT32_C(100),
|
||||
UINT32_C(1000), UINT32_C(10000), UINT32_C(100000),
|
||||
UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000),
|
||||
UINT32_C(1000000000),
|
||||
};
|
||||
|
||||
template <typename _Tp, typename = void>
|
||||
struct _LIBCPP_HIDDEN __traits_base
|
||||
{
|
||||
using type = uint64_t;
|
||||
|
||||
#if !defined(_LIBCPP_COMPILER_MSVC)
|
||||
static _LIBCPP_INLINE_VISIBILITY int __width(_Tp __v)
|
||||
{
|
||||
auto __t = (64 - __builtin_clzll(__v | 1)) * 1233 >> 12;
|
||||
return __t - (__v < __pow10_64[__t]) + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p)
|
||||
{
|
||||
return __u64toa(__v, __p);
|
||||
}
|
||||
|
||||
static _LIBCPP_INLINE_VISIBILITY decltype(__pow10_64)& __pow() { return __pow10_64; }
|
||||
};
|
||||
|
||||
template <typename _Tp>
|
||||
struct _LIBCPP_HIDDEN
|
||||
__traits_base<_Tp, decltype(void(uint32_t{declval<_Tp>()}))>
|
||||
{
|
||||
using type = uint32_t;
|
||||
|
||||
#if !defined(_LIBCPP_COMPILER_MSVC)
|
||||
static _LIBCPP_INLINE_VISIBILITY int __width(_Tp __v)
|
||||
{
|
||||
auto __t = (32 - __builtin_clz(__v | 1)) * 1233 >> 12;
|
||||
return __t - (__v < __pow10_32[__t]) + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p)
|
||||
{
|
||||
return __u32toa(__v, __p);
|
||||
}
|
||||
|
||||
static _LIBCPP_INLINE_VISIBILITY decltype(__pow10_32)& __pow() { return __pow10_32; }
|
||||
};
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool
|
||||
__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r)
|
||||
{
|
||||
auto __c = __a * __b;
|
||||
__r = __c;
|
||||
return __c > (numeric_limits<unsigned char>::max)();
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool
|
||||
__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r)
|
||||
{
|
||||
auto __c = __a * __b;
|
||||
__r = __c;
|
||||
return __c > (numeric_limits<unsigned short>::max)();
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool
|
||||
__mul_overflowed(_Tp __a, _Tp __b, _Tp& __r)
|
||||
{
|
||||
static_assert(is_unsigned<_Tp>::value, "");
|
||||
#if !defined(_LIBCPP_COMPILER_MSVC)
|
||||
return __builtin_mul_overflow(__a, __b, &__r);
|
||||
#else
|
||||
bool __did = __b && ((numeric_limits<_Tp>::max)() / __b) < __a;
|
||||
__r = __a * __b;
|
||||
return __did;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename _Tp, typename _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool
|
||||
__mul_overflowed(_Tp __a, _Up __b, _Tp& __r)
|
||||
{
|
||||
return __mul_overflowed(__a, static_cast<_Tp>(__b), __r);
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp>
|
||||
{
|
||||
static _LIBCPP_CONSTEXPR int digits = numeric_limits<_Tp>::digits10 + 1;
|
||||
using __traits_base<_Tp>::__pow;
|
||||
using typename __traits_base<_Tp>::type;
|
||||
|
||||
// precondition: at least one non-zero character available
|
||||
static _LIBCPP_INLINE_VISIBILITY char const*
|
||||
__read(char const* __p, char const* __ep, type& __a, type& __b)
|
||||
{
|
||||
type __cprod[digits];
|
||||
int __j = digits - 1;
|
||||
int __i = digits;
|
||||
do
|
||||
{
|
||||
if (!('0' <= *__p && *__p <= '9'))
|
||||
break;
|
||||
__cprod[--__i] = *__p++ - '0';
|
||||
} while (__p != __ep && __i != 0);
|
||||
|
||||
__a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1,
|
||||
__cprod[__i]);
|
||||
if (__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b))
|
||||
--__p;
|
||||
return __p;
|
||||
}
|
||||
|
||||
template <typename _It1, typename _It2, class _Up>
|
||||
static _LIBCPP_INLINE_VISIBILITY _Up
|
||||
__inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init)
|
||||
{
|
||||
for (; __first1 < __last1; ++__first1, ++__first2)
|
||||
__init = __init + *__first1 * *__first2;
|
||||
return __init;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace __itoa
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _Tp
|
||||
__complement(_Tp __x)
|
||||
{
|
||||
static_assert(is_unsigned<_Tp>::value, "cast to unsigned first");
|
||||
return _Tp(~__x + 1);
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY typename make_unsigned<_Tp>::type
|
||||
__to_unsigned(_Tp __x)
|
||||
{
|
||||
return static_cast<typename make_unsigned<_Tp>::type>(__x);
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
|
||||
__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type)
|
||||
{
|
||||
auto __x = __to_unsigned(__value);
|
||||
if (__value < 0 && __first != __last)
|
||||
{
|
||||
*__first++ = '-';
|
||||
__x = __complement(__x);
|
||||
}
|
||||
|
||||
return __to_chars_itoa(__first, __last, __x, false_type());
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
|
||||
__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type)
|
||||
{
|
||||
using __tx = __itoa::__traits<_Tp>;
|
||||
auto __diff = __last - __first;
|
||||
|
||||
#if !defined(_LIBCPP_COMPILER_MSVC)
|
||||
if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)
|
||||
return {__tx::__convert(__value, __first), errc(0)};
|
||||
else
|
||||
return {__last, errc::value_too_large};
|
||||
#else
|
||||
if (__tx::digits <= __diff)
|
||||
return {__tx::__convert(__value, __first), {}};
|
||||
else
|
||||
{
|
||||
char __buf[__tx::digits];
|
||||
auto __p = __tx::__convert(__value, __buf);
|
||||
auto __len = __p - __buf;
|
||||
if (__len <= __diff)
|
||||
{
|
||||
memcpy(__first, __buf, __len);
|
||||
return {__first + __len, {}};
|
||||
}
|
||||
else
|
||||
return {__last, errc::value_too_large};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
|
||||
true_type)
|
||||
{
|
||||
auto __x = __to_unsigned(__value);
|
||||
if (__value < 0 && __first != __last)
|
||||
{
|
||||
*__first++ = '-';
|
||||
__x = __complement(__x);
|
||||
}
|
||||
|
||||
return __to_chars_integral(__first, __last, __x, __base, false_type());
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
|
||||
false_type)
|
||||
{
|
||||
if (__base == 10)
|
||||
return __to_chars_itoa(__first, __last, __value, false_type());
|
||||
|
||||
auto __p = __last;
|
||||
while (__p != __first)
|
||||
{
|
||||
auto __c = __value % __base;
|
||||
__value /= __base;
|
||||
*--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c];
|
||||
if (__value == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
auto __len = __last - __p;
|
||||
if (__value != 0 || !__len)
|
||||
return {__last, errc::value_too_large};
|
||||
else
|
||||
{
|
||||
memmove(__first, __p, __len);
|
||||
return {__first + __len, {}};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
|
||||
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
|
||||
to_chars(char* __first, char* __last, _Tp __value)
|
||||
{
|
||||
return __to_chars_itoa(__first, __last, __value, is_signed<_Tp>());
|
||||
}
|
||||
|
||||
template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
|
||||
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
|
||||
to_chars(char* __first, char* __last, _Tp __value, int __base)
|
||||
{
|
||||
_LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]");
|
||||
return __to_chars_integral(__first, __last, __value, __base,
|
||||
is_signed<_Tp>());
|
||||
}
|
||||
|
||||
template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
|
||||
inline _LIBCPP_INLINE_VISIBILITY from_chars_result
|
||||
__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args)
|
||||
{
|
||||
using __tl = numeric_limits<_Tp>;
|
||||
decltype(__to_unsigned(__value)) __x;
|
||||
|
||||
bool __neg = (__first != __last && *__first == '-');
|
||||
auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...);
|
||||
switch (__r.ec)
|
||||
{
|
||||
case errc::invalid_argument:
|
||||
return {__first, __r.ec};
|
||||
case errc::result_out_of_range:
|
||||
return __r;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (__neg)
|
||||
{
|
||||
if (__x <= __complement(__to_unsigned(__tl::min())))
|
||||
{
|
||||
__x = __complement(__x);
|
||||
memcpy(&__value, &__x, sizeof(__x));
|
||||
return __r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (__x <= (__tl::max)())
|
||||
{
|
||||
__value = __x;
|
||||
return __r;
|
||||
}
|
||||
}
|
||||
|
||||
return {__r.ptr, errc::result_out_of_range};
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool
|
||||
__in_pattern(_Tp __c)
|
||||
{
|
||||
return '0' <= __c && __c <= '9';
|
||||
}
|
||||
|
||||
struct _LIBCPP_HIDDEN __in_pattern_result
|
||||
{
|
||||
bool __ok;
|
||||
int __val;
|
||||
|
||||
explicit _LIBCPP_INLINE_VISIBILITY operator bool() const { return __ok; }
|
||||
};
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY __in_pattern_result
|
||||
__in_pattern(_Tp __c, int __base)
|
||||
{
|
||||
if (__base <= 10)
|
||||
return {'0' <= __c && __c < '0' + __base, __c - '0'};
|
||||
else if (__in_pattern(__c))
|
||||
return {true, __c - '0'};
|
||||
else if ('a' <= __c && __c < 'a' + __base - 10)
|
||||
return {true, __c - 'a' + 10};
|
||||
else
|
||||
return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10};
|
||||
}
|
||||
|
||||
template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
|
||||
inline _LIBCPP_INLINE_VISIBILITY from_chars_result
|
||||
__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f,
|
||||
_Ts... __args)
|
||||
{
|
||||
auto __find_non_zero = [](_It __first, _It __last) {
|
||||
for (; __first != __last; ++__first)
|
||||
if (*__first != '0')
|
||||
break;
|
||||
return __first;
|
||||
};
|
||||
|
||||
auto __p = __find_non_zero(__first, __last);
|
||||
if (__p == __last || !__in_pattern(*__p, __args...))
|
||||
{
|
||||
if (__p == __first)
|
||||
return {__first, errc::invalid_argument};
|
||||
else
|
||||
{
|
||||
__value = 0;
|
||||
return {__p, {}};
|
||||
}
|
||||
}
|
||||
|
||||
auto __r = __f(__p, __last, __value, __args...);
|
||||
if (__r.ec == errc::result_out_of_range)
|
||||
{
|
||||
for (; __r.ptr != __last; ++__r.ptr)
|
||||
{
|
||||
if (!__in_pattern(*__r.ptr, __args...))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return __r;
|
||||
}
|
||||
|
||||
template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0>
|
||||
inline _LIBCPP_INLINE_VISIBILITY from_chars_result
|
||||
__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(
|
||||
__first, __last, __value,
|
||||
[](const char* __first, const char* __last,
|
||||
_Tp& __value) -> from_chars_result {
|
||||
__output_type __a, __b;
|
||||
auto __p = __tx::__read(__first, __last, __a, __b);
|
||||
if (__p == __last || !__in_pattern(*__p))
|
||||
{
|
||||
__output_type __m = (numeric_limits<_Tp>::max)();
|
||||
if (__m >= __a && __m - __a >= __b)
|
||||
{
|
||||
__value = __a + __b;
|
||||
return {__p, {}};
|
||||
}
|
||||
}
|
||||
return {__p, errc::result_out_of_range};
|
||||
});
|
||||
}
|
||||
|
||||
template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0>
|
||||
inline _LIBCPP_INLINE_VISIBILITY from_chars_result
|
||||
__from_chars_atoi(const char* __first, const char* __last, _Tp& __value)
|
||||
{
|
||||
using __t = decltype(__to_unsigned(__value));
|
||||
return __sign_combinator(__first, __last, __value, __from_chars_atoi<__t>);
|
||||
}
|
||||
|
||||
template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0>
|
||||
inline _LIBCPP_INLINE_VISIBILITY from_chars_result
|
||||
__from_chars_integral(const char* __first, const char* __last, _Tp& __value,
|
||||
int __base)
|
||||
{
|
||||
if (__base == 10)
|
||||
return __from_chars_atoi(__first, __last, __value);
|
||||
|
||||
return __subject_seq_combinator(
|
||||
__first, __last, __value,
|
||||
[](const char* __p, const char* __last, _Tp& __value,
|
||||
int __base) -> from_chars_result {
|
||||
using __tl = numeric_limits<_Tp>;
|
||||
auto __digits = __tl::digits / log2f(float(__base));
|
||||
_Tp __a = __in_pattern(*__p++, __base).__val, __b = 0;
|
||||
|
||||
for (int __i = 1; __p != __last; ++__i, ++__p)
|
||||
{
|
||||
if (auto __c = __in_pattern(*__p, __base))
|
||||
{
|
||||
if (__i < __digits - 1)
|
||||
__a = __a * __base + __c.__val;
|
||||
else
|
||||
{
|
||||
if (!__itoa::__mul_overflowed(__a, __base, __a))
|
||||
++__p;
|
||||
__b = __c.__val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (__p == __last || !__in_pattern(*__p, __base))
|
||||
{
|
||||
if ((__tl::max)() - __a >= __b)
|
||||
{
|
||||
__value = __a + __b;
|
||||
return {__p, {}};
|
||||
}
|
||||
}
|
||||
return {__p, errc::result_out_of_range};
|
||||
},
|
||||
__base);
|
||||
}
|
||||
|
||||
template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0>
|
||||
inline _LIBCPP_INLINE_VISIBILITY from_chars_result
|
||||
__from_chars_integral(const char* __first, const char* __last, _Tp& __value,
|
||||
int __base)
|
||||
{
|
||||
using __t = decltype(__to_unsigned(__value));
|
||||
return __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_INLINE_VISIBILITY from_chars_result
|
||||
from_chars(const char* __first, const char* __last, _Tp& __value)
|
||||
{
|
||||
return __from_chars_atoi(__first, __last, __value);
|
||||
}
|
||||
|
||||
template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
|
||||
inline _LIBCPP_INLINE_VISIBILITY 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);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_CHARCONV
|
1979
include/chrono
1979
include/chrono
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- cinttypes --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- ciso646 ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- climits ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===--------------------------- clocale ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
102
include/cmath
102
include/cmath
@ -1,10 +1,9 @@
|
||||
// -*- C++ -*-
|
||||
//===---------------------------- cmath -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -303,11 +302,16 @@ long double truncl(long double x);
|
||||
|
||||
#include <__config>
|
||||
#include <math.h>
|
||||
#include <version>
|
||||
#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
|
||||
|
||||
using ::signbit;
|
||||
@ -398,7 +402,6 @@ using ::cbrtf;
|
||||
using ::copysign;
|
||||
using ::copysignf;
|
||||
|
||||
#if !(defined(_LIBCPP_MSVCRT) && ((_VC_CRT_MAJOR_VERSION-0) < 14))
|
||||
using ::erf;
|
||||
using ::erff;
|
||||
using ::erfc;
|
||||
@ -435,12 +438,10 @@ using ::lrint;
|
||||
using ::lrintf;
|
||||
using ::lround;
|
||||
using ::lroundf;
|
||||
#endif // !(defined(_LIBCPP_MSVCRT) && ((_VC_CRT_MAJOR_VERSION-0) < 14))
|
||||
|
||||
using ::nan;
|
||||
using ::nanf;
|
||||
|
||||
#if !(defined(_LIBCPP_MSVCRT) && ((_VC_CRT_MAJOR_VERSION-0) < 14))
|
||||
using ::nearbyint;
|
||||
using ::nearbyintf;
|
||||
using ::nextafter;
|
||||
@ -463,7 +464,6 @@ using ::tgamma;
|
||||
using ::tgammaf;
|
||||
using ::trunc;
|
||||
using ::truncf;
|
||||
#endif // !(defined(_LIBCPP_MSVCRT) && ((_VC_CRT_MAJOR_VERSION-0) < 14))
|
||||
|
||||
using ::acosl;
|
||||
using ::asinl;
|
||||
@ -495,7 +495,6 @@ using ::cbrtl;
|
||||
|
||||
using ::copysignl;
|
||||
|
||||
#if !(defined(_LIBCPP_MSVCRT) && ((_VC_CRT_MAJOR_VERSION-0) < 14))
|
||||
using ::erfl;
|
||||
using ::erfcl;
|
||||
using ::exp2l;
|
||||
@ -526,7 +525,6 @@ using ::scalblnl;
|
||||
using ::scalbnl;
|
||||
using ::tgammal;
|
||||
using ::truncl;
|
||||
#endif // !(defined(_LIBCPP_MSVCRT) && ((_VC_CRT_MAJOR_VERSION-0) < 14))
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
inline _LIBCPP_INLINE_VISIBILITY float hypot( float x, float y, float z ) { return sqrt(x*x + y*y + z*z); }
|
||||
@ -535,7 +533,7 @@ inline _LIBCPP_INLINE_VISIBILITY long double hypot( long double x, long double y
|
||||
|
||||
template <class _A1, class _A2, class _A3>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename __lazy_enable_if
|
||||
typename _EnableIf
|
||||
<
|
||||
is_arithmetic<_A1>::value &&
|
||||
is_arithmetic<_A2>::value &&
|
||||
@ -553,9 +551,9 @@ hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT
|
||||
#endif
|
||||
|
||||
template <class _A1>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type
|
||||
__libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT
|
||||
__libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
#if __has_builtin(__builtin_isnan)
|
||||
return __builtin_isnan(__lcpp_x);
|
||||
@ -565,17 +563,17 @@ __libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type
|
||||
__libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT
|
||||
__libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return isnan(__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type
|
||||
__libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT
|
||||
__libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
#if __has_builtin(__builtin_isinf)
|
||||
return __builtin_isinf(__lcpp_x);
|
||||
@ -585,17 +583,17 @@ __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type
|
||||
__libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT
|
||||
__libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return isinf(__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR typename enable_if<is_floating_point<_A1>::value, bool>::type
|
||||
__libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT
|
||||
__libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
#if __has_builtin(__builtin_isfinite)
|
||||
return __builtin_isfinite(__lcpp_x);
|
||||
@ -605,13 +603,71 @@ __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR typename enable_if<!is_floating_point<_A1>::value, bool>::type
|
||||
__libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT
|
||||
__libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return isfinite(__lcpp_x);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <typename _Fp>
|
||||
constexpr
|
||||
_Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept {
|
||||
if ((__a <= 0 && __b >= 0) || (__a >= 0 && __b <= 0))
|
||||
return __t * __b + (1 - __t) * __a;
|
||||
|
||||
if (__t == 1) return __b;
|
||||
const _Fp __x = __a + __t * (__b - __a);
|
||||
if (__t > 1 == __b > __a)
|
||||
return __b < __x ? __x : __b;
|
||||
else
|
||||
return __x < __b ? __x : __b;
|
||||
}
|
||||
|
||||
constexpr float
|
||||
lerp(float __a, float __b, float __t) _NOEXCEPT { return __lerp(__a, __b, __t); }
|
||||
|
||||
constexpr double
|
||||
lerp(double __a, double __b, double __t) _NOEXCEPT { return __lerp(__a, __b, __t); }
|
||||
|
||||
constexpr long double
|
||||
lerp(long double __a, long double __b, long double __t) _NOEXCEPT { return __lerp(__a, __b, __t); }
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 17
|
||||
|
||||
template <class _IntT, class _FloatT,
|
||||
bool _FloatBigger = (numeric_limits<_FloatT>::digits > numeric_limits<_IntT>::digits),
|
||||
int _Bits = (numeric_limits<_IntT>::digits - numeric_limits<_FloatT>::digits)>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR _IntT __max_representable_int_for_float() _NOEXCEPT {
|
||||
static_assert(is_floating_point<_FloatT>::value, "must be a floating point type");
|
||||
static_assert(is_integral<_IntT>::value, "must be an integral type");
|
||||
static_assert(numeric_limits<_FloatT>::radix == 2, "FloatT has incorrect radix");
|
||||
static_assert((_IsSame<_FloatT, float>::value || _IsSame<_FloatT, double>::value
|
||||
|| _IsSame<_FloatT,long double>::value), "unsupported floating point type");
|
||||
return _FloatBigger ? numeric_limits<_IntT>::max() : (numeric_limits<_IntT>::max() >> _Bits << _Bits);
|
||||
}
|
||||
|
||||
// Convert a floating point number to the specified integral type after
|
||||
// clamping to the integral types representable range.
|
||||
//
|
||||
// The behavior is undefined if `__r` is NaN.
|
||||
template <class _IntT, class _RealT>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_IntT __clamp_to_integral(_RealT __r) _NOEXCEPT {
|
||||
using _Lim = std::numeric_limits<_IntT>;
|
||||
const _IntT _MaxVal = std::__max_representable_int_for_float<_IntT, _RealT>();
|
||||
if (__r >= ::nextafter(static_cast<_RealT>(_MaxVal), INFINITY)) {
|
||||
return _Lim::max();
|
||||
} else if (__r <= _Lim::lowest()) {
|
||||
return _Lim::min();
|
||||
}
|
||||
return static_cast<_IntT>(__r);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_CMATH
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user