Merge remote-tracking branch 'upstream/master' into HEAD

This commit is contained in:
Lubos Dolezel 2020-04-17 14:51:11 +02:00
commit f1d9f7bb21
7334 changed files with 205138 additions and 100414 deletions

View File

@ -1,4 +1,4 @@
{
"project_id" : "libcxx",
"repository.callsign" : "CXX",
"conduit_uri" : "https://reviews.llvm.org/"
}

View File

@ -2,6 +2,7 @@ BasedOnStyle: LLVM
---
Language: Cpp
Standard: Cpp03
AlwaysBreakTemplateDeclarations: true
PointerAlignment: Left

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View 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();
}

View 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();

View 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();

View File

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

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

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

View 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();
}

View File

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

View 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();

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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).

View File

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

View File

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

View 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 |
.. +---------+-------------------------------------------------------+--------------------+------------------------------------------+-------------------------+

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

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

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

View File

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

View File

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

View 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*
================================================= =================

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +1 @@
5000
10000

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

486
include/bit Normal file
View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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