Vendor import of libc++ trunk r351319 (just before the release_80
branch point): https://llvm.org/svn/llvm-project/libcxx/trunk@351319
This commit is contained in:
parent
315d10f09e
commit
6012fe9abb
142
CMakeLists.txt
142
CMakeLists.txt
@ -27,7 +27,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
project(libcxx CXX C)
|
||||
|
||||
set(PACKAGE_NAME libcxx)
|
||||
set(PACKAGE_VERSION 7.0.0svn)
|
||||
set(PACKAGE_VERSION 8.0.0svn)
|
||||
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||
set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
|
||||
|
||||
@ -50,9 +50,14 @@ MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
|
||||
"${PROJECT_NAME} requires an out of source build. Please create a separate
|
||||
build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there."
|
||||
)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
|
||||
message(STATUS "Configuring for clang-cl")
|
||||
set(LIBCXX_TARGETING_CLANG_CL ON)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
set(LIBCXX_TARGETING_MSVC ON)
|
||||
message(STATUS "Configuring for MSVC")
|
||||
else()
|
||||
set(LIBCXX_TARGETING_MSVC OFF)
|
||||
endif()
|
||||
@ -77,7 +82,12 @@ option(LIBCXX_ENABLE_FILESYSTEM "Build filesystem as part of libc++fs.a"
|
||||
option(LIBCXX_INCLUDE_TESTS "Build the libc++ tests." ${LLVM_INCLUDE_TESTS})
|
||||
|
||||
# Benchmark options -----------------------------------------------------------
|
||||
option(LIBCXX_INCLUDE_BENCHMARKS "Build the libc++ benchmarks and their dependancies" ON)
|
||||
option(LIBCXX_INCLUDE_BENCHMARKS "Build the libc++ benchmarks and their dependencies" ON)
|
||||
|
||||
set(LIBCXX_BENCHMARK_TEST_ARGS_DEFAULT --benchmark_min_time=0.01)
|
||||
set(LIBCXX_BENCHMARK_TEST_ARGS "${LIBCXX_BENCHMARK_TEST_ARGS_DEFAULT}" CACHE STRING
|
||||
"Arguments to pass when running the benchmarks using check-cxx-benchmarks")
|
||||
|
||||
set(LIBCXX_BENCHMARK_NATIVE_STDLIB "" CACHE STRING
|
||||
"Build the benchmarks against the specified native STL.
|
||||
The value must be one of libc++/libstdc++")
|
||||
@ -111,15 +121,12 @@ cmake_dependent_option(LIBCXX_INSTALL_FILESYSTEM_LIBRARY
|
||||
"Install libc++fs.a" ON
|
||||
"LIBCXX_ENABLE_FILESYSTEM;LIBCXX_INSTALL_LIBRARY" OFF)
|
||||
|
||||
if (FUCHSIA)
|
||||
set(DEFAULT_ABI_VERSION 2)
|
||||
else()
|
||||
set(DEFAULT_ABI_VERSION 1)
|
||||
endif()
|
||||
set(LIBCXX_ABI_VERSION ${DEFAULT_ABI_VERSION} CACHE STRING "ABI version of libc++.")
|
||||
set(LIBCXX_ABI_VERSION "1" CACHE STRING "ABI version of libc++. Can be either 1 or 2, where 2 is currently not stable. Defaults to 1.")
|
||||
set(LIBCXX_ABI_NAMESPACE "" CACHE STRING "The inline ABI namespace used by libc++. It defaults to __n where `n` is the current ABI version.")
|
||||
option(LIBCXX_ABI_UNSTABLE "Unstable ABI of libc++." OFF)
|
||||
option(LIBCXX_ABI_FORCE_ITANIUM "Ignore auto-detection and force use of the Itanium ABI.")
|
||||
option(LIBCXX_ABI_FORCE_MICROSOFT "Ignore auto-detection and force use of the Microsoft ABI.")
|
||||
option(LIBCXX_HIDE_FROM_ABI_PER_TU_BY_DEFAULT "Enable per TU ABI insulation by default. To be used by vendors." OFF)
|
||||
set(LIBCXX_ABI_DEFINES "" CACHE STRING "A semicolon separated list of ABI macros to define in the site config header.")
|
||||
option(LIBCXX_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF)
|
||||
|
||||
@ -175,7 +182,7 @@ cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY
|
||||
|
||||
cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY
|
||||
"Statically link the ABI library to shared library" ON
|
||||
"LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_STATIC" OFF)
|
||||
"LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_SHARED" OFF)
|
||||
|
||||
# Generate and install a linker script inplace of libc++.so. The linker script
|
||||
# will link libc++ to the correct ABI library. This option is on by default
|
||||
@ -276,6 +283,9 @@ endif()
|
||||
option(LIBCXX_CONFIGURE_IDE "Configure libcxx for use within an IDE"
|
||||
${LIBCXX_CONFIGURE_IDE_DEFAULT})
|
||||
|
||||
option(LIBCXX_HERMETIC_STATIC_LIBRARY
|
||||
"Do not export any symbols from the static library." OFF)
|
||||
|
||||
#===============================================================================
|
||||
# Check option configurations
|
||||
#===============================================================================
|
||||
@ -502,14 +512,16 @@ remove_flags(-Wno-pedantic -pedantic-errors -pedantic)
|
||||
|
||||
# Required flags ==============================================================
|
||||
set(LIBCXX_STANDARD_VER c++11 CACHE INTERNAL "internal option to change build dialect")
|
||||
if (LIBCXX_HAS_MUSL_LIBC)
|
||||
if (LIBCXX_HAS_MUSL_LIBC OR LIBCXX_TARGETING_CLANG_CL)
|
||||
# musl's pthread implementations uses volatile types in their structs which is
|
||||
# not a constexpr in C++11 but is in C++14, so we use C++14 with musl.
|
||||
set(LIBCXX_STANDARD_VER c++14 CACHE INTERNAL "internal option to change build dialect")
|
||||
endif()
|
||||
add_compile_flags_if_supported(-std=${LIBCXX_STANDARD_VER})
|
||||
add_compile_flags_if_supported("/std:${LIBCXX_STANDARD_VER}")
|
||||
mangle_name("LIBCXX_SUPPORTS_STD_EQ_${LIBCXX_STANDARD_VER}_FLAG" SUPPORTS_DIALECT_NAME)
|
||||
if(NOT ${SUPPORTS_DIALECT_NAME})
|
||||
mangle_name("LIBCXX_SUPPORTS_STD_COLON_${LIBCXX_STANDARD_VER}_FLAG" SUPPORTS_DIALECT_NAME_MSVC)
|
||||
if(NOT ${SUPPORTS_DIALECT_NAME} AND NOT ${SUPPORTS_DIALECT_NAME_MSVC})
|
||||
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" AND NOT "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
|
||||
message(FATAL_ERROR "C++11 or greater is required but the compiler does not support ${LIBCXX_STANDARD_VER}")
|
||||
endif()
|
||||
@ -544,11 +556,29 @@ add_definitions(-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
add_compile_flags_if_supported(
|
||||
-Wall -Wextra -W -Wwrite-strings
|
||||
-Wno-unused-parameter -Wno-long-long
|
||||
-Werror=return-type)
|
||||
-Werror=return-type -Wextra-semi)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
add_compile_flags_if_supported(
|
||||
-Wno-user-defined-literals
|
||||
-Wno-covered-switch-default)
|
||||
if (LIBCXX_TARGETING_CLANG_CL)
|
||||
add_compile_flags_if_supported(
|
||||
-Wno-c++98-compat
|
||||
-Wno-c++98-compat-pedantic
|
||||
-Wno-c++11-compat
|
||||
-Wno-undef
|
||||
-Wno-reserved-id-macro
|
||||
-Wno-gnu-include-next
|
||||
-Wno-gcc-compat # For ignoring "'diagnose_if' is a clang extension" warnings
|
||||
-Wno-zero-as-null-pointer-constant # FIXME: Remove this and fix all occurrences.
|
||||
-Wno-deprecated-dynamic-exception-spec # For auto_ptr
|
||||
-Wno-sign-conversion
|
||||
-Wno-old-style-cast
|
||||
-Wno-deprecated # FIXME: Remove this and fix all occurrences.
|
||||
-Wno-shift-sign-overflow # FIXME: Why do we need this with clang-cl but not clang?
|
||||
-Wno-double-promotion # FIXME: remove me
|
||||
)
|
||||
endif()
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
add_compile_flags_if_supported(
|
||||
-Wno-literal-suffix
|
||||
@ -621,47 +651,67 @@ endif()
|
||||
|
||||
# Sanitizer flags =============================================================
|
||||
|
||||
function(get_sanitizer_flags OUT_VAR USE_SANITIZER)
|
||||
set(SANITIZER_FLAGS)
|
||||
set(USE_SANITIZER "${USE_SANITIZER}")
|
||||
# NOTE: LLVM_USE_SANITIZER checks for a UNIX like system instead of MSVC.
|
||||
# But we don't have LLVM_ON_UNIX so checking for MSVC is the best we can do.
|
||||
if (USE_SANITIZER AND NOT MSVC)
|
||||
append_flags_if_supported(SANITIZER_FLAGS "-fno-omit-frame-pointer")
|
||||
append_flags_if_supported(SANITIZER_FLAGS "-gline-tables-only")
|
||||
|
||||
if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" AND
|
||||
NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
|
||||
append_flags_if_supported(SANITIZER_FLAGS "-gline-tables-only")
|
||||
endif()
|
||||
if (USE_SANITIZER STREQUAL "Address")
|
||||
append_flags(SANITIZER_FLAGS "-fsanitize=address")
|
||||
elseif (USE_SANITIZER MATCHES "Memory(WithOrigins)?")
|
||||
append_flags(SANITIZER_FLAGS -fsanitize=memory)
|
||||
if (USE_SANITIZER STREQUAL "MemoryWithOrigins")
|
||||
append_flags(SANITIZER_FLAGS "-fsanitize-memory-track-origins")
|
||||
endif()
|
||||
elseif (USE_SANITIZER STREQUAL "Undefined")
|
||||
append_flags(SANITIZER_FLAGS "-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all")
|
||||
elseif (USE_SANITIZER STREQUAL "Thread")
|
||||
append_flags(SANITIZER_FLAGS -fsanitize=thread)
|
||||
else()
|
||||
message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${USE_SANITIZER}")
|
||||
endif()
|
||||
elseif(USE_SANITIZER AND MSVC)
|
||||
message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.")
|
||||
endif()
|
||||
set(${OUT_VAR} "${SANITIZER_FLAGS}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Configure for sanitizers. If LIBCXX_STANDALONE_BUILD then we have to do
|
||||
# the flag translation ourselves. Othewise LLVM's CMakeList.txt will handle it.
|
||||
if (LIBCXX_STANDALONE_BUILD)
|
||||
set(LLVM_USE_SANITIZER "" CACHE STRING
|
||||
"Define the sanitizer used to build the library and tests")
|
||||
# NOTE: LLVM_USE_SANITIZER checks for a UNIX like system instead of MSVC.
|
||||
# But we don't have LLVM_ON_UNIX so checking for MSVC is the best we can do.
|
||||
if (LLVM_USE_SANITIZER AND NOT MSVC)
|
||||
add_flags_if_supported("-fno-omit-frame-pointer")
|
||||
add_flags_if_supported("-gline-tables-only")
|
||||
|
||||
if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" AND
|
||||
NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
|
||||
add_flags_if_supported("-gline-tables-only")
|
||||
endif()
|
||||
if (LLVM_USE_SANITIZER STREQUAL "Address")
|
||||
add_flags("-fsanitize=address")
|
||||
elseif (LLVM_USE_SANITIZER MATCHES "Memory(WithOrigins)?")
|
||||
add_flags(-fsanitize=memory)
|
||||
if (LLVM_USE_SANITIZER STREQUAL "MemoryWithOrigins")
|
||||
add_flags("-fsanitize-memory-track-origins")
|
||||
endif()
|
||||
elseif (LLVM_USE_SANITIZER STREQUAL "Undefined")
|
||||
add_flags("-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all")
|
||||
elseif (LLVM_USE_SANITIZER STREQUAL "Thread")
|
||||
add_flags(-fsanitize=thread)
|
||||
else()
|
||||
message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}")
|
||||
endif()
|
||||
elseif(LLVM_USE_SANITIZER AND MSVC)
|
||||
message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.")
|
||||
endif()
|
||||
endif()
|
||||
get_sanitizer_flags(SANITIZER_FLAGS "${LLVM_USE_SANITIZER}")
|
||||
if (LIBCXX_STANDALONE_BUILD AND SANITIZER_FLAGS)
|
||||
add_flags(${SANITIZER_FLAGS})
|
||||
endif()
|
||||
|
||||
# Configuration file flags =====================================================
|
||||
if (NOT LIBCXX_ABI_VERSION EQUAL DEFAULT_ABI_VERSION)
|
||||
if (NOT LIBCXX_ABI_VERSION EQUAL 1)
|
||||
config_define(${LIBCXX_ABI_VERSION} _LIBCPP_ABI_VERSION)
|
||||
endif()
|
||||
if (NOT LIBCXX_ABI_NAMESPACE STREQUAL "")
|
||||
if (NOT LIBCXX_ABI_NAMESPACE MATCHES "__.*")
|
||||
message(WARNING "LIBCXX_ABI_NAMESPACE must be a reserved identifier.")
|
||||
endif()
|
||||
if (LIBCXX_ABI_NAMESPACE MATCHES "__[0-9]+$")
|
||||
message(FATAL_ERROR "LIBCXX_ABI_NAMESPACE '${LIBCXX_ABI_NAMESPACE}' is reserved for use by libc++.")
|
||||
endif()
|
||||
config_define(${LIBCXX_ABI_NAMESPACE} _LIBCPP_ABI_NAMESPACE)
|
||||
endif()
|
||||
config_define_if(LIBCXX_ABI_UNSTABLE _LIBCPP_ABI_UNSTABLE)
|
||||
config_define_if(LIBCXX_ABI_FORCE_ITANIUM _LIBCPP_ABI_FORCE_ITANIUM)
|
||||
config_define_if(LIBCXX_ABI_FORCE_MICROSOFT _LIBCPP_ABI_FORCE_MICROSOFT)
|
||||
config_define_if(LIBCXX_HIDE_FROM_ABI_PER_TU_BY_DEFAULT _LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT)
|
||||
|
||||
config_define_if_not(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE)
|
||||
config_define_if_not(LIBCXX_ENABLE_STDIN _LIBCPP_HAS_NO_STDIN)
|
||||
@ -724,6 +774,18 @@ include_directories(include)
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(lib)
|
||||
|
||||
set(LIBCXX_TEST_DEPS "")
|
||||
|
||||
if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY)
|
||||
list(APPEND LIBCXX_TEST_DEPS cxx_experimental)
|
||||
endif()
|
||||
if (LIBCXX_ENABLE_FILESYSTEM)
|
||||
list(APPEND LIBCXX_TEST_DEPS cxx_filesystem)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
list(APPEND LIBCXX_TEST_DEPS cxx_external_threads)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_INCLUDE_BENCHMARKS)
|
||||
add_subdirectory(benchmarks)
|
||||
|
@ -14,7 +14,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.
|
||||
|
||||
|
@ -9,7 +9,7 @@ cd C:\projects\deps
|
||||
:: Setup Compiler
|
||||
::###########################################################################
|
||||
if NOT EXIST llvm-installer.exe (
|
||||
appveyor DownloadFile http://prereleases.llvm.org/win-snapshots/LLVM-7.0.0-r325576-win32.exe -FileName llvm-installer.exe
|
||||
appveyor DownloadFile https://prereleases.llvm.org/win-snapshots/LLVM-8.0.0-r345380-win32.exe -FileName llvm-installer.exe
|
||||
)
|
||||
if "%CLANG_VERSION%"=="ToT" (
|
||||
START /WAIT llvm-installer.exe /S /D=C:\"Program Files\LLVM"
|
||||
|
@ -18,14 +18,6 @@ environment:
|
||||
GENERATOR: Ninja
|
||||
MAKE_PROGRAM: ninja
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_OPTIONS: -DCMAKE_C_COMPILER=clang-cl.exe -DCMAKE_CXX_COMPILER=clang-cl.exe
|
||||
CLANG_VERSION: 4
|
||||
MSVC_SETUP_PATH: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
|
||||
MSVC_SETUP_ARG: x86_amd64
|
||||
GENERATOR: Ninja
|
||||
MAKE_PROGRAM: ninja
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
- 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
|
||||
|
@ -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
|
||||
@ -67,8 +71,19 @@ 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++17 -O2
|
||||
${BENCHMARK_DIALECT_FLAG} -O2
|
||||
-I${BENCHMARK_LIBCXX_INSTALL}/include
|
||||
-I${LIBCXX_SOURCE_DIR}/test/support
|
||||
)
|
||||
@ -76,11 +91,18 @@ set(BENCHMARK_TEST_LIBCXX_COMPILE_FLAGS
|
||||
-nostdinc++
|
||||
-isystem ${LIBCXX_SOURCE_DIR}/include
|
||||
${BENCHMARK_TEST_COMPILE_FLAGS}
|
||||
${SANITIZER_FLAGS}
|
||||
-Wno-user-defined-literals
|
||||
)
|
||||
if (LIBCXX_NEEDS_SITE_CONFIG)
|
||||
list(APPEND BENCHMARK_TEST_LIBCXX_COMPILE_FLAGS
|
||||
-include "${LIBCXX_BINARY_DIR}/__config_site")
|
||||
endif()
|
||||
|
||||
set(BENCHMARK_TEST_LIBCXX_LINK_FLAGS
|
||||
-nodefaultlibs
|
||||
-L${BENCHMARK_LIBCXX_INSTALL}/lib/
|
||||
${SANITIZER_FLAGS}
|
||||
)
|
||||
set(BENCHMARK_TEST_NATIVE_COMPILE_FLAGS
|
||||
${BENCHMARK_NATIVE_TARGET_FLAGS}
|
||||
@ -95,10 +117,25 @@ 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)
|
||||
@ -108,7 +145,13 @@ macro(add_benchmark_test name source_file)
|
||||
if (TARGET cxx_experimental)
|
||||
target_link_libraries(${libcxx_target} cxx_experimental)
|
||||
endif()
|
||||
if (TARGET cxx_filesystem)
|
||||
target_link_libraries(${libcxx_target} cxx_filesystem)
|
||||
endif()
|
||||
target_link_libraries(${libcxx_target} -lbenchmark)
|
||||
if (LLVM_USE_SANITIZER)
|
||||
target_link_libraries(${libcxx_target} -ldl)
|
||||
endif()
|
||||
set_target_properties(${libcxx_target}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "${name}.libcxx.out"
|
||||
@ -116,15 +159,19 @@ macro(add_benchmark_test name source_file)
|
||||
COMPILE_FLAGS "${BENCHMARK_TEST_LIBCXX_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${BENCHMARK_TEST_LIBCXX_LINK_FLAGS}")
|
||||
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)
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libstdc++")
|
||||
target_link_libraries(${native_target} -lstdc++fs)
|
||||
target_link_libraries(${native_target} ${LIBSTDCXX_FILESYSTEM_LIB})
|
||||
elseif (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libc++")
|
||||
target_link_libraries(${native_target} -lc++experimental)
|
||||
target_link_libraries(${native_target} -lc++fs -lc++experimental)
|
||||
endif()
|
||||
if (LIBCXX_HAS_PTHREAD_LIB)
|
||||
target_link_libraries(${native_target} -pthread)
|
||||
@ -138,7 +185,7 @@ macro(add_benchmark_test name source_file)
|
||||
COMPILE_FLAGS "${BENCHMARK_TEST_NATIVE_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${BENCHMARK_TEST_NATIVE_LINK_FLAGS}")
|
||||
endif()
|
||||
endmacro()
|
||||
endfunction()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
@ -155,3 +202,23 @@ 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()
|
||||
|
135
benchmarks/CartesianBenchmarks.hpp
Normal file
135
benchmarks/CartesianBenchmarks.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class D, class E, size_t I>
|
||||
struct EnumValue : std::integral_constant<E, static_cast<E>(I)> {
|
||||
static std::string name() { return std::string("_") + D::Names[I]; }
|
||||
};
|
||||
|
||||
template <class D, class E, size_t ...Idxs>
|
||||
constexpr auto makeEnumValueTuple(std::index_sequence<Idxs...>) {
|
||||
return std::make_tuple(EnumValue<D, E, Idxs>{}...);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
static auto skip(const B& Bench, int) -> decltype(Bench.skip()) {
|
||||
return Bench.skip();
|
||||
}
|
||||
template <class B>
|
||||
static auto skip(const B& Bench, char) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class B, class Args, size_t... Is>
|
||||
void makeBenchmarkFromValuesImpl(const Args& A, std::index_sequence<Is...>) {
|
||||
for (auto& V : A) {
|
||||
B Bench{std::get<Is>(V)...};
|
||||
if (!internal::skip(Bench, 0)) {
|
||||
benchmark::RegisterBenchmark(Bench.name().c_str(),
|
||||
[=](benchmark::State& S) { Bench.run(S); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class B, class... Args>
|
||||
void makeBenchmarkFromValues(const std::vector<std::tuple<Args...> >& A) {
|
||||
makeBenchmarkFromValuesImpl<B>(A, std::index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
template <template <class...> class B, class Args, class... U>
|
||||
void makeBenchmarkImpl(const Args& A, std::tuple<U...> t) {
|
||||
makeBenchmarkFromValues<B<U...> >(A);
|
||||
}
|
||||
|
||||
template <template <class...> class B, class Args, class... U,
|
||||
class... T, class... Tuples>
|
||||
void makeBenchmarkImpl(const Args& A, std::tuple<U...>, std::tuple<T...>,
|
||||
Tuples... rest) {
|
||||
(internal::makeBenchmarkImpl<B>(A, std::tuple<U..., T>(), rest...), ...);
|
||||
}
|
||||
|
||||
template <class R, class T>
|
||||
void allValueCombinations(R& Result, const T& Final) {
|
||||
return Result.push_back(Final);
|
||||
}
|
||||
|
||||
template <class R, class T, class V, class... Vs>
|
||||
void allValueCombinations(R& Result, const T& Prev, const V& Value,
|
||||
const Vs&... Values) {
|
||||
for (const auto& E : Value) {
|
||||
allValueCombinations(Result, std::tuple_cat(Prev, std::make_tuple(E)),
|
||||
Values...);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// CRTP class that enables using enum types as a dimension for
|
||||
// makeCartesianProductBenchmark below.
|
||||
// The type passed to `B` will be a std::integral_constant<E, e>, with the
|
||||
// additional static function `name()` that returns the stringified name of the
|
||||
// label.
|
||||
//
|
||||
// Eg:
|
||||
// enum class MyEnum { A, B };
|
||||
// struct AllMyEnum : EnumValuesAsTuple<AllMyEnum, MyEnum, 2> {
|
||||
// static constexpr absl::string_view Names[] = {"A", "B"};
|
||||
// };
|
||||
template <class Derived, class EnumType, size_t NumLabels>
|
||||
using EnumValuesAsTuple =
|
||||
decltype(internal::makeEnumValueTuple<Derived, EnumType>(
|
||||
std::make_index_sequence<NumLabels>{}));
|
||||
|
||||
// Instantiates B<T0, T1, ..., TN> where <Ti...> are the combinations in the
|
||||
// cartesian product of `Tuples...`, and pass (arg0, ..., argN) as constructor
|
||||
// arguments where `(argi...)` are the combination in the cartesian product of
|
||||
// the runtime values of `A...`.
|
||||
// B<T...> requires:
|
||||
// - std::string name(args...): The name of the benchmark.
|
||||
// - void run(benchmark::State&, args...): The body of the benchmark.
|
||||
// It can also optionally provide:
|
||||
// - bool skip(args...): When `true`, skips the combination. Default is false.
|
||||
//
|
||||
// Returns int to facilitate registration. The return value is unspecified.
|
||||
template <template <class...> class B, class... Tuples, class... Args>
|
||||
int makeCartesianProductBenchmark(const Args&... A) {
|
||||
std::vector<std::tuple<typename Args::value_type...> > V;
|
||||
internal::allValueCombinations(V, std::tuple<>(), A...);
|
||||
internal::makeBenchmarkImpl<B>(V, std::tuple<>(), Tuples()...);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class B, class... Args>
|
||||
int makeCartesianProductBenchmark(const Args&... A) {
|
||||
std::vector<std::tuple<typename Args::value_type...> > V;
|
||||
internal::allValueCombinations(V, std::tuple<>(), A...);
|
||||
internal::makeBenchmarkFromValues<B>(V);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// When `opaque` is true, this function hides the runtime state of `value` from
|
||||
// the optimizer.
|
||||
// It returns `value`.
|
||||
template <class T>
|
||||
TEST_ALWAYS_INLINE inline T maybeOpaque(T value, bool opaque) {
|
||||
if (opaque) benchmark::DoNotOptimize(value);
|
||||
return value;
|
||||
}
|
||||
|
@ -1,62 +1,270 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "CartesianBenchmarks.hpp"
|
||||
#include "GenerateInput.hpp"
|
||||
#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, 1 << 18};
|
||||
makeCartesianProductBenchmark<Sort, AllValueTypes, AllOrders>(Quantities);
|
||||
makeCartesianProductBenchmark<StableSort, AllValueTypes, AllOrders>(
|
||||
Quantities);
|
||||
makeCartesianProductBenchmark<MakeHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
makeCartesianProductBenchmark<SortHeap, AllValueTypes>(Quantities);
|
||||
makeCartesianProductBenchmark<MakeThenSortHeap, AllValueTypes, AllOrders>(
|
||||
Quantities);
|
||||
makeCartesianProductBenchmark<PushHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
makeCartesianProductBenchmark<PopHeap, AllValueTypes>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
||||
|
124
benchmarks/algorithms.partition_point.bench.cpp
Normal file
124
benchmarks/algorithms.partition_point.bench.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "CartesianBenchmarks.hpp"
|
||||
#include "GenerateInput.hpp"
|
||||
|
||||
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();
|
||||
}
|
232
benchmarks/function.bench.cpp
Normal file
232
benchmarks/function.bench.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "CartesianBenchmarks.hpp"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class FunctionType {
|
||||
Null,
|
||||
FunctionPointer,
|
||||
MemberFunctionPointer,
|
||||
MemberPointer,
|
||||
SmallTrivialFunctor,
|
||||
SmallNonTrivialFunctor,
|
||||
LargeTrivialFunctor,
|
||||
LargeNonTrivialFunctor
|
||||
};
|
||||
|
||||
struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {
|
||||
static constexpr const char* Names[] = {"Null",
|
||||
"FuncPtr",
|
||||
"MemFuncPtr",
|
||||
"MemPtr",
|
||||
"SmallTrivialFunctor",
|
||||
"SmallNonTrivialFunctor",
|
||||
"LargeTrivialFunctor",
|
||||
"LargeNonTrivialFunctor"};
|
||||
};
|
||||
|
||||
enum class Opacity { kOpaque, kTransparent };
|
||||
|
||||
struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
|
||||
static constexpr const char* Names[] = {"Opaque", "Transparent"};
|
||||
};
|
||||
|
||||
struct S {
|
||||
int function() const { return 0; }
|
||||
int field = 0;
|
||||
};
|
||||
|
||||
int FunctionWithS(const S*) { return 0; }
|
||||
|
||||
struct SmallTrivialFunctor {
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct SmallNonTrivialFunctor {
|
||||
SmallNonTrivialFunctor() {}
|
||||
SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {}
|
||||
~SmallNonTrivialFunctor() {}
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct LargeTrivialFunctor {
|
||||
LargeTrivialFunctor() {
|
||||
// Do not spend time initializing the padding.
|
||||
}
|
||||
int padding[16];
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct LargeNonTrivialFunctor {
|
||||
int padding[16];
|
||||
LargeNonTrivialFunctor() {
|
||||
// Do not spend time initializing the padding.
|
||||
}
|
||||
LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {}
|
||||
~LargeNonTrivialFunctor() {}
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
|
||||
using Function = std::function<int(const S*)>;
|
||||
|
||||
TEST_ALWAYS_INLINE
|
||||
inline Function MakeFunction(FunctionType type, bool opaque = false) {
|
||||
switch (type) {
|
||||
case FunctionType::Null:
|
||||
return nullptr;
|
||||
case FunctionType::FunctionPointer:
|
||||
return maybeOpaque(FunctionWithS, opaque);
|
||||
case FunctionType::MemberFunctionPointer:
|
||||
return maybeOpaque(&S::function, opaque);
|
||||
case FunctionType::MemberPointer:
|
||||
return maybeOpaque(&S::field, opaque);
|
||||
case FunctionType::SmallTrivialFunctor:
|
||||
return maybeOpaque(SmallTrivialFunctor{}, opaque);
|
||||
case FunctionType::SmallNonTrivialFunctor:
|
||||
return maybeOpaque(SmallNonTrivialFunctor{}, opaque);
|
||||
case FunctionType::LargeTrivialFunctor:
|
||||
return maybeOpaque(LargeTrivialFunctor{}, opaque);
|
||||
case FunctionType::LargeNonTrivialFunctor:
|
||||
return maybeOpaque(LargeNonTrivialFunctor{}, opaque);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Opacity, class FunctionType>
|
||||
struct ConstructAndDestroy {
|
||||
static void run(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
if (Opacity() == ::Opacity::kOpaque) {
|
||||
benchmark::DoNotOptimize(MakeFunction(FunctionType(), true));
|
||||
} else {
|
||||
MakeFunction(FunctionType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Copy {
|
||||
static void run(benchmark::State& state) {
|
||||
auto value = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(value);
|
||||
auto copy = value; // NOLINT
|
||||
benchmark::DoNotOptimize(copy);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_Copy" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Move {
|
||||
static void run(benchmark::State& state) {
|
||||
Function values[2] = {MakeFunction(FunctionType())};
|
||||
int i = 0;
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(values);
|
||||
benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));
|
||||
i ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_Move" + FunctionType::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Function1, class Function2>
|
||||
struct Swap {
|
||||
static void run(benchmark::State& state) {
|
||||
Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())};
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(values);
|
||||
values[0].swap(values[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return Function1() > Function2(); }
|
||||
|
||||
static std::string name() {
|
||||
return "BM_Swap" + Function1::name() + Function2::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct OperatorBool {
|
||||
static void run(benchmark::State& state) {
|
||||
auto f = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(f);
|
||||
benchmark::DoNotOptimize(static_cast<bool>(f));
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Invoke {
|
||||
static void run(benchmark::State& state) {
|
||||
S s;
|
||||
const auto value = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(value);
|
||||
benchmark::DoNotOptimize(value(&s));
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return FunctionType() == ::FunctionType::Null; }
|
||||
|
||||
static std::string name() { return "BM_Invoke" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct InvokeInlined {
|
||||
static void run(benchmark::State& state) {
|
||||
S s;
|
||||
for (auto _ : state) {
|
||||
MakeFunction(FunctionType())(&s);
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return FunctionType() == ::FunctionType::Null; }
|
||||
|
||||
static std::string name() {
|
||||
return "BM_InvokeInlined" + FunctionType::name();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity,
|
||||
AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Copy, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Move, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
23
benchmarks/lit.cfg.py
Normal file
23
benchmarks/lit.cfg.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
|
||||
# Configuration file for the 'lit' test runner.
|
||||
import os
|
||||
import site
|
||||
|
||||
site.addsitedir(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'utils'))
|
||||
from libcxx.test.googlebenchmark import GoogleBenchmark
|
||||
|
||||
# Tell pylint that we know config and lit_config exist somewhere.
|
||||
if 'PYLINT_IMPORT' in os.environ:
|
||||
config = object()
|
||||
lit_config = object()
|
||||
|
||||
# name: The name of this test suite.
|
||||
config.name = 'libc++ benchmarks'
|
||||
config.suffixes = []
|
||||
|
||||
config.test_exec_root = os.path.join(config.libcxx_obj_root, 'benchmarks')
|
||||
config.test_source_root = config.test_exec_root
|
||||
|
||||
config.test_format = GoogleBenchmark(test_sub_dirs='.',
|
||||
test_suffix='.libcxx.out',
|
||||
benchmark_args=config.benchmark_args)
|
10
benchmarks/lit.site.cfg.py.in
Normal file
10
benchmarks/lit.site.cfg.py.in
Normal file
@ -0,0 +1,10 @@
|
||||
@LIT_SITE_CFG_IN_HEADER@
|
||||
|
||||
import sys
|
||||
|
||||
config.libcxx_src_root = "@LIBCXX_SOURCE_DIR@"
|
||||
config.libcxx_obj_root = "@LIBCXX_BINARY_DIR@"
|
||||
config.benchmark_args = "@LIBCXX_BENCHMARK_TEST_ARGS@".split(';')
|
||||
|
||||
# Let the main config do the real work.
|
||||
lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/benchmarks/lit.cfg.py")
|
249
benchmarks/ordered_set.bench.cpp
Normal file
249
benchmarks/ordered_set.bench.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "CartesianBenchmarks.hpp"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class HitType { Hit, Miss };
|
||||
|
||||
struct AllHitTypes : EnumValuesAsTuple<AllHitTypes, HitType, 2> {
|
||||
static constexpr const char* Names[] = {"Hit", "Miss"};
|
||||
};
|
||||
|
||||
enum class AccessPattern { Ordered, Random };
|
||||
|
||||
struct AllAccessPattern
|
||||
: EnumValuesAsTuple<AllAccessPattern, AccessPattern, 2> {
|
||||
static constexpr const char* Names[] = {"Ordered", "Random"};
|
||||
};
|
||||
|
||||
void sortKeysBy(std::vector<uint64_t>& Keys, AccessPattern AP) {
|
||||
if (AP == AccessPattern::Random) {
|
||||
std::random_device R;
|
||||
std::mt19937 M(R());
|
||||
std::shuffle(std::begin(Keys), std::end(Keys), M);
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSets {
|
||||
std::vector<std::set<uint64_t> > Sets;
|
||||
std::vector<uint64_t> Keys;
|
||||
};
|
||||
|
||||
TestSets makeTestingSets(size_t TableSize, size_t NumTables, HitType Hit,
|
||||
AccessPattern Access) {
|
||||
TestSets R;
|
||||
R.Sets.resize(1);
|
||||
|
||||
for (uint64_t I = 0; I < TableSize; ++I) {
|
||||
R.Sets[0].insert(2 * I);
|
||||
R.Keys.push_back(Hit == HitType::Hit ? 2 * I : 2 * I + 1);
|
||||
}
|
||||
R.Sets.resize(NumTables, R.Sets[0]);
|
||||
sortKeysBy(R.Keys, Access);
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
struct Base {
|
||||
size_t TableSize;
|
||||
size_t NumTables;
|
||||
Base(size_t T, size_t N) : TableSize(T), NumTables(N) {}
|
||||
|
||||
bool skip() const {
|
||||
size_t Total = TableSize * NumTables;
|
||||
return Total < 100 || Total > 1000000;
|
||||
}
|
||||
|
||||
std::string baseName() const {
|
||||
return "_TableSize" + std::to_string(TableSize) + "_NumTables" +
|
||||
std::to_string(NumTables);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct Create : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
std::vector<uint64_t> Keys(TableSize);
|
||||
std::iota(Keys.begin(), Keys.end(), uint64_t{0});
|
||||
sortKeysBy(Keys, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
std::vector<std::set<uint64_t>> Sets(NumTables);
|
||||
for (auto K : Keys) {
|
||||
for (auto& Set : Sets) {
|
||||
benchmark::DoNotOptimize(Set.insert(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Create" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Hit, class Access>
|
||||
struct Find : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.find(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Find" + Hit::name() + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Hit, class Access>
|
||||
struct FindNeEnd : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.find(K) != Set.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_FindNeEnd" + Hit::name() + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct InsertHit : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Hit, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.insert(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_InsertHit" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct InsertMissAndErase : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.erase(Set.insert(K).first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_InsertMissAndErase" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
struct IterateRangeFor : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
|
||||
AccessPattern::Ordered);
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
for (auto& V : Set) {
|
||||
benchmark::DoNotOptimize(V);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const { return "BM_IterateRangeFor" + baseName(); }
|
||||
};
|
||||
|
||||
struct IterateBeginEnd : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
|
||||
AccessPattern::Ordered);
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
for (auto it = Set.begin(); it != Set.end(); ++it) {
|
||||
benchmark::DoNotOptimize(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const { return "BM_IterateBeginEnd" + baseName(); }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
const std::vector<size_t> TableSize{1, 10, 100, 1000, 10000, 100000, 1000000};
|
||||
const std::vector<size_t> NumTables{1, 10, 100, 1000, 10000, 100000, 1000000};
|
||||
|
||||
makeCartesianProductBenchmark<Create, AllAccessPattern>(TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<Find, AllHitTypes, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<FindNeEnd, AllHitTypes, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<InsertHit, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<InsertMissAndErase, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<IterateRangeFor>(TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<IterateBeginEnd>(TableSize, NumTables);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include <cstdint>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
#include "CartesianBenchmarks.hpp"
|
||||
#include "GenerateInput.hpp"
|
||||
#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,30 +44,332 @@ 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);
|
||||
|
||||
static void BM_StringCtorDefault(benchmark::State &state) {
|
||||
while (state.KeepRunning()) {
|
||||
for (unsigned I=0; I < 1000; ++I) {
|
||||
std::string Default;
|
||||
benchmark::DoNotOptimize(Default.c_str());
|
||||
}
|
||||
for (auto _ : state) {
|
||||
std::string Default;
|
||||
benchmark::DoNotOptimize(Default);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_StringCtorDefault);
|
||||
|
||||
static void BM_StringCtorCStr(benchmark::State &state) {
|
||||
std::string Input = getRandomString(state.range(0));
|
||||
const char *Str = Input.c_str();
|
||||
benchmark::DoNotOptimize(Str);
|
||||
while (state.KeepRunning()) {
|
||||
std::string Tmp(Str);
|
||||
benchmark::DoNotOptimize(Tmp.c_str());
|
||||
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"};
|
||||
};
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getSmallString(DiffType D) {
|
||||
switch (D) {
|
||||
case DiffType::Control:
|
||||
return "0123456";
|
||||
case DiffType::ChangeFirst:
|
||||
return "-123456";
|
||||
case DiffType::ChangeMiddle:
|
||||
return "012-456";
|
||||
case DiffType::ChangeLast:
|
||||
return "012345-";
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_StringCtorCStr)->Arg(1)->Arg(8)->Range(16, MAX_STRING_LEN / 4);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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<StringRead, AllTemperatures, AllDepths,
|
||||
AllLengths>();
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <sstream>
|
||||
double __attribute__((noinline)) istream_numbers();
|
||||
|
||||
TEST_NOINLINE double istream_numbers();
|
||||
|
||||
double istream_numbers() {
|
||||
const char *a[] = {
|
||||
|
@ -9,25 +9,26 @@
|
||||
|
||||
#include "ContainerBenchmarks.hpp"
|
||||
#include "GenerateInput.hpp"
|
||||
#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));
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ function(find_compiler_rt_library name dest)
|
||||
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
|
||||
|
@ -41,7 +41,7 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs)
|
||||
get_filename_component(ifile ${fpath} NAME)
|
||||
set(src ${incpath}/${fpath})
|
||||
|
||||
set(dst ${LIBCXX_BINARY_INCLUDE_DIR}/${dstdir}/${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}
|
||||
|
@ -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})
|
||||
|
@ -222,6 +222,15 @@ libc++ specific options
|
||||
|
||||
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
|
||||
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 avoid exporting any libc++ symbols in that case.
|
||||
|
||||
.. _libc++experimental options:
|
||||
|
||||
libc++experimental Specific Options
|
||||
@ -316,6 +325,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**:: ``""``
|
||||
@ -332,6 +350,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
|
||||
--------------------------
|
||||
@ -351,6 +378,20 @@ 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**: ``""``
|
||||
|
@ -24,11 +24,11 @@ systems. For example::
|
||||
|
||||
// Define availability macros.
|
||||
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE)
|
||||
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
|
||||
# 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
|
||||
# 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.
|
||||
@ -43,9 +43,9 @@ For example::
|
||||
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 {
|
||||
_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:
|
||||
|
||||
@ -55,7 +55,7 @@ or on a particular symbol:
|
||||
Testing
|
||||
=======
|
||||
|
||||
Some parameters can be passed to lit to run the test-suite and exercising the
|
||||
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
|
||||
@ -65,14 +65,11 @@ availability.
|
||||
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/`.
|
||||
* The `with_availability` boolean parameter enables the availability markup.
|
||||
|
||||
Tests can be marked as XFAIL based on multiple features made available by lit:
|
||||
|
||||
|
||||
* if either `use_system_cxx_lib` or `with_availability` is passed to lit,
|
||||
assuming `--param=platform=macosx10.8` is passed as well the following
|
||||
features will be available:
|
||||
* if `--param=platform=macosx10.8` is passed, the following features will be available:
|
||||
|
||||
- availability
|
||||
- availability=x86_64
|
||||
@ -81,11 +78,11 @@ Tests can be marked as XFAIL based on multiple features made available by lit:
|
||||
- availability=x86_64-apple-macosx10.8
|
||||
- availability=macosx10.8
|
||||
|
||||
This feature is used to XFAIL a test that *is* using a class of a method marked
|
||||
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` is passed to lit, the following features will also
|
||||
be available:
|
||||
* 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
|
||||
@ -94,21 +91,9 @@ Tests can be marked as XFAIL based on multiple features made available by lit:
|
||||
- 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 of a method
|
||||
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 we know that it exhibits a but in the libc on a
|
||||
particular system version.
|
||||
|
||||
* if `with_availability` is passed to lit, the following features will also
|
||||
be available:
|
||||
|
||||
- availability_markup
|
||||
- availability_markup=x86_64
|
||||
- availability_markup=macosx
|
||||
- availability_markup=x86_64-macosx
|
||||
- availability_markup=x86_64-apple-macosx10.8
|
||||
- availability_markup=macosx10.8
|
||||
|
||||
This feature is used to XFAIL a test that *is* using a class of a method
|
||||
marked as unavailable *but* that is expected to *pass* if deployed on an older
|
||||
system. For example if it is using a symbol in a statically evaluated context.
|
||||
system. For example, if the test exhibits a bug in the libc on a particular
|
||||
system version, or if the test uses a symbol that is not available on an
|
||||
older version of the dylib (but for which there is no availability markup,
|
||||
otherwise the XFAIL should use `availability` above).
|
||||
|
@ -28,7 +28,7 @@ Design Goals
|
||||
It makes developers lives harder if they have to regenerate the libc++ headers
|
||||
every time they are modified.
|
||||
|
||||
* The solution should not make any of the libc++ headers dependant on
|
||||
* The solution should not make any of the libc++ headers dependent on
|
||||
files generated by the build system. The headers should be able to compile
|
||||
out of the box without any modification.
|
||||
|
||||
|
44
docs/DesignDocs/FeatureTestMacros.rst
Normal file
44
docs/DesignDocs/FeatureTestMacros.rst
Normal file
@ -0,0 +1,44 @@
|
||||
===================
|
||||
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/test/std/language.support/support.limits/support.limits.general/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.
|
@ -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
|
||||
@ -42,9 +42,57 @@ Visibility Macros
|
||||
|
||||
**_LIBCPP_HIDE_FROM_ABI**
|
||||
Mark a function as not being part of the ABI of any final linked image that
|
||||
uses it, and also as being internal to each TU that uses that function. In
|
||||
other words, the address of a function marked with this attribute is not
|
||||
guaranteed to be the same across translation units.
|
||||
uses it.
|
||||
|
||||
**_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.
|
||||
@ -139,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*.
|
||||
|
200
docs/FeatureTestMacroTable.rst
Normal file
200
docs/FeatureTestMacroTable.rst
Normal file
@ -0,0 +1,200 @@
|
||||
.. _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`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_erase_if`` ``201811L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_generic_unordered_lookup`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_constant_evaluated`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_list_remove_return_type`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_ranges`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_three_way_comparison`` *unimplemented*
|
||||
================================================= =================
|
||||
|
||||
|
62
docs/ReleaseNotes.rst
Normal file
62
docs/ReleaseNotes.rst
Normal file
@ -0,0 +1,62 @@
|
||||
========================================
|
||||
Libc++ 8.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++ 8 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 8.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++ 8.0.0?
|
||||
===========================
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
API Changes
|
||||
-----------
|
||||
- Building libc++ for Mac OSX 10.6 is not supported anymore.
|
||||
- Starting with LLVM 8.0.0, users that wish to link together translation units
|
||||
built with different versions of libc++'s headers into the same final linked
|
||||
image MUST define the _LIBCPP_HIDE_FROM_ABI_PER_TU macro to 1 when building
|
||||
those translation units. Not defining _LIBCPP_HIDE_FROM_ABI_PER_TU to 1 and
|
||||
linking translation units built with different versions of libc++'s headers
|
||||
together may lead to ODR violations and ABI issues. On the flipside, code
|
||||
size improvements should be expected for everyone not defining the macro.
|
||||
- Starting with LLVM 8.0.0, std::dynarray has been removed from the library.
|
||||
std::dynarray was a feature proposed for C++14 that was pulled from the
|
||||
Standard at the last minute and was never standardized. Since there are no
|
||||
plans to standardize this facility it is being removed.
|
||||
- Starting with LLVM 8.0.0, std::bad_array_length has been removed from the
|
||||
library. std::bad_array_length was a feature proposed for C++14 alongside
|
||||
std::dynarray, but it never actually made it into the C++ Standard. There
|
||||
are no plans to standardize this feature at this time. Formally speaking,
|
||||
this removal constitutes an ABI break because the symbols were shipped in
|
||||
the shared library. However, on macOS systems, the feature was not usable
|
||||
because it was hidden behind availability annotations. We do not expect
|
||||
any actual breakage to happen from this change.
|
@ -138,8 +138,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 +154,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.
|
||||
|
@ -203,8 +203,10 @@ 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++
|
||||
@ -226,6 +228,26 @@ thread safety annotations.
|
||||
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_ENABLE_DEPRECATION_WARNINGS**:
|
||||
This macro enables warnings when using deprecated components. For example,
|
||||
when compiling in C++11 mode, using `std::auto_ptr` with the macro defined
|
||||
will trigger a warning saying that `std::auto_ptr` is deprecated. By default,
|
||||
this macro is not defined.
|
||||
|
||||
C++17 Specific Configuration Macros
|
||||
-----------------------------------
|
||||
**_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES**:
|
||||
@ -238,3 +260,58 @@ 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).
|
||||
|
||||
* ``get_temporary_buffer``
|
||||
|
@ -40,16 +40,16 @@
|
||||
|
||||
# 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 = '7.0'
|
||||
version = '8.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '7.0'
|
||||
release = '8.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@ -241,7 +241,7 @@
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
|
||||
# FIXME: Define intersphinx configration.
|
||||
# FIXME: Define intersphinx configuration.
|
||||
intersphinx_mapping = {}
|
||||
|
||||
|
||||
|
@ -34,11 +34,17 @@ Getting Started with libc++
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
ReleaseNotes
|
||||
UsingLibcxx
|
||||
BuildingLibcxx
|
||||
TestingLibcxx
|
||||
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
FeatureTestMacroTable
|
||||
|
||||
Current Status
|
||||
--------------
|
||||
|
||||
@ -79,8 +85,8 @@ 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.
|
||||
|
||||
@ -104,8 +110,9 @@ 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
|
||||
----------------------
|
||||
@ -135,6 +142,7 @@ Design Documents
|
||||
DesignDocs/VisibilityMacros
|
||||
DesignDocs/ThreadingSupportAPI
|
||||
DesignDocs/FileTimeType
|
||||
DesignDocs/FeatureTestMacros
|
||||
|
||||
* `<atomic> design <http://libcxx.llvm.org/atomic_design.html>`_
|
||||
* `<type_traits> design <http://libcxx.llvm.org/type_traits_design.html>`_
|
||||
@ -160,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>`_.
|
||||
|
||||
|
||||
|
||||
@ -183,7 +188,7 @@ 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`_
|
||||
* `libcxx-commits Mailing List`_
|
||||
* `libcxx-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/>`_
|
||||
|
@ -8,18 +8,18 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// A set of routines to use when fuzzing the algorithms in libc++
|
||||
// Each one tests a single algorithm.
|
||||
// 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 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.
|
||||
// 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.
|
||||
// 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.
|
||||
|
||||
|
||||
|
||||
@ -32,574 +32,587 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// If we had C++14, we could use the four iterator version of is_permutation and equal
|
||||
// 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.
|
||||
// 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) {}
|
||||
};
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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) 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;
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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
|
||||
// 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;
|
||||
size_t xBuckets[256] = {0};
|
||||
size_t xPayloads[256] = {0};
|
||||
size_t yBuckets[256] = {0};
|
||||
size_t yPayloads[256] = {0};
|
||||
|
||||
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;
|
||||
}
|
||||
for (; first1 != last1; ++first1, ++first2)
|
||||
{
|
||||
xBuckets [first1->key]++;
|
||||
xPayloads[first1->key] += first1->payload;
|
||||
|
||||
return true;
|
||||
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;
|
||||
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), "");
|
||||
|
||||
return true;
|
||||
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 ==
|
||||
// == sort ==
|
||||
int sort(const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec working(data, data + size);
|
||||
std::sort(working.begin(), working.end());
|
||||
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;
|
||||
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 ==
|
||||
// == 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());
|
||||
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;
|
||||
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 ==
|
||||
// == 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>());
|
||||
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;
|
||||
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 ==
|
||||
// == 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>());
|
||||
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;
|
||||
// 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;
|
||||
// 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
|
||||
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;
|
||||
// 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 ==
|
||||
// == 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>());
|
||||
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;
|
||||
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
|
||||
// == 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());
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// == partial_sort ==
|
||||
// use the first element as a position into the data
|
||||
// == 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 (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;
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// == partial_sort_copy ==
|
||||
// use the first element as a count
|
||||
// == 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());
|
||||
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 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 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"
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
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 '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;
|
||||
// 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 ==
|
||||
// == 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;
|
||||
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
|
||||
|
||||
// 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;
|
||||
// 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 ==
|
||||
// == 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;
|
||||
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
|
||||
|
||||
// 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;
|
||||
// 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
|
||||
// -- 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;
|
||||
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;
|
||||
(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;
|
||||
(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;
|
||||
(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;
|
||||
(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;
|
||||
(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;
|
||||
(void) regex_helper(data, size, std::regex_constants::egrep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -- heap fuzzers
|
||||
// -- heap fuzzers
|
||||
int make_heap (const uint8_t *data, size_t size)
|
||||
{
|
||||
Vec working(data, data + size);
|
||||
std::make_heap(working.begin(), working.end());
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
// 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;
|
||||
}
|
||||
// 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;
|
||||
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());
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// -- search fuzzers
|
||||
// -- 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;
|
||||
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;
|
||||
if (size < 2) return 0;
|
||||
|
||||
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;
|
||||
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
|
||||
// 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);
|
||||
// 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);
|
||||
// return search_helper<std::boyer_moore_horspool_searcher<const uint8_t *>>(data, size);
|
||||
// }
|
||||
|
||||
|
||||
// -- set operation fuzzers
|
||||
// -- 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);
|
||||
assert(size > 1);
|
||||
|
||||
std::sort(v1.begin(), v1.end());
|
||||
std::sort(v2.begin(), v2.end());
|
||||
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
|
||||
|
@ -25,6 +25,7 @@ set(files
|
||||
any
|
||||
array
|
||||
atomic
|
||||
bit
|
||||
bitset
|
||||
cassert
|
||||
ccomplex
|
||||
@ -68,7 +69,6 @@ set(files
|
||||
experimental/chrono
|
||||
experimental/coroutine
|
||||
experimental/deque
|
||||
experimental/dynarray
|
||||
experimental/filesystem
|
||||
experimental/forward_list
|
||||
experimental/functional
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define _LIBCPP___BIT_REFERENCE
|
||||
|
||||
#include <__config>
|
||||
#include <bit>
|
||||
#include <algorithm>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
@ -254,18 +255,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::__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::__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::__popcount(*__first.__seg_ & __m);
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
@ -285,18 +286,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::__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::__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::__popcount(~*__first.__seg_ & __m);
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
|
341
include/__config
341
include/__config
@ -33,14 +33,10 @@
|
||||
# define _GNUC_VER_NEW 0
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_VERSION 7000
|
||||
#define _LIBCPP_VERSION 8000
|
||||
|
||||
#ifndef _LIBCPP_ABI_VERSION
|
||||
# ifdef __Fuchsia__
|
||||
# define _LIBCPP_ABI_VERSION 2
|
||||
# else
|
||||
# define _LIBCPP_ABI_VERSION 1
|
||||
# endif
|
||||
# define _LIBCPP_ABI_VERSION 1
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_STD_VER
|
||||
@ -99,6 +95,8 @@
|
||||
// Use the smallest possible integer type to represent the index of the variant.
|
||||
// Previously libc++ used "unsigned int" exclusivly.
|
||||
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
|
||||
// Unstable attempt to provide a more optimized std::function
|
||||
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
|
||||
#elif _LIBCPP_ABI_VERSION == 1
|
||||
# if !defined(_LIBCPP_OBJECT_FORMAT_COFF)
|
||||
// Enable compiling copies of now inline methods into the dylib to support
|
||||
@ -123,7 +121,9 @@
|
||||
#define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
|
||||
#define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y)
|
||||
|
||||
#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION)
|
||||
#ifndef _LIBCPP_ABI_NAMESPACE
|
||||
# define _LIBCPP_ABI_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION)
|
||||
#endif
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
#define _LIBCPP_CXX03_LANG
|
||||
@ -328,6 +328,43 @@
|
||||
# define _LIBCPP_NO_CFI
|
||||
#endif
|
||||
|
||||
#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L
|
||||
# if defined(__FreeBSD__)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# elif defined(__Fuchsia__)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# define _LIBCPP_HAS_TIMESPEC_GET
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# elif defined(__linux__)
|
||||
# if !defined(_LIBCPP_HAS_MUSL_LIBC)
|
||||
# if _LIBCPP_GLIBC_PREREQ(2, 15) || defined(__BIONIC__)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# endif
|
||||
# if _LIBCPP_GLIBC_PREREQ(2, 17)
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# define _LIBCPP_HAS_TIMESPEC_GET
|
||||
# endif
|
||||
# else // defined(_LIBCPP_HAS_MUSL_LIBC)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# define _LIBCPP_HAS_TIMESPEC_GET
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# endif
|
||||
# endif // __linux__
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
# define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp)
|
||||
#elif defined(_LIBCPP_COMPILER_CLANG)
|
||||
# define _LIBCPP_ALIGNOF(_Tp) _Alignof(_Tp)
|
||||
#else
|
||||
// This definition is potentially buggy, but it's only taken with GCC in C++03,
|
||||
// which we barely support anyway. See llvm.org/PR39713
|
||||
# define _LIBCPP_ALIGNOF(_Tp) __alignof(_Tp)
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp)
|
||||
|
||||
#if defined(_LIBCPP_COMPILER_CLANG)
|
||||
|
||||
// _LIBCPP_ALTERNATE_STRING_LAYOUT is an old name for
|
||||
@ -342,7 +379,7 @@
|
||||
# define _ALIGNAS_TYPE(x) alignas(x)
|
||||
# define _ALIGNAS(x) alignas(x)
|
||||
#else
|
||||
# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x))))
|
||||
# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x))))
|
||||
# define _ALIGNAS(x) __attribute__((__aligned__(x)))
|
||||
#endif
|
||||
|
||||
@ -430,28 +467,6 @@ typedef __char32_t char32_t;
|
||||
#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES
|
||||
#endif
|
||||
|
||||
#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L
|
||||
# if defined(__FreeBSD__)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# elif defined(__Fuchsia__)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# elif defined(__linux__)
|
||||
# if !defined(_LIBCPP_HAS_MUSL_LIBC)
|
||||
# if _LIBCPP_GLIBC_PREREQ(2, 15) || defined(__BIONIC__)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# endif
|
||||
# if _LIBCPP_GLIBC_PREREQ(2, 17)
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# endif
|
||||
# else // defined(_LIBCPP_HAS_MUSL_LIBC)
|
||||
# define _LIBCPP_HAS_QUICK_EXIT
|
||||
# define _LIBCPP_HAS_C11_FEATURES
|
||||
# endif
|
||||
# endif // __linux__
|
||||
#endif
|
||||
|
||||
#if !(__has_feature(cxx_noexcept))
|
||||
#define _LIBCPP_HAS_NO_NOEXCEPT
|
||||
#endif
|
||||
@ -464,16 +479,6 @@ typedef __char32_t char32_t;
|
||||
#define _LIBCPP_IS_LITERAL(T) __is_literal(T)
|
||||
#endif
|
||||
|
||||
// Inline namespaces are available in Clang regardless of C++ dialect.
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE {
|
||||
#define _LIBCPP_END_NAMESPACE_STD } }
|
||||
#define _VSTD std::_LIBCPP_NAMESPACE
|
||||
|
||||
namespace std {
|
||||
inline namespace _LIBCPP_NAMESPACE {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_ASAN) && !__has_feature(address_sanitizer)
|
||||
#define _LIBCPP_HAS_NO_ASAN
|
||||
#endif
|
||||
@ -493,10 +498,15 @@ namespace std {
|
||||
|
||||
#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__))
|
||||
|
||||
// No apple compilers support ""d and ""y at this time.
|
||||
#if _LIBCPP_CLANG_VER < 800 || defined(__apple_build_version__)
|
||||
#define _LIBCPP_HAS_NO_CXX20_CHRONO_LITERALS
|
||||
#endif
|
||||
|
||||
#elif defined(_LIBCPP_COMPILER_GCC)
|
||||
|
||||
#define _ALIGNAS(x) __attribute__((__aligned__(x)))
|
||||
#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x))))
|
||||
#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x))))
|
||||
|
||||
#define _LIBCPP_NORETURN __attribute__((noreturn))
|
||||
|
||||
@ -563,15 +573,6 @@ namespace std {
|
||||
|
||||
#endif // __GXX_EXPERIMENTAL_CXX0X__
|
||||
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { inline namespace _LIBCPP_NAMESPACE {
|
||||
#define _LIBCPP_END_NAMESPACE_STD } }
|
||||
#define _VSTD std::_LIBCPP_NAMESPACE
|
||||
|
||||
namespace std {
|
||||
inline namespace _LIBCPP_NAMESPACE {
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_ASAN) && !defined(__SANITIZE_ADDRESS__)
|
||||
#define _LIBCPP_HAS_NO_ASAN
|
||||
#endif
|
||||
@ -607,13 +608,6 @@ namespace std {
|
||||
#define _ALIGNAS_TYPE(x) alignas(x)
|
||||
#define _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
|
||||
#define _LIBCPP_END_NAMESPACE_STD }
|
||||
#define _VSTD std
|
||||
|
||||
namespace std {
|
||||
}
|
||||
|
||||
#define _LIBCPP_WEAK
|
||||
|
||||
#define _LIBCPP_HAS_NO_ASAN
|
||||
@ -625,7 +619,7 @@ namespace std {
|
||||
#elif defined(_LIBCPP_COMPILER_IBM)
|
||||
|
||||
#define _ALIGNAS(x) __attribute__((__aligned__(x)))
|
||||
#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x))))
|
||||
#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x))))
|
||||
#define _ATTRIBUTE(x) __attribute__((x))
|
||||
#define _LIBCPP_NORETURN __attribute__((noreturn))
|
||||
|
||||
@ -641,15 +635,6 @@ namespace std {
|
||||
#define __MULTILOCALE_API
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE {
|
||||
#define _LIBCPP_END_NAMESPACE_STD } }
|
||||
#define _VSTD std::_LIBCPP_NAMESPACE
|
||||
|
||||
namespace std {
|
||||
inline namespace _LIBCPP_NAMESPACE {
|
||||
}
|
||||
}
|
||||
|
||||
#define _LIBCPP_HAS_NO_ASAN
|
||||
|
||||
#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__))
|
||||
@ -658,20 +643,6 @@ namespace std {
|
||||
|
||||
#endif // _LIBCPP_COMPILER_[CLANG|GCC|MSVC|IBM]
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem {
|
||||
#else
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem {
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_END_NAMESPACE_FILESYSTEM \
|
||||
_LIBCPP_END_NAMESPACE_STD } }
|
||||
|
||||
#define _VSTD_FS _VSTD::__fs::filesystem
|
||||
|
||||
|
||||
#if defined(_LIBCPP_OBJECT_FORMAT_COFF)
|
||||
|
||||
#ifdef _DLL
|
||||
@ -685,33 +656,29 @@ namespace std {
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI
|
||||
#elif defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
# define _LIBCPP_DLL_VIS __declspec(dllexport)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllexport)
|
||||
#else
|
||||
# define _LIBCPP_DLL_VIS __declspec(dllimport)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_TYPE_VIS _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_FUNC_VIS _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_EXTERN_VIS _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_HIDDEN
|
||||
#define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
#define _LIBCPP_TEMPLATE_VIS
|
||||
#define _LIBCPP_ENUM_VIS
|
||||
|
||||
#if defined(_LIBCPP_COMPILER_MSVC)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline
|
||||
#else
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__ ((__always_inline__))
|
||||
#endif
|
||||
|
||||
#endif // defined(_LIBCPP_OBJECT_FORMAT_COFF)
|
||||
|
||||
#ifndef _LIBCPP_HIDDEN
|
||||
@ -759,8 +726,12 @@ namespace std {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_EXTERN_VIS
|
||||
#define _LIBCPP_EXTERN_VIS
|
||||
#ifndef _LIBCPP_EXPORTED_FROM_ABI
|
||||
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI __attribute__((__visibility__("default")))
|
||||
# else
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_OVERRIDABLE_FUNC_VIS
|
||||
@ -801,21 +772,63 @@ namespace std {
|
||||
# define _LIBCPP_INTERNAL_LINKAGE _LIBCPP_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HIDE_FROM_ABI
|
||||
# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_INTERNAL_LINKAGE
|
||||
#if __has_attribute(exclude_from_explicit_instantiation)
|
||||
# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__ ((__exclude_from_explicit_instantiation__))
|
||||
#else
|
||||
// Try to approximate the effect of exclude_from_explicit_instantiation
|
||||
// (which is that entities are not assumed to be provided by explicit
|
||||
// template instantitations in the dylib) by always inlining those entities.
|
||||
# define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION _LIBCPP_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
// Just so we can migrate to _LIBCPP_HIDE_FROM_ABI gradually.
|
||||
#define _LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI
|
||||
|
||||
#ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__visibility__("default"), __always_inline__))
|
||||
#ifndef _LIBCPP_HIDE_FROM_ABI_PER_TU
|
||||
# ifndef _LIBCPP_HIDE_FROM_ABI_PER_TU_BY_DEFAULT
|
||||
# define _LIBCPP_HIDE_FROM_ABI_PER_TU 0
|
||||
# else
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__always_inline__))
|
||||
# define _LIBCPP_HIDE_FROM_ABI_PER_TU 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HIDE_FROM_ABI
|
||||
# if _LIBCPP_HIDE_FROM_ABI_PER_TU
|
||||
# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_INTERNAL_LINKAGE
|
||||
# else
|
||||
# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _LIBCPP_BUILDING_LIBRARY
|
||||
# if _LIBCPP_ABI_VERSION > 1
|
||||
# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI
|
||||
# else
|
||||
# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
# endif
|
||||
#else
|
||||
# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI
|
||||
#endif
|
||||
|
||||
// Just so we can migrate to the new macros gradually.
|
||||
#define _LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI
|
||||
|
||||
// Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect.
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { inline namespace _LIBCPP_ABI_NAMESPACE {
|
||||
#define _LIBCPP_END_NAMESPACE_STD } }
|
||||
#define _VSTD std::_LIBCPP_ABI_NAMESPACE
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem {
|
||||
#else
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem {
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_END_NAMESPACE_FILESYSTEM \
|
||||
_LIBCPP_END_NAMESPACE_STD } }
|
||||
|
||||
#define _VSTD_FS _VSTD::__fs::filesystem
|
||||
|
||||
#ifndef _LIBCPP_PREFERRED_OVERLOAD
|
||||
# if __has_attribute(__enable_if__)
|
||||
# define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, "")))
|
||||
@ -976,7 +989,14 @@ template <unsigned> struct __static_assert_check {};
|
||||
// If we are getting operator new from the MSVC CRT, then allocation overloads
|
||||
// for align_val_t were added in 19.12, aka VS 2017 version 15.3.
|
||||
#if defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912
|
||||
#define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
|
||||
#elif defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME)
|
||||
# define _LIBCPP_DEFER_NEW_TO_VCRUNTIME
|
||||
# if !defined(__cpp_aligned_new)
|
||||
// We're defering to Microsoft's STL to provide aligned new et al. We don't
|
||||
// have it unless the language feature test macro is defined.
|
||||
# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
@ -984,13 +1004,13 @@ template <unsigned> struct __static_assert_check {};
|
||||
defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
|
||||
# define __MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||
# endif
|
||||
# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
|
||||
# if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
# endif
|
||||
# endif
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) && \
|
||||
(defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) || \
|
||||
(!defined(__cpp_aligned_new) || __cpp_aligned_new < 201606))
|
||||
# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#define _LIBCPP_HAS_DEFAULTRUNELOCALE
|
||||
@ -1000,18 +1020,46 @@ template <unsigned> struct __static_assert_check {};
|
||||
#define _LIBCPP_WCTYPE_IS_MASK
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
# define _LIBCPP_DEPRECATED [[deprecated]]
|
||||
#if _LIBCPP_STD_VER <= 17 || !defined(__cpp_char8_t)
|
||||
#define _LIBCPP_NO_HAS_CHAR8_T
|
||||
#endif
|
||||
|
||||
// Deprecation macros.
|
||||
// Deprecations warnings are only enabled when _LIBCPP_ENABLE_DEPRECATION_WARNINGS is defined.
|
||||
#if defined(_LIBCPP_ENABLE_DEPRECATION_WARNINGS)
|
||||
# if __has_attribute(deprecated)
|
||||
# define _LIBCPP_DEPRECATED __attribute__ ((deprecated))
|
||||
# elif _LIBCPP_STD_VER > 11
|
||||
# define _LIBCPP_DEPRECATED [[deprecated]]
|
||||
# else
|
||||
# define _LIBCPP_DEPRECATED
|
||||
# endif
|
||||
#else
|
||||
# define _LIBCPP_DEPRECATED
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_CXX03_LANG)
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED
|
||||
#else
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX11
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX14 _LIBCPP_DEPRECATED
|
||||
#else
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX14
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_DEPRECATED
|
||||
#else
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX17
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER <= 11
|
||||
# define _LIBCPP_EXPLICIT_AFTER_CXX11
|
||||
# define _LIBCPP_DEPRECATED_AFTER_CXX11
|
||||
#else
|
||||
# define _LIBCPP_EXPLICIT_AFTER_CXX11 explicit
|
||||
# define _LIBCPP_DEPRECATED_AFTER_CXX11 [[deprecated]]
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
|
||||
@ -1032,8 +1080,30 @@ template <unsigned> struct __static_assert_check {};
|
||||
# define _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
#endif
|
||||
|
||||
#if __has_cpp_attribute(nodiscard) && _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_DISABLE_NODISCARD_AFTER_CXX17)
|
||||
# define _LIBCPP_NODISCARD_AFTER_CXX17 [[nodiscard]]
|
||||
// The _LIBCPP_NODISCARD_ATTRIBUTE should only be used to define other
|
||||
// NODISCARD macros to the correct attribute.
|
||||
#if __has_cpp_attribute(nodiscard) || defined(_LIBCPP_COMPILER_MSVC)
|
||||
# define _LIBCPP_NODISCARD_ATTRIBUTE [[nodiscard]]
|
||||
#elif defined(_LIBCPP_COMPILER_CLANG) && !defined(_LIBCPP_CXX03_LANG)
|
||||
# define _LIBCPP_NODISCARD_ATTRIBUTE [[clang::warn_unused_result]]
|
||||
#else
|
||||
// We can't use GCC's [[gnu::warn_unused_result]] and
|
||||
// __attribute__((warn_unused_result)), because GCC does not silence them via
|
||||
// (void) cast.
|
||||
# define _LIBCPP_NODISCARD_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
// _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not
|
||||
// specified as such as an extension.
|
||||
#if defined(_LIBCPP_ENABLE_NODISCARD) && !defined(_LIBCPP_DISABLE_NODISCARD_EXT)
|
||||
# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD_ATTRIBUTE
|
||||
#else
|
||||
# define _LIBCPP_NODISCARD_EXT
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_DISABLE_NODISCARD_AFTER_CXX17) && \
|
||||
(_LIBCPP_STD_VER > 17 || defined(_LIBCPP_ENABLE_NODISCARD))
|
||||
# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD_ATTRIBUTE
|
||||
#else
|
||||
# define _LIBCPP_NODISCARD_AFTER_CXX17
|
||||
#endif
|
||||
@ -1090,6 +1160,7 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
defined(__Fuchsia__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(__linux__) || \
|
||||
defined(__GNU__) || \
|
||||
defined(__APPLE__) || \
|
||||
defined(__CloudABI__) || \
|
||||
defined(__sun__) || \
|
||||
@ -1195,8 +1266,12 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
# define _LIBCPP_DIAGNOSE_ERROR(...)
|
||||
#endif
|
||||
|
||||
#if __has_attribute(fallthough) || _GNUC_VER >= 700
|
||||
// Use a function like macro to imply that it must be followed by a semicolon
|
||||
#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
|
||||
# define _LIBCPP_FALLTHROUGH() [[fallthrough]]
|
||||
#elif __has_cpp_attribute(clang::fallthrough)
|
||||
# define _LIBCPP_FALLTHROUGH() [[clang::fallthrough]]
|
||||
#elif __has_attribute(fallthough) || _GNUC_VER >= 700
|
||||
# define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__))
|
||||
#else
|
||||
# define _LIBCPP_FALLTHROUGH() ((void)0)
|
||||
@ -1250,9 +1325,15 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
__attribute__((availability(ios,strict,introduced=10.0))) \
|
||||
__attribute__((availability(tvos,strict,introduced=10.0))) \
|
||||
__attribute__((availability(watchos,strict,introduced=3.0)))
|
||||
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
|
||||
# define _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH __attribute__((unavailable))
|
||||
# define _LIBCPP_AVAILABILITY_BAD_ANY_CAST __attribute__((unavailable))
|
||||
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \
|
||||
__attribute__((availability(macosx,strict,introduced=10.14))) \
|
||||
__attribute__((availability(ios,strict,introduced=12.0))) \
|
||||
__attribute__((availability(tvos,strict,introduced=12.0))) \
|
||||
__attribute__((availability(watchos,strict,introduced=5.0)))
|
||||
# define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS \
|
||||
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_BAD_ANY_CAST \
|
||||
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS \
|
||||
__attribute__((availability(macosx,strict,introduced=10.12))) \
|
||||
__attribute__((availability(ios,strict,introduced=10.0))) \
|
||||
@ -1276,8 +1357,8 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
__attribute__((availability(ios,strict,introduced=7.0)))
|
||||
#else
|
||||
# define _LIBCPP_AVAILABILITY_SHARED_MUTEX
|
||||
# define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
# define _LIBCPP_AVAILABILITY_BAD_ANY_CAST
|
||||
# define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS
|
||||
# define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE
|
||||
@ -1289,26 +1370,30 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
|
||||
// Define availability that depends on _LIBCPP_NO_EXCEPTIONS.
|
||||
#ifdef _LIBCPP_NO_EXCEPTIONS
|
||||
# define _LIBCPP_AVAILABILITY_DYNARRAY
|
||||
# define _LIBCPP_AVAILABILITY_FUTURE
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
|
||||
#else
|
||||
# define _LIBCPP_AVAILABILITY_DYNARRAY _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
# define _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_AVAILABILITY_FUTURE_ERROR
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST \
|
||||
_LIBCPP_AVAILABILITY_BAD_ANY_CAST
|
||||
# define _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_AVAILABILITY_FUTURE_ERROR
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST _LIBCPP_AVAILABILITY_BAD_ANY_CAST
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS
|
||||
#endif
|
||||
|
||||
// Availability of stream API in the dylib got dropped and re-added. The
|
||||
// extern template should effectively be available at:
|
||||
// availability(macosx,introduced=10.9)
|
||||
// availability(ios,introduced=7.0)
|
||||
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE) && \
|
||||
// The stream API was dropped and re-added in the dylib shipped on macOS
|
||||
// and iOS. We can only assume the dylib to provide these definitions for
|
||||
// macosx >= 10.9 and ios >= 7.0. Otherwise, the definitions are available
|
||||
// from the headers, but not from the dylib. Explicit instantiation
|
||||
// declarations for streams exist conditionally to this; if we provide
|
||||
// an explicit instantiation declaration and we try to deploy to a dylib
|
||||
// that does not provide those symbols, we'll get a load-time error.
|
||||
#if !defined(_LIBCPP_BUILDING_LIBRARY) && \
|
||||
((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1090) || \
|
||||
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 70000))
|
||||
#define _LIBCPP_AVAILABILITY_NO_STREAMS_EXTERN_TEMPLATE
|
||||
# define _LIBCPP_DO_NOT_ASSUME_STREAMS_EXPLICIT_INSTANTIATION_IN_DYLIB
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_COMPILER_IBM)
|
||||
@ -1351,6 +1436,8 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
# endif // defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
#endif // _LIBCPP_NO_AUTO_LINK
|
||||
|
||||
#define _LIBCPP_UNUSED_VAR(x) ((void)(x))
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _LIBCPP_CONFIG
|
||||
|
@ -14,6 +14,7 @@
|
||||
#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
|
||||
@ -27,6 +28,7 @@
|
||||
#cmakedefine _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL
|
||||
#cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS
|
||||
#cmakedefine _LIBCPP_NO_VCRUNTIME
|
||||
#cmakedefine _LIBCPP_ABI_NAMESPACE @_LIBCPP_ABI_NAMESPACE@
|
||||
|
||||
@_LIBCPP_ABI_DEFINES@
|
||||
|
||||
|
@ -74,7 +74,7 @@ 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
|
||||
|
@ -50,7 +50,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 +59,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)))
|
||||
@ -552,7 +552,7 @@ template <class _Tp, class, class = void>
|
||||
struct __is_transparent : false_type {};
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
struct __is_transparent<_Tp, _Up,
|
||||
struct __is_transparent<_Tp, _Up,
|
||||
typename __void_t<typename _Tp::is_transparent>::type>
|
||||
: true_type {};
|
||||
#endif
|
||||
@ -562,7 +562,7 @@ struct __is_transparent<_Tp, _Up,
|
||||
struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { };
|
||||
|
||||
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
extern const allocator_arg_t allocator_arg;
|
||||
extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg;
|
||||
#else
|
||||
/* _LIBCPP_INLINE_VAR */ constexpr allocator_arg_t allocator_arg = allocator_arg_t();
|
||||
#endif
|
||||
|
@ -35,15 +35,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
template <class _Key, class _Tp>
|
||||
struct __hash_value_type;
|
||||
|
||||
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>
|
||||
struct __is_hash_value_type_imp : false_type {};
|
||||
@ -418,7 +409,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_)
|
||||
{
|
||||
@ -871,35 +862,32 @@ struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc>
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class _Key, class _Hash, class _Equal>
|
||||
struct __enforce_unordered_container_requirements {
|
||||
#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");
|
||||
"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;
|
||||
}
|
||||
"the specified comparator is required to be copy constructible");
|
||||
#endif
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
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>
|
||||
{
|
||||
};
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
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 const call operator")
|
||||
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
|
||||
"the specified hash functor does not provide a 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
|
||||
@ -963,10 +951,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_;
|
||||
@ -1058,8 +1042,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);
|
||||
|
||||
@ -1170,6 +1172,9 @@ public:
|
||||
_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
|
||||
@ -1177,6 +1182,9 @@ public:
|
||||
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
|
||||
@ -1849,73 +1857,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)
|
||||
{
|
||||
@ -1923,8 +1970,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();
|
||||
@ -1938,24 +2021,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)
|
||||
@ -1966,6 +2031,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
|
||||
@ -2216,6 +2292,32 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
|
||||
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
|
||||
@ -2244,6 +2346,27 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
|
||||
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>
|
||||
|
@ -1 +1 @@
|
||||
7000
|
||||
8000
|
||||
|
@ -1255,13 +1255,13 @@ 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_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_INLINE_VISIBILITY
|
||||
@ -1289,13 +1289,13 @@ 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_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_INLINE_VISIBILITY
|
||||
@ -1345,13 +1345,13 @@ 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_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_INLINE_VISIBILITY
|
||||
@ -1379,13 +1379,13 @@ 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_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_INLINE_VISIBILITY
|
||||
|
@ -76,9 +76,9 @@ struct _LIBCPP_TYPE_VIS adopt_lock_t {};
|
||||
|
||||
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
|
||||
extern const defer_lock_t defer_lock;
|
||||
extern const try_to_lock_t try_to_lock;
|
||||
extern const adopt_lock_t adopt_lock;
|
||||
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
|
||||
|
||||
|
@ -26,8 +26,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
|
||||
#define __cpp_lib_node_extract 201606L
|
||||
|
||||
// Specialized in __tree & __hash_table for their _NodeType.
|
||||
template <class _NodeType, class _Alloc>
|
||||
struct __generic_container_node_destructor;
|
||||
|
@ -55,14 +55,14 @@ public:
|
||||
__allocated_ = true;
|
||||
return (pointer)&buf_;
|
||||
}
|
||||
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_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, __alignof(_Tp));
|
||||
_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);}
|
||||
|
||||
|
@ -47,6 +47,7 @@ struct char_traits
|
||||
|
||||
template <> struct char_traits<char>;
|
||||
template <> struct char_traits<wchar_t>;
|
||||
template <> struct char_traits<char8_t>; // c++20
|
||||
|
||||
} // std
|
||||
|
||||
@ -389,6 +390,102 @@ char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __
|
||||
}
|
||||
|
||||
|
||||
#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 <>
|
||||
|
@ -70,7 +70,7 @@ 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
|
||||
|
106
include/__tree
106
include/__tree
@ -40,10 +40,6 @@ template <class _Tp, class _VoidPtr> class __tree_node;
|
||||
template <class _Key, class _Value>
|
||||
struct __value_type;
|
||||
|
||||
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;
|
||||
template <class _TreeIterator> class _LIBCPP_TEMPLATE_VIS __map_const_iterator;
|
||||
@ -857,7 +853,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
|
||||
@ -966,24 +962,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 const call operator")
|
||||
#endif
|
||||
int __diagnose_non_const_comparator();
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
class __tree
|
||||
@ -1341,15 +1325,20 @@ public:
|
||||
|
||||
#endif // !_LIBCPP_CXX03_LANG
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
iterator __node_insert_unique(const_iterator __p,
|
||||
__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);
|
||||
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY iterator __remove_node_pointer(__node_pointer);
|
||||
_LIBCPP_INLINE_VISIBILITY iterator
|
||||
__remove_node_pointer(__node_pointer) _NOEXCEPT;
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
template <class _NodeHandle, class _InsertReturnType>
|
||||
@ -1358,6 +1347,9 @@ public:
|
||||
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
|
||||
@ -1365,6 +1357,9 @@ public:
|
||||
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>
|
||||
@ -1384,7 +1379,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);
|
||||
@ -1488,7 +1483,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
|
||||
@ -1830,7 +1825,7 @@ __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>());
|
||||
@ -1844,10 +1839,6 @@ __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());
|
||||
}
|
||||
|
||||
@ -2129,10 +2120,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;
|
||||
@ -2384,7 +2374,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p,
|
||||
|
||||
template <class _Tp, class _Compare, class _Allocator>
|
||||
typename __tree<_Tp, _Compare, _Allocator>::iterator
|
||||
__tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr)
|
||||
__tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _NOEXCEPT
|
||||
{
|
||||
iterator __r(__ptr);
|
||||
++__r;
|
||||
@ -2471,6 +2461,30 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p)
|
||||
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
|
||||
@ -2507,6 +2521,28 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(
|
||||
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>
|
||||
|
@ -22,36 +22,36 @@
|
||||
|
||||
_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;
|
||||
@ -165,7 +165,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)>
|
||||
{
|
||||
};
|
||||
@ -291,7 +291,7 @@ public:
|
||||
|
||||
|
||||
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)>
|
||||
{
|
||||
};
|
||||
|
@ -645,13 +645,8 @@ template <class BidirectionalIterator, class Compare>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(__IBMCPP__)
|
||||
#include "support/ibm/support.h"
|
||||
#endif
|
||||
#if defined(_LIBCPP_COMPILER_MSVC)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include <bit>
|
||||
#include <version>
|
||||
|
||||
#include <__debug>
|
||||
|
||||
@ -755,6 +750,32 @@ public:
|
||||
bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);}
|
||||
};
|
||||
|
||||
// Perform division by two quickly for positive integers (llvm.org/PR39129)
|
||||
|
||||
template <typename _Integral>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
typename enable_if
|
||||
<
|
||||
is_integral<_Integral>::value,
|
||||
_Integral
|
||||
>::type
|
||||
__half_positive(_Integral __value)
|
||||
{
|
||||
return static_cast<_Integral>(static_cast<typename make_unsigned<_Integral>::type>(__value) / 2);
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
typename enable_if
|
||||
<
|
||||
!is_integral<_Tp>::value,
|
||||
_Tp
|
||||
>::type
|
||||
__half_positive(_Tp __value)
|
||||
{
|
||||
return __value / 2;
|
||||
}
|
||||
|
||||
#ifdef _LIBCPP_DEBUG
|
||||
|
||||
template <class _Compare>
|
||||
@ -788,135 +809,6 @@ struct __debug_less
|
||||
|
||||
#endif // _LIBCPP_DEBUG
|
||||
|
||||
// Precondition: __x != 0
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
unsigned __ctz(unsigned __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return static_cast<unsigned>(__builtin_ctz(__x));
|
||||
#else
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
unsigned long where;
|
||||
// Search from LSB to MSB for first set bit.
|
||||
// Returns zero if no set bit is found.
|
||||
if (_BitScanForward(&where, __x))
|
||||
return where;
|
||||
return 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
unsigned long __ctz(unsigned long __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return static_cast<unsigned long>(__builtin_ctzl(__x));
|
||||
#else
|
||||
static_assert(sizeof(unsigned long) == sizeof(unsigned), "");
|
||||
return __ctz(static_cast<unsigned>(__x));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
unsigned long long __ctz(unsigned long long __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return static_cast<unsigned long long>(__builtin_ctzll(__x));
|
||||
#else
|
||||
unsigned long where;
|
||||
// Search from LSB to MSB for first set bit.
|
||||
// Returns zero if no set bit is found.
|
||||
#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.
|
||||
// Scan the Low Word.
|
||||
if (_BitScanForward(&where, static_cast<unsigned long>(__x)))
|
||||
return where;
|
||||
// Scan the High Word.
|
||||
if (_BitScanForward(&where, static_cast<unsigned long>(__x >> 32)))
|
||||
return where + 32; // Create a bit offset from the LSB.
|
||||
#endif
|
||||
return 64;
|
||||
#endif // _LIBCPP_COMPILER_MSVC
|
||||
}
|
||||
|
||||
// Precondition: __x != 0
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
unsigned __clz(unsigned __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return static_cast<unsigned>(__builtin_clz(__x));
|
||||
#else
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
unsigned long where;
|
||||
// Search from LSB to MSB for first set bit.
|
||||
// Returns zero if no set bit is found.
|
||||
if (_BitScanReverse(&where, __x))
|
||||
return 31 - where;
|
||||
return 32; // Undefined Behavior.
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
unsigned long __clz(unsigned long __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return static_cast<unsigned long>(__builtin_clzl (__x));
|
||||
#else
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
return __clz(static_cast<unsigned>(__x));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
unsigned long long __clz(unsigned long long __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return static_cast<unsigned long long>(__builtin_clzll(__x));
|
||||
#else
|
||||
unsigned long where;
|
||||
// BitScanReverse scans from MSB to LSB for first set bit.
|
||||
// Returns 0 if no set bit is found.
|
||||
#if defined(_LIBCPP_HAS_BITSCAN64)
|
||||
if (_BitScanReverse64(&where, __x))
|
||||
return static_cast<int>(63 - where);
|
||||
#else
|
||||
// Scan the high 32 bits.
|
||||
if (_BitScanReverse(&where, static_cast<unsigned long>(__x >> 32)))
|
||||
return 63 - (where + 32); // Create a bit offset from the MSB.
|
||||
// Scan the low 32 bits.
|
||||
if (_BitScanReverse(&where, static_cast<unsigned long>(__x)))
|
||||
return 63 - where;
|
||||
#endif
|
||||
return 64; // Undefined Behavior.
|
||||
#endif // _LIBCPP_COMPILER_MSVC
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return __builtin_popcount (__x);
|
||||
#else
|
||||
static_assert(sizeof(unsigned) == 4, "");
|
||||
return __popcnt(__x);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned long __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return __builtin_popcountl (__x);
|
||||
#else
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
return __popcnt(__x);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __pop_count(unsigned long long __x) {
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
return __builtin_popcountll(__x);
|
||||
#else
|
||||
static_assert(sizeof(unsigned long long) == 8, "");
|
||||
return __popcnt64(__x);
|
||||
#endif
|
||||
}
|
||||
|
||||
// all_of
|
||||
|
||||
template <class _InputIterator, class _Predicate>
|
||||
@ -2533,6 +2425,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_ForwardIterator
|
||||
min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
|
||||
{
|
||||
static_assert(__is_forward_iterator<_ForwardIterator>::value,
|
||||
"std::min_element requires a ForwardIterator");
|
||||
if (__first != __last)
|
||||
{
|
||||
_ForwardIterator __i = __first;
|
||||
@ -2597,6 +2491,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_ForwardIterator
|
||||
max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
|
||||
{
|
||||
static_assert(__is_forward_iterator<_ForwardIterator>::value,
|
||||
"std::max_element requires a ForwardIterator");
|
||||
if (__first != __last)
|
||||
{
|
||||
_ForwardIterator __i = __first;
|
||||
@ -2683,6 +2579,8 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
std::pair<_ForwardIterator, _ForwardIterator>
|
||||
minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
|
||||
{
|
||||
static_assert(__is_forward_iterator<_ForwardIterator>::value,
|
||||
"std::minmax_element requires a ForwardIterator");
|
||||
std::pair<_ForwardIterator, _ForwardIterator> __result(__first, __first);
|
||||
if (__first != __last)
|
||||
{
|
||||
@ -3027,10 +2925,11 @@ template<class _IntType>
|
||||
template<class _URNG>
|
||||
typename uniform_int_distribution<_IntType>::result_type
|
||||
uniform_int_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p)
|
||||
_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
|
||||
{
|
||||
typedef typename conditional<sizeof(result_type) <= sizeof(uint32_t),
|
||||
uint32_t, uint64_t>::type _UIntType;
|
||||
const _UIntType _Rp = __p.b() - __p.a() + _UIntType(1);
|
||||
const _UIntType _Rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1);
|
||||
if (_Rp == 1)
|
||||
return __p.a();
|
||||
const size_t _Dt = numeric_limits<_UIntType>::digits;
|
||||
@ -3080,7 +2979,7 @@ public:
|
||||
_LIBCPP_FUNC_VIS __rs_default __rs_get();
|
||||
|
||||
template <class _RandomAccessIterator>
|
||||
void
|
||||
_LIBCPP_DEPRECATED_IN_CXX14 void
|
||||
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
|
||||
@ -3101,7 +3000,7 @@ random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
}
|
||||
|
||||
template <class _RandomAccessIterator, class _RandomNumberGenerator>
|
||||
void
|
||||
_LIBCPP_DEPRECATED_IN_CXX14 void
|
||||
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_RandomNumberGenerator&& __rand)
|
||||
@ -3116,7 +3015,8 @@ random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
for (--__last; __first < __last; ++__first, --__d)
|
||||
{
|
||||
difference_type __i = __rand(__d);
|
||||
swap(*__first, *(__first + __i));
|
||||
if (__i != difference_type(0))
|
||||
swap(*__first, *(__first + __i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3328,7 +3228,7 @@ partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __
|
||||
difference_type __len = _VSTD::distance(__first, __last);
|
||||
while (__len != 0)
|
||||
{
|
||||
difference_type __l2 = __len / 2;
|
||||
difference_type __l2 = _VSTD::__half_positive(__len);
|
||||
_ForwardIterator __m = __first;
|
||||
_VSTD::advance(__m, __l2);
|
||||
if (__pred(*__m))
|
||||
@ -3737,6 +3637,7 @@ __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3,
|
||||
// stable, 4-10 compares, 0-9 swaps
|
||||
|
||||
template <class _Compare, class _ForwardIterator>
|
||||
_LIBCPP_HIDDEN
|
||||
unsigned
|
||||
__sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3,
|
||||
_ForwardIterator __x4, _ForwardIterator __x5, _Compare __c)
|
||||
@ -4195,7 +4096,7 @@ __lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __va
|
||||
difference_type __len = _VSTD::distance(__first, __last);
|
||||
while (__len != 0)
|
||||
{
|
||||
difference_type __l2 = __len / 2;
|
||||
difference_type __l2 = _VSTD::__half_positive(__len);
|
||||
_ForwardIterator __m = __first;
|
||||
_VSTD::advance(__m, __l2);
|
||||
if (__comp(*__m, __value_))
|
||||
@ -4214,14 +4115,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
_ForwardIterator
|
||||
lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
|
||||
{
|
||||
#ifdef _LIBCPP_DEBUG
|
||||
typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
|
||||
__debug_less<_Compare> __c(__comp);
|
||||
return __lower_bound<_Comp_ref>(__first, __last, __value_, __c);
|
||||
#else // _LIBCPP_DEBUG
|
||||
typedef typename add_lvalue_reference<_Compare>::type _Comp_ref;
|
||||
return __lower_bound<_Comp_ref>(__first, __last, __value_, __comp);
|
||||
#endif // _LIBCPP_DEBUG
|
||||
}
|
||||
|
||||
template <class _ForwardIterator, class _Tp>
|
||||
@ -4243,7 +4138,7 @@ __upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __va
|
||||
difference_type __len = _VSTD::distance(__first, __last);
|
||||
while (__len != 0)
|
||||
{
|
||||
difference_type __l2 = __len / 2;
|
||||
difference_type __l2 = _VSTD::__half_positive(__len);
|
||||
_ForwardIterator __m = __first;
|
||||
_VSTD::advance(__m, __l2);
|
||||
if (__comp(__value_, *__m))
|
||||
@ -4262,14 +4157,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
_ForwardIterator
|
||||
upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
|
||||
{
|
||||
#ifdef _LIBCPP_DEBUG
|
||||
typedef typename add_lvalue_reference<__debug_less<_Compare> >::type _Comp_ref;
|
||||
__debug_less<_Compare> __c(__comp);
|
||||
return __upper_bound<_Comp_ref>(__first, __last, __value_, __c);
|
||||
#else // _LIBCPP_DEBUG
|
||||
typedef typename add_lvalue_reference<_Compare>::type _Comp_ref;
|
||||
return __upper_bound<_Comp_ref>(__first, __last, __value_, __comp);
|
||||
#endif // _LIBCPP_DEBUG
|
||||
}
|
||||
|
||||
template <class _ForwardIterator, class _Tp>
|
||||
@ -4291,7 +4180,7 @@ __equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __va
|
||||
difference_type __len = _VSTD::distance(__first, __last);
|
||||
while (__len != 0)
|
||||
{
|
||||
difference_type __l2 = __len / 2;
|
||||
difference_type __l2 = _VSTD::__half_positive(__len);
|
||||
_ForwardIterator __m = __first;
|
||||
_VSTD::advance(__m, __l2);
|
||||
if (__comp(*__m, __value_))
|
||||
|
@ -87,13 +87,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;
|
||||
@ -105,12 +106,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
|
||||
_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
|
||||
}
|
||||
|
||||
@ -576,6 +578,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>;
|
||||
@ -590,6 +593,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>;
|
||||
@ -604,6 +608,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>;
|
||||
|
@ -91,7 +91,7 @@ template <class T, size_t N>
|
||||
template <class T, size_t N >
|
||||
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // C++17
|
||||
|
||||
template <class T> class tuple_size;
|
||||
template <class T> struct tuple_size;
|
||||
template <size_t I, class T> class 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>>;
|
||||
@ -112,6 +112,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib> // for _LIBCPP_UNREACHABLE
|
||||
#include <version>
|
||||
#include <__debug>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
@ -367,7 +368,7 @@ array(_Tp, _Args...)
|
||||
|
||||
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.begin(), __x.end(), __y.begin());
|
||||
@ -375,7 +376,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);
|
||||
@ -383,7 +384,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 _VSTD::lexicographical_compare(__x.begin(), __x.end(),
|
||||
@ -392,7 +393,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;
|
||||
@ -400,7 +401,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);
|
||||
@ -408,7 +409,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);
|
||||
@ -429,7 +430,7 @@ 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>
|
||||
|
@ -544,6 +544,7 @@ void atomic_signal_fence(memory_order m) noexcept;
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -559,10 +560,6 @@ void atomic_signal_fence(memory_order m) noexcept;
|
||||
#error C++ standard library is incompatible with <stdatomic.h>
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
# define __cpp_lib_atomic_is_always_lock_free 201603L
|
||||
#endif
|
||||
|
||||
#define _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) \
|
||||
_LIBCPP_DIAGNOSE_WARNING(__m == memory_order_consume || \
|
||||
__m == memory_order_acquire || \
|
||||
|
158
include/bit
Normal file
158
include/bit
Normal file
@ -0,0 +1,158 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------------ bit ----------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_BIT
|
||||
#define _LIBCPP_BIT
|
||||
|
||||
/*
|
||||
bit synopsis
|
||||
|
||||
namespace std {
|
||||
|
||||
} // namespace std
|
||||
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <version>
|
||||
|
||||
#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_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __ctz(unsigned __x) { return __builtin_ctz(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __ctz(unsigned long __x) { return __builtin_ctzl(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __ctz(unsigned long long __x) { return __builtin_ctzll(__x); }
|
||||
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __clz(unsigned __x) { return __builtin_clz(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __clz(unsigned long __x) { return __builtin_clzl(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __clz(unsigned long long __x) { return __builtin_clzll(__x); }
|
||||
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __popcount(unsigned __x) { return __builtin_popcount(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __popcount(unsigned long __x) { return __builtin_popcountl(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __popcount(unsigned long long __x) { return __builtin_popcountll(__x); }
|
||||
|
||||
#else // _LIBCPP_COMPILER_MSVC
|
||||
|
||||
// Precondition: __x != 0
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __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 __ctz(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned long) == sizeof(unsigned), "");
|
||||
return __ctz(static_cast<unsigned>(__x));
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __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 __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 __clz(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
return __clz(static_cast<unsigned>(__x));
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __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 __popcount(unsigned __x) {
|
||||
static_assert(sizeof(unsigned) == 4, "");
|
||||
return __popcnt(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __popcount(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
return __popcnt(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __popcount(unsigned long long __x) {
|
||||
static_assert(sizeof(unsigned long long) == 8, "");
|
||||
return __popcnt64(__x);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_COMPILER_MSVC
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_BIT
|
@ -238,9 +238,9 @@ __bitset<_N_words, _Size>::__init(unsigned long long __v, false_type) _NOEXCEPT
|
||||
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;
|
||||
__t[__i] = static_cast<__storage_type>(__v) & ( 1ULL << __sz ) - 1;
|
||||
else
|
||||
__t[__i] = static_cast<__storage_type>(__v);
|
||||
__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]),
|
||||
@ -254,7 +254,7 @@ __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;
|
||||
__first_[0] &= ( 1ULL << _Size ) - 1;
|
||||
|
||||
_VSTD::fill(__first_ + 1, __first_ + sizeof(__first_)/sizeof(__first_[0]), __storage_type(0));
|
||||
}
|
||||
@ -269,9 +269,9 @@ __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
|
||||
#if __SIZEOF_SIZE_T__ == 8
|
||||
: __first_{__v}
|
||||
#elif __SIZEOF_SIZE_T__ == 4
|
||||
: __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)}
|
||||
: __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
|
||||
@ -991,7 +991,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>
|
||||
|
@ -87,8 +87,16 @@ namespace std {
|
||||
#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);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
|
||||
enum class _LIBCPP_ENUM_VIS chars_format
|
||||
@ -147,9 +155,6 @@ static constexpr uint32_t __pow10_32[] = {
|
||||
UINT32_C(1000000000),
|
||||
};
|
||||
|
||||
_LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer);
|
||||
_LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer);
|
||||
|
||||
template <typename _Tp, typename = void>
|
||||
struct _LIBCPP_HIDDEN __traits_base
|
||||
{
|
||||
@ -607,4 +612,6 @@ from_chars(const char* __first, const char* __last, _Tp& __value, int __base)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_CHARCONV
|
||||
|
1283
include/chrono
1283
include/chrono
File diff suppressed because it is too large
Load Diff
@ -303,6 +303,7 @@ long double truncl(long double x);
|
||||
|
||||
#include <__config>
|
||||
#include <math.h>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
|
@ -245,6 +245,7 @@ template<class T, class charT, class traits>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
|
@ -35,6 +35,7 @@ Types:
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -50,7 +51,7 @@ using ::ptrdiff_t;
|
||||
using ::size_t;
|
||||
|
||||
#if defined(__CLANG_MAX_ALIGN_T_DEFINED) || defined(_GCC_MAX_ALIGN_T) || \
|
||||
defined(__DEFINED_max_align_t)
|
||||
defined(__DEFINED_max_align_t) || defined(__NetBSD__)
|
||||
// Re-use the compiler's <stddef.h> max_align_t where possible.
|
||||
using ::max_align_t;
|
||||
#else
|
||||
@ -66,10 +67,10 @@ enum class byte : unsigned char {};
|
||||
|
||||
constexpr byte operator| (byte __lhs, byte __rhs) noexcept
|
||||
{
|
||||
return static_cast<byte>(
|
||||
static_cast<unsigned char>(
|
||||
static_cast<unsigned int>(__lhs) | static_cast<unsigned int>(__rhs)
|
||||
));
|
||||
return static_cast<byte>(
|
||||
static_cast<unsigned char>(
|
||||
static_cast<unsigned int>(__lhs) | static_cast<unsigned int>(__rhs)
|
||||
));
|
||||
}
|
||||
|
||||
constexpr byte& operator|=(byte& __lhs, byte __rhs) noexcept
|
||||
@ -77,10 +78,10 @@ constexpr byte& operator|=(byte& __lhs, byte __rhs) noexcept
|
||||
|
||||
constexpr byte operator& (byte __lhs, byte __rhs) noexcept
|
||||
{
|
||||
return static_cast<byte>(
|
||||
static_cast<unsigned char>(
|
||||
static_cast<unsigned int>(__lhs) & static_cast<unsigned int>(__rhs)
|
||||
));
|
||||
return static_cast<byte>(
|
||||
static_cast<unsigned char>(
|
||||
static_cast<unsigned int>(__lhs) & static_cast<unsigned int>(__rhs)
|
||||
));
|
||||
}
|
||||
|
||||
constexpr byte& operator&=(byte& __lhs, byte __rhs) noexcept
|
||||
@ -88,13 +89,13 @@ constexpr byte& operator&=(byte& __lhs, byte __rhs) noexcept
|
||||
|
||||
constexpr byte operator^ (byte __lhs, byte __rhs) noexcept
|
||||
{
|
||||
return static_cast<byte>(
|
||||
static_cast<unsigned char>(
|
||||
static_cast<unsigned int>(__lhs) ^ static_cast<unsigned int>(__rhs)
|
||||
));
|
||||
return static_cast<byte>(
|
||||
static_cast<unsigned char>(
|
||||
static_cast<unsigned int>(__lhs) ^ static_cast<unsigned int>(__rhs)
|
||||
));
|
||||
}
|
||||
|
||||
constexpr byte& operator^=(byte& __lhs, byte __rhs) noexcept
|
||||
constexpr byte& operator^=(byte& __lhs, byte __rhs) noexcept
|
||||
{ return __lhs = __lhs ^ __rhs; }
|
||||
|
||||
constexpr byte operator~ (byte __b) noexcept
|
||||
|
@ -151,11 +151,11 @@ using ::mbtowc;
|
||||
using ::wctomb;
|
||||
using ::mbstowcs;
|
||||
using ::wcstombs;
|
||||
#ifdef _LIBCPP_HAS_QUICK_EXIT
|
||||
#if !defined(_LIBCPP_CXX03_LANG) && defined(_LIBCPP_HAS_QUICK_EXIT)
|
||||
using ::at_quick_exit;
|
||||
using ::quick_exit;
|
||||
#endif
|
||||
#ifdef _LIBCPP_HAS_C11_FEATURES
|
||||
#if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_C11_FEATURES)
|
||||
using ::aligned_alloc;
|
||||
#endif
|
||||
|
||||
|
@ -73,7 +73,7 @@ using ::gmtime;
|
||||
using ::localtime;
|
||||
#endif
|
||||
using ::strftime;
|
||||
#if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_C11_FEATURES)
|
||||
#if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_TIMESPEC_GET)
|
||||
using ::timespec_get;
|
||||
#endif
|
||||
|
||||
|
@ -150,6 +150,11 @@ template <class T, class Allocator>
|
||||
void swap(deque<T,Allocator>& x, deque<T,Allocator>& y)
|
||||
noexcept(noexcept(x.swap(y)));
|
||||
|
||||
template <class T, class Allocator, class U>
|
||||
void erase(deque<T, Allocator>& c, const U& value); // C++20
|
||||
template <class T, class Allocator, class Predicate>
|
||||
void erase_if(deque<T, Allocator>& c, Predicate pred); // C++20
|
||||
|
||||
} // std
|
||||
|
||||
*/
|
||||
@ -161,6 +166,7 @@ template <class T, class Allocator>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -986,7 +992,7 @@ public:
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT;
|
||||
#else
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value);
|
||||
#endif
|
||||
protected:
|
||||
@ -1155,7 +1161,7 @@ __deque_base<_Tp, _Allocator>::swap(__deque_base& __c)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value)
|
||||
#endif
|
||||
{
|
||||
@ -2341,7 +2347,7 @@ deque<_Tp, _Allocator>::__add_front_capacity()
|
||||
_Dp(__a, __base::__block_size));
|
||||
__buf.push_back(__hold.get());
|
||||
__hold.release();
|
||||
|
||||
|
||||
for (typename __base::__map_pointer __i = __base::__map_.begin();
|
||||
__i != __base::__map_.end(); ++__i)
|
||||
__buf.push_back(*__i);
|
||||
@ -2603,6 +2609,7 @@ template <class _Tp, class _Allocator>
|
||||
void
|
||||
deque<_Tp, _Allocator>::pop_back()
|
||||
{
|
||||
_LIBCPP_ASSERT(!empty(), "deque::pop_back called for empty deque");
|
||||
allocator_type& __a = __base::__alloc();
|
||||
size_type __p = __base::size() + __base::__start_ - 1;
|
||||
__alloc_traits::destroy(__a, __to_raw_pointer(*(__base::__map_.begin() +
|
||||
@ -2853,7 +2860,7 @@ deque<_Tp, _Allocator>::swap(deque& __c)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
|
||||
__is_nothrow_swappable<allocator_type>::value)
|
||||
#endif
|
||||
{
|
||||
@ -2926,6 +2933,19 @@ swap(deque<_Tp, _Allocator>& __x, deque<_Tp, _Allocator>& __y)
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Tp, class _Allocator, class _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase(deque<_Tp, _Allocator>& __c, const _Up& __v)
|
||||
{ __c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end()); }
|
||||
|
||||
template <class _Tp, class _Allocator, class _Predicate>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase_if(deque<_Tp, _Allocator>& __c, _Predicate __pred)
|
||||
{ __c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end()); }
|
||||
#endif
|
||||
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
@ -81,6 +81,7 @@ template <class E> void rethrow_if_nested(const E& e);
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
#include <version>
|
||||
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME)
|
||||
#include <vcruntime_exception.h>
|
||||
@ -163,7 +164,7 @@ public:
|
||||
};
|
||||
|
||||
template<class _Ep>
|
||||
exception_ptr
|
||||
_LIBCPP_INLINE_VISIBILITY exception_ptr
|
||||
make_exception_ptr(_Ep __e) _NOEXCEPT
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
@ -222,7 +223,7 @@ _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr p);
|
||||
template <class _E> void *__GetExceptionInfo(_E);
|
||||
|
||||
template<class _Ep>
|
||||
exception_ptr
|
||||
_LIBCPP_INLINE_VISIBILITY exception_ptr
|
||||
make_exception_ptr(_Ep __e) _NOEXCEPT
|
||||
{
|
||||
return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e));
|
||||
|
@ -1,11 +1,21 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------------ any -----------------------------------===//
|
||||
//===------------------------------- any ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_ANY
|
||||
#define _LIBCPP_EXPERIMENTAL_ANY
|
||||
|
||||
#error "<experimental/any> has been removed. Use <any> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/any> has been removed. Use <any> instead.")
|
||||
#else
|
||||
# warning "<experimental/any> has been removed. Use <any> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_ANY
|
||||
|
@ -1,11 +1,21 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------------ chrono ---------------------------------===//
|
||||
//===---------------------------- chrono ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_CHRONO
|
||||
#define _LIBCPP_EXPERIMENTAL_CHRONO
|
||||
|
||||
#error "<experimental/chrono> has been removed. Use <chrono> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/chrono> has been removed. Use <chrono> instead.")
|
||||
#else
|
||||
# warning "<experimental/chrono> has been removed. Use <chrono> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_CHRONO
|
||||
|
@ -214,7 +214,7 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_Promise& promise() const {
|
||||
return *static_cast<_Promise*>(
|
||||
__builtin_coro_promise(this->__handle_, __alignof(_Promise), false));
|
||||
__builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false));
|
||||
}
|
||||
|
||||
public:
|
||||
@ -254,7 +254,7 @@ public:
|
||||
coroutine_handle __tmp;
|
||||
__tmp.__handle_ = __builtin_coro_promise(
|
||||
_VSTD::addressof(const_cast<_RawPromise&>(__promise)),
|
||||
__alignof(_Promise), true);
|
||||
_LIBCPP_ALIGNOF(_Promise), true);
|
||||
return __tmp;
|
||||
}
|
||||
};
|
||||
@ -272,7 +272,7 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_Promise& promise() const {
|
||||
return *static_cast<_Promise*>(
|
||||
__builtin_coro_promise(this->__handle_, __alignof(_Promise), false));
|
||||
__builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false));
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return true; }
|
||||
|
@ -1,305 +0,0 @@
|
||||
// -*- C++ -*-
|
||||
//===-------------------------- dynarray ----------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_DYNARRAY
|
||||
#define _LIBCPP_DYNARRAY
|
||||
|
||||
/*
|
||||
dynarray synopsis
|
||||
|
||||
namespace std { namespace experimental {
|
||||
|
||||
template< typename T >
|
||||
class dynarray
|
||||
{
|
||||
// types:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef implementation-defined iterator;
|
||||
typedef implementation-defined const_iterator;
|
||||
typedef reverse_iterator<iterator> reverse_iterator;
|
||||
typedef reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
public:
|
||||
// construct/copy/destroy:
|
||||
explicit dynarray(size_type c);
|
||||
dynarray(size_type c, const T& v);
|
||||
dynarray(const dynarray& d);
|
||||
dynarray(initializer_list<T>);
|
||||
|
||||
template <class Alloc>
|
||||
dynarray(allocator_arg_t, const Alloc& a, size_type c, const Alloc& alloc);
|
||||
template <class Alloc>
|
||||
dynarray(allocator_arg_t, const Alloc& a, size_type c, const T& v, const Alloc& alloc);
|
||||
template <class Alloc>
|
||||
dynarray(allocator_arg_t, const Alloc& a, const dynarray& d, const Alloc& alloc);
|
||||
template <class Alloc>
|
||||
dynarray(allocator_arg_t, const Alloc& a, initializer_list<T>, const Alloc& alloc);
|
||||
dynarray& operator=(const dynarray&) = delete;
|
||||
~dynarray();
|
||||
|
||||
// iterators:
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator cbegin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept;
|
||||
const_reverse_iterator rbegin() const noexcept;
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
reverse_iterator rend() noexcept;
|
||||
const_reverse_iterator rend() const noexcept;
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
// capacity:
|
||||
size_type size() const noexcept;
|
||||
size_type max_size() const noexcept;
|
||||
bool empty() const noexcept;
|
||||
|
||||
// element access:
|
||||
reference operator[](size_type n);
|
||||
const_reference operator[](size_type n) const;
|
||||
|
||||
reference front();
|
||||
const_reference front() const;
|
||||
reference back();
|
||||
const_reference back() const;
|
||||
|
||||
const_reference at(size_type n) const;
|
||||
reference at(size_type n);
|
||||
|
||||
// data access:
|
||||
T* data() noexcept;
|
||||
const T* data() const noexcept;
|
||||
|
||||
// mutating member functions:
|
||||
void fill(const T& v);
|
||||
};
|
||||
|
||||
}} // std::experimental
|
||||
|
||||
*/
|
||||
#include <__config>
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
|
||||
#include <__functional_base>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <initializer_list>
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
namespace std { namespace experimental { inline namespace __array_extensions_v1 {
|
||||
|
||||
template <class _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_DYNARRAY dynarray
|
||||
{
|
||||
public:
|
||||
// types:
|
||||
typedef dynarray __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;
|
||||
|
||||
private:
|
||||
size_t __size_;
|
||||
value_type * __base_;
|
||||
_LIBCPP_INLINE_VISIBILITY dynarray () noexcept : __size_(0), __base_(nullptr) {}
|
||||
|
||||
static inline _LIBCPP_INLINE_VISIBILITY
|
||||
value_type* __allocate(size_t __count) {
|
||||
if (numeric_limits<size_t>::max() / sizeof (value_type) <= __count)
|
||||
__throw_bad_array_length();
|
||||
|
||||
return static_cast<value_type *>(
|
||||
_VSTD::__libcpp_allocate(sizeof(value_type) * __count, __alignof(value_type)));
|
||||
}
|
||||
|
||||
static inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __deallocate_value(value_type* __ptr ) noexcept {
|
||||
_VSTD::__libcpp_deallocate(static_cast<void *>(__ptr), __alignof(value_type));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
explicit dynarray(size_type __c);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
dynarray(size_type __c, const value_type& __v);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
dynarray(const dynarray& __d);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
dynarray(initializer_list<value_type>);
|
||||
|
||||
// We're not implementing these right now.
|
||||
// Updated with the resolution of LWG issue #2255
|
||||
// template <typename _Alloc>
|
||||
// dynarray(allocator_arg_t, const _Alloc& __alloc, size_type __c);
|
||||
// template <typename _Alloc>
|
||||
// dynarray(allocator_arg_t, const _Alloc& __alloc, size_type __c, const value_type& __v);
|
||||
// template <typename _Alloc>
|
||||
// dynarray(allocator_arg_t, const _Alloc& __alloc, const dynarray& __d);
|
||||
// template <typename _Alloc>
|
||||
// dynarray(allocator_arg_t, const _Alloc& __alloc, initializer_list<value_type>);
|
||||
|
||||
dynarray& operator=(const dynarray&) = delete;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
~dynarray();
|
||||
|
||||
// iterators:
|
||||
inline _LIBCPP_INLINE_VISIBILITY iterator begin() noexcept { return iterator(data()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_iterator begin() const noexcept { return const_iterator(data()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const noexcept { return const_iterator(data()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY iterator end() noexcept { return iterator(data() + __size_); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_iterator end() const noexcept { return const_iterator(data() + __size_); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_iterator cend() const noexcept { return const_iterator(data() + __size_); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
|
||||
// capacity:
|
||||
inline _LIBCPP_INLINE_VISIBILITY size_type size() const noexcept { return __size_; }
|
||||
inline _LIBCPP_INLINE_VISIBILITY size_type max_size() const noexcept { return __size_; }
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool empty() const noexcept { return __size_ == 0; }
|
||||
|
||||
// element access:
|
||||
inline _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) { return data()[__n]; }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const { return data()[__n]; }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY reference front() { return data()[0]; }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reference front() const { return data()[0]; }
|
||||
inline _LIBCPP_INLINE_VISIBILITY reference back() { return data()[__size_-1]; }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reference back() const { return data()[__size_-1]; }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY const_reference at(size_type __n) const;
|
||||
inline _LIBCPP_INLINE_VISIBILITY reference at(size_type __n);
|
||||
|
||||
// data access:
|
||||
inline _LIBCPP_INLINE_VISIBILITY _Tp* data() noexcept { return __base_; }
|
||||
inline _LIBCPP_INLINE_VISIBILITY const _Tp* data() const noexcept { return __base_; }
|
||||
|
||||
// mutating member functions:
|
||||
inline _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __v) { fill_n(begin(), __size_, __v); }
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
inline
|
||||
dynarray<_Tp>::dynarray(size_type __c) : dynarray ()
|
||||
{
|
||||
__base_ = __allocate (__c);
|
||||
value_type *__data = data ();
|
||||
for ( __size_ = 0; __size_ < __c; ++__size_, ++__data )
|
||||
::new (__data) value_type;
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline
|
||||
dynarray<_Tp>::dynarray(size_type __c, const value_type& __v) : dynarray ()
|
||||
{
|
||||
__base_ = __allocate (__c);
|
||||
value_type *__data = data ();
|
||||
for ( __size_ = 0; __size_ < __c; ++__size_, ++__data )
|
||||
::new (__data) value_type (__v);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline
|
||||
dynarray<_Tp>::dynarray(initializer_list<value_type> __il) : dynarray ()
|
||||
{
|
||||
size_t sz = __il.size();
|
||||
__base_ = __allocate (sz);
|
||||
value_type *__data = data ();
|
||||
auto src = __il.begin();
|
||||
for ( __size_ = 0; __size_ < sz; ++__size_, ++__data, ++src )
|
||||
::new (__data) value_type (*src);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline
|
||||
dynarray<_Tp>::dynarray(const dynarray& __d) : dynarray ()
|
||||
{
|
||||
size_t sz = __d.size();
|
||||
__base_ = __allocate (sz);
|
||||
value_type *__data = data ();
|
||||
auto src = __d.begin();
|
||||
for ( __size_ = 0; __size_ < sz; ++__size_, ++__data, ++src )
|
||||
::new (__data) value_type (*src);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline
|
||||
dynarray<_Tp>::~dynarray()
|
||||
{
|
||||
value_type *__data = data () + __size_;
|
||||
for ( size_t i = 0; i < __size_; ++i )
|
||||
(--__data)->value_type::~value_type();
|
||||
__deallocate_value( __base_ );
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename dynarray<_Tp>::reference
|
||||
dynarray<_Tp>::at(size_type __n)
|
||||
{
|
||||
if (__n >= __size_)
|
||||
__throw_out_of_range("dynarray::at");
|
||||
|
||||
return data()[__n];
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename dynarray<_Tp>::const_reference
|
||||
dynarray<_Tp>::at(size_type __n) const
|
||||
{
|
||||
if (__n >= __size_)
|
||||
__throw_out_of_range("dynarray::at");
|
||||
|
||||
return data()[__n];
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
template <class _Tp, class _Alloc>
|
||||
struct _LIBCPP_TEMPLATE_VIS uses_allocator<std::experimental::dynarray<_Tp>, _Alloc> : true_type {};
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // if _LIBCPP_STD_VER > 11
|
||||
#endif // _LIBCPP_DYNARRAY
|
@ -98,7 +98,7 @@ size_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT
|
||||
// 8.5, memory.resource
|
||||
class _LIBCPP_TYPE_VIS memory_resource
|
||||
{
|
||||
static const size_t __max_align = alignof(max_align_t);
|
||||
static const size_t __max_align = _LIBCPP_ALIGNOF(max_align_t);
|
||||
|
||||
// 8.5.2, memory.resource.public
|
||||
public:
|
||||
@ -190,7 +190,7 @@ public:
|
||||
" 'n' exceeds maximum supported size");
|
||||
}
|
||||
return static_cast<_ValueType*>(
|
||||
__res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType))
|
||||
__res_->allocate(__n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType))
|
||||
);
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ public:
|
||||
void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT {
|
||||
_LIBCPP_ASSERT(__n <= __max_size(),
|
||||
"deallocate called for size which exceeds max_size()");
|
||||
__res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType));
|
||||
__res_->deallocate(__p, __n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType));
|
||||
}
|
||||
|
||||
template <class _Tp, class ..._Ts>
|
||||
@ -345,7 +345,7 @@ class _LIBCPP_TEMPLATE_VIS __resource_adaptor_imp
|
||||
&& is_same<typename _CTraits::pointer, char*>::value
|
||||
&& is_same<typename _CTraits::void_pointer, void*>::value, "");
|
||||
|
||||
static const size_t _MaxAlign = alignof(max_align_t);
|
||||
static const size_t _MaxAlign = _LIBCPP_ALIGNOF(max_align_t);
|
||||
|
||||
using _Alloc = typename _CTraits::template rebind_alloc<
|
||||
typename aligned_storage<_MaxAlign, _MaxAlign>::type
|
||||
|
@ -7,5 +7,15 @@
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_NUMERIC
|
||||
#define _LIBCPP_EXPERIMENTAL_NUMERIC
|
||||
|
||||
#error "<experimental/numeric> has been removed. Use <numeric> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/numeric> has been removed. Use <numeric> instead.")
|
||||
#else
|
||||
# warning "<experimental/numeric> has been removed. Use <numeric> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_NUMERIC
|
||||
|
@ -7,5 +7,15 @@
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_OPTIONAL
|
||||
#define _LIBCPP_EXPERIMENTAL_OPTIONAL
|
||||
|
||||
#error "<experimental/optional> has been removed. Use <optional> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/optional> has been removed. Use <optional> instead.")
|
||||
#else
|
||||
# warning "<experimental/optional> has been removed. Use <optional> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_OPTIONAL
|
||||
|
@ -1,11 +1,21 @@
|
||||
// -*- C++ -*-
|
||||
//===------------------------------ ratio ---------------------------------===//
|
||||
//===----------------------------- ratio ----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_RATIO
|
||||
#define _LIBCPP_EXPERIMENTAL_RATIO
|
||||
|
||||
#error "<experimental/ratio> has been removed. Use <ratio> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/ratio> has been removed. Use <ratio> instead.")
|
||||
#else
|
||||
# warning "<experimental/ratio> has been removed. Use <ratio> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_RATIO
|
||||
|
@ -3,9 +3,19 @@
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_STRING_VIEW
|
||||
#define _LIBCPP_EXPERIMENTAL_STRING_VIEW
|
||||
|
||||
#error "<experimental/string_view> has been removed. Use <string_view> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/string_view> has been removed. Use <string_view> instead.")
|
||||
#else
|
||||
# warning "<experimental/string_view> has been removed. Use <string_view> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_STRING_VIEW
|
||||
|
@ -7,5 +7,15 @@
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_SYSTEM_ERROR
|
||||
#define _LIBCPP_EXPERIMENTAL_SYSTEM_ERROR
|
||||
|
||||
#error "<experimental/system_error> has been removed. Use <system_error> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/system_error> has been removed. Use <system_error> instead.")
|
||||
#else
|
||||
# warning "<experimental/system_error> has been removed. Use <system_error> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_SYSTEM_ERROR
|
||||
|
@ -7,5 +7,15 @@
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_EXPERIMENTAL_TUPLE
|
||||
#define _LIBCPP_EXPERIMENTAL_TUPLE
|
||||
|
||||
#error "<experimental/tuple> has been removed. Use <tuple> instead."
|
||||
#include <__config>
|
||||
|
||||
#ifdef _LIBCPP_WARNING
|
||||
_LIBCPP_WARNING("<experimental/tuple> has been removed. Use <tuple> instead.")
|
||||
#else
|
||||
# warning "<experimental/tuple> has been removed. Use <tuple> instead."
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPERIMENTAL_TUPLE
|
||||
|
@ -244,6 +244,7 @@
|
||||
#include <utility>
|
||||
#include <iomanip> // for quoted
|
||||
#include <string_view>
|
||||
#include <version>
|
||||
|
||||
#include <__debug>
|
||||
|
||||
@ -256,42 +257,8 @@ _LIBCPP_PUSH_MACROS
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
#define __cpp_lib_filesystem 201703
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
|
||||
|
||||
struct _FilesystemClock {
|
||||
#if !defined(_LIBCPP_HAS_NO_INT128)
|
||||
typedef __int128_t rep;
|
||||
typedef nano period;
|
||||
#else
|
||||
typedef long long rep;
|
||||
typedef nano period;
|
||||
#endif
|
||||
|
||||
typedef chrono::duration<rep, period> duration;
|
||||
typedef chrono::time_point<_FilesystemClock> time_point;
|
||||
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false;
|
||||
|
||||
_LIBCPP_FUNC_VIS static time_point now() noexcept;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static time_t to_time_t(const time_point& __t) noexcept {
|
||||
typedef chrono::duration<rep> __secs;
|
||||
return time_t(
|
||||
chrono::duration_cast<__secs>(__t.time_since_epoch()).count());
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static time_point from_time_t(time_t __t) noexcept {
|
||||
typedef chrono::duration<rep> __secs;
|
||||
return time_point(__secs(__t));
|
||||
}
|
||||
};
|
||||
|
||||
typedef chrono::time_point<_FilesystemClock> file_time_type;
|
||||
|
||||
struct _LIBCPP_TYPE_VIS space_info {
|
||||
@ -590,7 +557,7 @@ template <class _ECharT>
|
||||
typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
|
||||
__is_separator(_ECharT __e) {
|
||||
return __e == _ECharT('/');
|
||||
};
|
||||
}
|
||||
|
||||
struct _NullSentinal {};
|
||||
|
||||
@ -1184,6 +1151,31 @@ public:
|
||||
return __is;
|
||||
}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) == 0;
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) != 0;
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) < 0;
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) <= 0;
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) > 0;
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) >= 0;
|
||||
}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
|
||||
const path& __rhs) {
|
||||
path __result(__lhs);
|
||||
__result /= __rhs;
|
||||
return __result;
|
||||
}
|
||||
private:
|
||||
inline _LIBCPP_INLINE_VISIBILITY path&
|
||||
__assign_view(__string_view const& __s) noexcept {
|
||||
@ -1200,43 +1192,6 @@ inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
|
||||
_LIBCPP_FUNC_VIS
|
||||
size_t hash_value(const path& __p) noexcept;
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs,
|
||||
const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) == 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs,
|
||||
const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) != 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs,
|
||||
const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) < 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs,
|
||||
const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) <= 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs,
|
||||
const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) > 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs,
|
||||
const path& __rhs) noexcept {
|
||||
return __lhs.compare(__rhs) >= 0;
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
|
||||
const path& __rhs) {
|
||||
path __result(__lhs);
|
||||
__result /= __rhs;
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Source>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if<__is_pathable<_Source>::value, path>::type
|
||||
|
@ -167,6 +167,11 @@ template <class T, class Allocator>
|
||||
void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y)
|
||||
noexcept(noexcept(x.swap(y)));
|
||||
|
||||
template <class T, class Allocator, class U>
|
||||
void erase(forward_list<T, Allocator>& c, const U& value); // C++20
|
||||
template <class T, class Allocator, class Predicate>
|
||||
void erase_if(forward_list<T, Allocator>& c, Predicate pred); // C++20
|
||||
|
||||
} // std
|
||||
|
||||
*/
|
||||
@ -177,6 +182,7 @@ template <class T, class Allocator>
|
||||
#include <limits>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -1743,6 +1749,18 @@ swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y)
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Tp, class _Allocator, class _Predicate>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred)
|
||||
{ __c.remove_if(__pred); }
|
||||
|
||||
template <class _Tp, class _Allocator, class _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v)
|
||||
{ _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); }
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
@ -702,6 +702,7 @@ basic_filebuf<_CharT, _Traits>::close()
|
||||
__file_ = 0;
|
||||
else
|
||||
__rt = 0;
|
||||
setbuf(0, 0);
|
||||
}
|
||||
return __rt;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -556,13 +556,14 @@ public:
|
||||
{return (__state_ & __constructed) || (__exception_ != nullptr);}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __set_future_attached()
|
||||
{
|
||||
void __attach_future() {
|
||||
lock_guard<mutex> __lk(__mut_);
|
||||
bool __has_future_attached = (__state_ & __future_attached) != 0;
|
||||
if (__has_future_attached)
|
||||
__throw_future_error(future_errc::future_already_retrieved);
|
||||
this->__add_shared();
|
||||
__state_ |= __future_attached;
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
bool __has_future_attached() const {return (__state_ & __future_attached) != 0;}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __set_deferred() {__state_ |= deferred;}
|
||||
@ -1154,10 +1155,7 @@ template <class _Rp>
|
||||
future<_Rp>::future(__assoc_state<_Rp>* __state)
|
||||
: __state_(__state)
|
||||
{
|
||||
if (__state_->__has_future_attached())
|
||||
__throw_future_error(future_errc::future_already_retrieved);
|
||||
__state_->__add_shared();
|
||||
__state_->__set_future_attached();
|
||||
__state_->__attach_future();
|
||||
}
|
||||
|
||||
struct __release_shared_count
|
||||
@ -1257,10 +1255,7 @@ template <class _Rp>
|
||||
future<_Rp&>::future(__assoc_state<_Rp&>* __state)
|
||||
: __state_(__state)
|
||||
{
|
||||
if (__state_->__has_future_attached())
|
||||
__throw_future_error(future_errc::future_already_retrieved);
|
||||
__state_->__add_shared();
|
||||
__state_->__set_future_attached();
|
||||
__state_->__attach_future();
|
||||
}
|
||||
|
||||
template <class _Rp>
|
||||
|
@ -46,6 +46,7 @@ template <class charT, class traits, class Allocator>
|
||||
#include <__config>
|
||||
#include <__string>
|
||||
#include <istream>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
|
@ -18,6 +18,12 @@ namespace std
|
||||
{
|
||||
|
||||
template<class charT> struct char_traits;
|
||||
template<> struct char_traits<char>;
|
||||
template<> struct char_traits<char8_t>; // C++20
|
||||
template<> struct char_traits<char16_t>;
|
||||
template<> struct char_traits<char32_t>;
|
||||
template<> struct char_traits<wchar_t>;
|
||||
|
||||
template<class T> class allocator;
|
||||
|
||||
class ios_base;
|
||||
@ -98,6 +104,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
class _LIBCPP_TYPE_VIS ios_base;
|
||||
|
||||
template<class _CharT> struct _LIBCPP_TEMPLATE_VIS char_traits;
|
||||
template<> struct char_traits<char>;
|
||||
#ifndef _LIBCPP_NO_HAS_CHAR8_T
|
||||
template<> struct char_traits<char8_t>;
|
||||
#endif
|
||||
template<> struct char_traits<char16_t>;
|
||||
template<> struct char_traits<char32_t>;
|
||||
template<> struct char_traits<wchar_t>;
|
||||
|
||||
template<class _Tp> class _LIBCPP_TEMPLATE_VIS allocator;
|
||||
|
||||
template <class _CharT, class _Traits = char_traits<_CharT> >
|
||||
@ -175,6 +189,9 @@ typedef basic_fstream<wchar_t> wfstream;
|
||||
template <class _State> class _LIBCPP_TEMPLATE_VIS fpos;
|
||||
typedef fpos<mbstate_t> streampos;
|
||||
typedef fpos<mbstate_t> wstreampos;
|
||||
#ifndef _LIBCPP_NO_HAS_CHAR8_T
|
||||
typedef fpos<mbstate_t> u8streampos;
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
typedef fpos<mbstate_t> u16streampos;
|
||||
typedef fpos<mbstate_t> u32streampos;
|
||||
|
@ -160,6 +160,7 @@ template <class charT, class traits, class T>
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <version>
|
||||
#include <ostream>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
@ -186,7 +187,7 @@ public:
|
||||
typedef typename traits_type::off_type off_type;
|
||||
|
||||
// 27.7.1.1.1 Constructor/destructor:
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
explicit basic_istream(basic_streambuf<char_type, traits_type>* __sb) : __gc_(0)
|
||||
{ this->init(__sb); }
|
||||
virtual ~basic_istream();
|
||||
@ -200,7 +201,7 @@ protected:
|
||||
basic_istream& operator=(basic_istream&& __rhs);
|
||||
#endif
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
void swap(basic_istream& __rhs) {
|
||||
_VSTD::swap(__gc_, __rhs.__gc_);
|
||||
basic_ios<char_type, traits_type>::swap(__rhs);
|
||||
@ -216,16 +217,16 @@ public:
|
||||
class _LIBCPP_TEMPLATE_VIS sentry;
|
||||
|
||||
// 27.7.1.2 Formatted input:
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&))
|
||||
{ return __pf(*this); }
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_istream& operator>>(basic_ios<char_type, traits_type>&
|
||||
(*__pf)(basic_ios<char_type, traits_type>&))
|
||||
{ __pf(*this); return *this; }
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_istream& operator>>(ios_base& (*__pf)(ios_base&))
|
||||
{ __pf(*this); return *this; }
|
||||
|
||||
@ -249,7 +250,7 @@ public:
|
||||
streamsize gcount() const {return __gc_;}
|
||||
int_type get();
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_istream& get(char_type& __c) {
|
||||
int_type __ch = get();
|
||||
if (__ch != traits_type::eof())
|
||||
@ -257,19 +258,19 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_istream& get(char_type* __s, streamsize __n)
|
||||
{ return get(__s, __n, this->widen('\n')); }
|
||||
|
||||
basic_istream& get(char_type* __s, streamsize __n, char_type __dlm);
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_istream& get(basic_streambuf<char_type, traits_type>& __sb)
|
||||
{ return get(__sb, this->widen('\n')); }
|
||||
|
||||
basic_istream& get(basic_streambuf<char_type, traits_type>& __sb, char_type __dlm);
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_istream& getline(char_type* __s, streamsize __n)
|
||||
{ return getline(__s, __n, this->widen('\n')); }
|
||||
|
||||
@ -517,8 +518,9 @@ basic_istream<_CharT, _Traits>::operator>>(int& __n)
|
||||
}
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_istream<_CharT, _Traits>&
|
||||
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
||||
__input_c_string(basic_istream<_CharT, _Traits>& __is, _CharT* __p, size_t __n)
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
@ -527,13 +529,10 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
||||
typename basic_istream<_CharT, _Traits>::sentry __sen(__is);
|
||||
if (__sen)
|
||||
{
|
||||
streamsize __n = __is.width();
|
||||
if (__n <= 0)
|
||||
__n = numeric_limits<streamsize>::max() / sizeof(_CharT) - 1;
|
||||
streamsize __c = 0;
|
||||
auto __s = __p;
|
||||
const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc());
|
||||
ios_base::iostate __err = ios_base::goodbit;
|
||||
while (__c < __n-1)
|
||||
while (__s != __p + (__n-1))
|
||||
{
|
||||
typename _Traits::int_type __i = __is.rdbuf()->sgetc();
|
||||
if (_Traits::eq_int_type(__i, _Traits::eof()))
|
||||
@ -545,12 +544,11 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
||||
if (__ct.is(__ct.space, __ch))
|
||||
break;
|
||||
*__s++ = __ch;
|
||||
++__c;
|
||||
__is.rdbuf()->sbumpc();
|
||||
}
|
||||
*__s = _CharT();
|
||||
__is.width(0);
|
||||
if (__c == 0)
|
||||
if (__s == __p)
|
||||
__err |= ios_base::failbit;
|
||||
__is.setstate(__err);
|
||||
}
|
||||
@ -564,6 +562,48 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
||||
return __is;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
template<class _CharT, class _Traits, size_t _Np>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_istream<_CharT, _Traits>&
|
||||
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT (&__buf)[_Np])
|
||||
{
|
||||
auto __n = _Np;
|
||||
if (__is.width() > 0)
|
||||
__n = _VSTD::min(size_t(__is.width()), _Np);
|
||||
return _VSTD::__input_c_string(__is, __buf, __n);
|
||||
}
|
||||
|
||||
template<class _Traits, size_t _Np>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_istream<char, _Traits>&
|
||||
operator>>(basic_istream<char, _Traits>& __is, unsigned char (&__buf)[_Np])
|
||||
{
|
||||
return __is >> (char(&)[_Np])__buf;
|
||||
}
|
||||
|
||||
template<class _Traits, size_t _Np>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_istream<char, _Traits>&
|
||||
operator>>(basic_istream<char, _Traits>& __is, signed char (&__buf)[_Np])
|
||||
{
|
||||
return __is >> (char(&)[_Np])__buf;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_istream<_CharT, _Traits>&
|
||||
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
||||
{
|
||||
streamsize __n = __is.width();
|
||||
if (__n <= 0)
|
||||
__n = numeric_limits<streamsize>::max() / sizeof(_CharT) - 1;
|
||||
return _VSTD::__input_c_string(__is, __s, size_t(__n));
|
||||
}
|
||||
|
||||
template<class _Traits>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_istream<char, _Traits>&
|
||||
@ -580,6 +620,8 @@ operator>>(basic_istream<char, _Traits>& __is, signed char* __s)
|
||||
return __is >> (char*)__s;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 17
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT& __c)
|
||||
@ -1238,7 +1280,7 @@ public:
|
||||
typedef typename traits_type::off_type off_type;
|
||||
|
||||
// constructor/destructor
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
explicit basic_iostream(basic_streambuf<char_type, traits_type>* __sb)
|
||||
: basic_istream<_CharT, _Traits>(__sb)
|
||||
{}
|
||||
@ -1253,7 +1295,7 @@ protected:
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_iostream& operator=(basic_iostream&& __rhs);
|
||||
#endif
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
void swap(basic_iostream& __rhs)
|
||||
{ basic_istream<char_type, traits_type>::swap(__rhs); }
|
||||
public:
|
||||
@ -1463,7 +1505,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, bitset<_Size>& __x)
|
||||
return __is;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_AVAILABILITY_NO_STREAMS_EXTERN_TEMPLATE
|
||||
#ifndef _LIBCPP_DO_NOT_ASSUME_STREAMS_EXPLICIT_INSTANTIATION_IN_DYLIB
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_istream<char>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_istream<wchar_t>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_iostream<char>)
|
||||
|
@ -418,6 +418,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <version>
|
||||
#ifdef __APPLE__
|
||||
#include <Availability.h>
|
||||
#endif
|
||||
@ -436,6 +437,23 @@ struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag : public input_iterator_t
|
||||
struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {};
|
||||
struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {};
|
||||
|
||||
template <class _Tp>
|
||||
struct __has_iterator_typedefs
|
||||
{
|
||||
private:
|
||||
struct __two {char __lx; char __lxx;};
|
||||
template <class _Up> static __two __test(...);
|
||||
template <class _Up> static char __test(typename std::__void_t<typename _Up::iterator_category>::type* = 0,
|
||||
typename std::__void_t<typename _Up::difference_type>::type* = 0,
|
||||
typename std::__void_t<typename _Up::value_type>::type* = 0,
|
||||
typename std::__void_t<typename _Up::reference>::type* = 0,
|
||||
typename std::__void_t<typename _Up::pointer>::type* = 0
|
||||
);
|
||||
public:
|
||||
static const bool value = sizeof(__test<_Tp>(0,0,0,0,0)) == 1;
|
||||
};
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
struct __has_iterator_category
|
||||
{
|
||||
@ -478,7 +496,7 @@ struct __iterator_traits<_Iter, true>
|
||||
|
||||
template <class _Iter>
|
||||
struct _LIBCPP_TEMPLATE_VIS iterator_traits
|
||||
: __iterator_traits<_Iter, __has_iterator_category<_Iter>::value> {};
|
||||
: __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {};
|
||||
|
||||
template<class _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*>
|
||||
|
@ -82,6 +82,7 @@ template<> class numeric_limits<cv char>;
|
||||
template<> class numeric_limits<cv signed char>;
|
||||
template<> class numeric_limits<cv unsigned char>;
|
||||
template<> class numeric_limits<cv wchar_t>;
|
||||
template<> class numeric_limits<cv char8_t>; // C++20
|
||||
template<> class numeric_limits<cv char16_t>;
|
||||
template<> class numeric_limits<cv char32_t>;
|
||||
|
||||
@ -118,6 +119,7 @@ template<> class numeric_limits<cv long double>;
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
#include <version>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
22
include/list
22
include/list
@ -169,6 +169,11 @@ template <class T, class Alloc>
|
||||
void swap(list<T,Alloc>& x, list<T,Alloc>& y)
|
||||
noexcept(noexcept(x.swap(y)));
|
||||
|
||||
template <class T, class Allocator, class U>
|
||||
void erase(list<T, Allocator>& c, const U& value); // C++20
|
||||
template <class T, class Allocator, class Predicate>
|
||||
void erase_if(list<T, Allocator>& c, Predicate pred); // C++20
|
||||
|
||||
} // std
|
||||
|
||||
*/
|
||||
@ -181,6 +186,7 @@ template <class T, class Alloc>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <version>
|
||||
|
||||
#include <__debug>
|
||||
|
||||
@ -1169,7 +1175,7 @@ list<_Tp, _Alloc>::__link_nodes_at_front(__link_pointer __f, __link_pointer __l)
|
||||
base::__end_.__next_ = __f;
|
||||
}
|
||||
|
||||
// Link in nodes [__f, __l] at the front of the list
|
||||
// Link in nodes [__f, __l] at the back of the list
|
||||
template <class _Tp, class _Alloc>
|
||||
inline
|
||||
void
|
||||
@ -2208,7 +2214,7 @@ template <class _Comp>
|
||||
void
|
||||
list<_Tp, _Alloc>::merge(list& __c, _Comp __comp)
|
||||
{
|
||||
if (this != &__c)
|
||||
if (this != _VSTD::addressof(__c))
|
||||
{
|
||||
iterator __f1 = begin();
|
||||
iterator __e1 = end();
|
||||
@ -2449,6 +2455,18 @@ swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Tp, class _Allocator, class _Predicate>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred)
|
||||
{ __c.remove_if(__pred); }
|
||||
|
||||
template <class _Tp, class _Allocator, class _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase(list<_Tp, _Allocator>& __c, const _Up& __v)
|
||||
{ _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); }
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
@ -187,6 +187,7 @@ template <class charT> class messages_byname;
|
||||
#include <streambuf>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <version>
|
||||
#ifndef __APPLE__
|
||||
#include <cstdarg>
|
||||
#endif
|
||||
@ -727,7 +728,7 @@ locale::id
|
||||
num_get<_CharT, _InputIterator>::id;
|
||||
|
||||
template <class _Tp>
|
||||
_Tp
|
||||
_LIBCPP_HIDDEN _Tp
|
||||
__num_get_signed_integral(const char* __a, const char* __a_end,
|
||||
ios_base::iostate& __err, int __base)
|
||||
{
|
||||
@ -762,7 +763,7 @@ __num_get_signed_integral(const char* __a, const char* __a_end,
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_Tp
|
||||
_LIBCPP_HIDDEN _Tp
|
||||
__num_get_unsigned_integral(const char* __a, const char* __a_end,
|
||||
ios_base::iostate& __err, int __base)
|
||||
{
|
||||
@ -2408,6 +2409,23 @@ private:
|
||||
string_type __analyze(char __fmt, const ctype<_CharT>&);
|
||||
};
|
||||
|
||||
#define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \
|
||||
template <> _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
|
||||
template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
|
||||
template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
|
||||
template <> _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
|
||||
template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
|
||||
extern template _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
|
||||
extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
|
||||
extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
|
||||
extern template _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
|
||||
extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
|
||||
/**/
|
||||
|
||||
_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char)
|
||||
_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)
|
||||
#undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION
|
||||
|
||||
template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
|
||||
class _LIBCPP_TEMPLATE_VIS time_get_byname
|
||||
: public time_get<_CharT, _InputIterator>,
|
||||
@ -3550,6 +3568,7 @@ messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
|
||||
__cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
|
||||
return __cat;
|
||||
#else // !_LIBCPP_HAS_CATOPEN
|
||||
_LIBCPP_UNUSED_VAR(__nm);
|
||||
return -1;
|
||||
#endif // _LIBCPP_HAS_CATOPEN
|
||||
}
|
||||
@ -3573,6 +3592,9 @@ messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
|
||||
__n, __n + strlen(__n));
|
||||
return __w;
|
||||
#else // !_LIBCPP_HAS_CATOPEN
|
||||
_LIBCPP_UNUSED_VAR(__c);
|
||||
_LIBCPP_UNUSED_VAR(__set);
|
||||
_LIBCPP_UNUSED_VAR(__msgid);
|
||||
return __dflt;
|
||||
#endif // _LIBCPP_HAS_CATOPEN
|
||||
}
|
||||
@ -3586,6 +3608,8 @@ messages<_CharT>::do_close(catalog __c) const
|
||||
__c <<= 1;
|
||||
nl_catd __cat = (nl_catd)__c;
|
||||
catclose(__cat);
|
||||
#else // !_LIBCPP_HAS_CATOPEN
|
||||
_LIBCPP_UNUSED_VAR(__c);
|
||||
#endif // _LIBCPP_HAS_CATOPEN
|
||||
}
|
||||
|
||||
|
122
include/map
122
include/map
@ -167,6 +167,15 @@ public:
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void clear() noexcept;
|
||||
|
||||
template<class C2>
|
||||
void merge(map<Key, T, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(map<Key, T, C2, Allocator>&& source); // C++17
|
||||
template<class C2>
|
||||
void merge(multimap<Key, T, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(multimap<Key, T, C2, Allocator>&& source); // C++17
|
||||
|
||||
void swap(map& m)
|
||||
noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
|
||||
is_nothrow_swappable<key_compare>::value); // C++17
|
||||
@ -245,6 +254,10 @@ void
|
||||
swap(map<Key, T, Compare, Allocator>& x, map<Key, T, Compare, Allocator>& y)
|
||||
noexcept(noexcept(x.swap(y)));
|
||||
|
||||
template <class Key, class T, class Compare, class Allocator, class Predicate>
|
||||
void erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
|
||||
|
||||
|
||||
template <class Key, class T, class Compare = less<Key>,
|
||||
class Allocator = allocator<pair<const Key, T>>>
|
||||
class multimap
|
||||
@ -368,6 +381,15 @@ public:
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void clear() noexcept;
|
||||
|
||||
template<class C2>
|
||||
void merge(multimap<Key, T, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(multimap<Key, T, C2, Allocator>&& source); // C++17
|
||||
template<class C2>
|
||||
void merge(map<Key, T, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(map<Key, T, C2, Allocator>&& source); // C++17
|
||||
|
||||
void swap(multimap& m)
|
||||
noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
|
||||
is_nothrow_swappable<key_compare>::value); // C++17
|
||||
@ -447,6 +469,9 @@ swap(multimap<Key, T, Compare, Allocator>& x,
|
||||
multimap<Key, T, Compare, Allocator>& y)
|
||||
noexcept(noexcept(x.swap(y)));
|
||||
|
||||
template <class Key, class T, class Compare, class Allocator, class Predicate>
|
||||
void erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
|
||||
|
||||
} // std
|
||||
|
||||
*/
|
||||
@ -460,6 +485,7 @@ swap(multimap<Key, T, Compare, Allocator>& x,
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -467,7 +493,8 @@ swap(multimap<Key, T, Compare, Allocator>& x,
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Key, class _CP, class _Compare, bool _IsSmall>
|
||||
template <class _Key, class _CP, class _Compare,
|
||||
bool = is_empty<_Compare>::value && !__libcpp_is_final<_Compare>::value>
|
||||
class __map_value_compare
|
||||
: private _Compare
|
||||
{
|
||||
@ -881,6 +908,7 @@ public:
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
|
||||
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
|
||||
"Allocator::value_type must be same type as value_type");
|
||||
|
||||
@ -925,6 +953,11 @@ public:
|
||||
typedef __insert_return_type<iterator, node_type> insert_return_type;
|
||||
#endif
|
||||
|
||||
template <class _Key2, class _Value2, class _Comp2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS map;
|
||||
template <class _Key2, class _Value2, class _Comp2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS multimap;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
map()
|
||||
_NOEXCEPT_(
|
||||
@ -1299,6 +1332,38 @@ public:
|
||||
{
|
||||
return __tree_.template __node_handle_extract<node_type>(__it.__i_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(map<key_type, mapped_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(map<key_type, mapped_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -1556,6 +1621,14 @@ swap(map<_Key, _Tp, _Compare, _Allocator>& __x,
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred)
|
||||
{ __libcpp_erase_if_container(__c, __pred); }
|
||||
#endif
|
||||
|
||||
|
||||
template <class _Key, class _Tp, class _Compare = less<_Key>,
|
||||
class _Allocator = allocator<pair<const _Key, _Tp> > >
|
||||
class _LIBCPP_TEMPLATE_VIS multimap
|
||||
@ -1570,6 +1643,7 @@ public:
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
|
||||
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
|
||||
"Allocator::value_type must be same type as value_type");
|
||||
|
||||
@ -1614,6 +1688,11 @@ public:
|
||||
typedef __map_node_handle<typename __base::__node, allocator_type> node_type;
|
||||
#endif
|
||||
|
||||
template <class _Key2, class _Value2, class _Comp2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS map;
|
||||
template <class _Key2, class _Value2, class _Comp2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS multimap;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
multimap()
|
||||
_NOEXCEPT_(
|
||||
@ -1881,10 +1960,42 @@ public:
|
||||
return __tree_.template __node_handle_extract<node_type>(
|
||||
__it.__i_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
return __tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
return __tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(map<key_type, mapped_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
return __tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(map<key_type, mapped_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
return __tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void clear() {__tree_.clear();}
|
||||
void clear() _NOEXCEPT {__tree_.clear();}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void swap(multimap& __m)
|
||||
@ -2055,6 +2166,13 @@ swap(multimap<_Key, _Tp, _Compare, _Allocator>& __x,
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred)
|
||||
{ __libcpp_erase_if_container(__c, __pred); }
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_MAP
|
||||
|
139
include/memory
139
include/memory
@ -43,7 +43,7 @@ struct pointer_traits<T*>
|
||||
|
||||
template <class U> using rebind = U*;
|
||||
|
||||
static pointer pointer_to(<details>) noexcept;
|
||||
static pointer pointer_to(<details>) noexcept; // constexpr in C++20
|
||||
};
|
||||
|
||||
template <class T> constexpr T* to_address(T* p) noexcept; // C++20
|
||||
@ -212,10 +212,10 @@ template <class ForwardIterator>
|
||||
template <class ForwardIterator, class Size>
|
||||
ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
|
||||
|
||||
template <class Y> struct auto_ptr_ref {}; // removed in C++17
|
||||
template <class Y> struct auto_ptr_ref {}; // deprecated in C++11, removed in C++17
|
||||
|
||||
template<class X>
|
||||
class auto_ptr // removed in C++17
|
||||
class auto_ptr // deprecated in C++11, removed in C++17
|
||||
{
|
||||
public:
|
||||
typedef X element_type;
|
||||
@ -667,6 +667,7 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
|
||||
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
|
||||
# include <atomic>
|
||||
#endif
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -983,7 +984,7 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*>
|
||||
private:
|
||||
struct __nat {};
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
static pointer pointer_to(typename conditional<is_void<element_type>::value,
|
||||
__nat, element_type>::type& __r) _NOEXCEPT
|
||||
{return _VSTD::addressof(__r);}
|
||||
@ -1459,29 +1460,21 @@ struct __has_select_on_container_copy_construction
|
||||
|
||||
#else // _LIBCPP_CXX03_LANG
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||
template <class _Alloc, class _Pointer, class _Tp, class = void>
|
||||
struct __has_construct : std::false_type {};
|
||||
|
||||
template <class _Alloc, class _Pointer, class ..._Args>
|
||||
struct __has_construct
|
||||
: false_type
|
||||
{
|
||||
};
|
||||
template <class _Alloc, class _Pointer, class _Tp>
|
||||
struct __has_construct<_Alloc, _Pointer, _Tp, typename __void_t<
|
||||
decltype(_VSTD::declval<_Alloc>().construct(_VSTD::declval<_Pointer>(), _VSTD::declval<_Tp>()))
|
||||
>::type> : std::true_type {};
|
||||
|
||||
#else // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class _Alloc, class _Pointer, class _Args>
|
||||
struct __has_construct
|
||||
: false_type
|
||||
{
|
||||
};
|
||||
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
template <class _Alloc, class _Pointer, class = void>
|
||||
struct __has_destroy : false_type {};
|
||||
|
||||
template <class _Alloc, class _Pointer>
|
||||
struct __has_destroy
|
||||
: false_type
|
||||
{
|
||||
};
|
||||
struct __has_destroy<_Alloc, _Pointer, typename __void_t<
|
||||
decltype(_VSTD::declval<_Alloc>().destroy(_VSTD::declval<_Pointer>()))
|
||||
>::type> : std::true_type {};
|
||||
|
||||
template <class _Alloc>
|
||||
struct __has_max_size
|
||||
@ -1509,6 +1502,12 @@ struct __alloc_traits_difference_type<_Alloc, _Ptr, true>
|
||||
typedef typename _Alloc::difference_type type;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct __is_default_allocator : false_type {};
|
||||
|
||||
template <class _Tp>
|
||||
struct __is_default_allocator<_VSTD::allocator<_Tp> > : true_type {};
|
||||
|
||||
template <class _Alloc>
|
||||
struct _LIBCPP_TEMPLATE_VIS allocator_traits
|
||||
{
|
||||
@ -1570,9 +1569,10 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
|
||||
}
|
||||
template <class _Tp, class _A0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static void construct(allocator_type&, _Tp* __p, const _A0& __a0)
|
||||
static void construct(allocator_type& __a, _Tp* __p, const _A0& __a0)
|
||||
{
|
||||
::new ((void*)__p) _Tp(__a0);
|
||||
__construct(__has_construct<allocator_type, _Tp*, const _A0&>(),
|
||||
__a, __p, __a0);
|
||||
}
|
||||
template <class _Tp, class _A0, class _A1>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -1612,7 +1612,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
|
||||
void
|
||||
__construct_forward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2)
|
||||
{
|
||||
for (; __begin1 != __end1; ++__begin1, ++__begin2)
|
||||
for (; __begin1 != __end1; ++__begin1, (void) ++__begin2)
|
||||
construct(__a, _VSTD::__to_raw_pointer(__begin2), _VSTD::move_if_noexcept(*__begin1));
|
||||
}
|
||||
|
||||
@ -1621,7 +1621,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
|
||||
static
|
||||
typename enable_if
|
||||
<
|
||||
(is_same<allocator_type, allocator<_Tp> >::value
|
||||
(__is_default_allocator<allocator_type>::value
|
||||
|| !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
|
||||
is_trivially_move_constructible<_Tp>::value,
|
||||
void
|
||||
@ -1646,23 +1646,25 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
|
||||
construct(__a, _VSTD::__to_raw_pointer(__begin2), *__begin1);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
template <class _SourceTp, class _DestTp,
|
||||
class _RawSourceTp = typename remove_const<_SourceTp>::type,
|
||||
class _RawDestTp = typename remove_const<_DestTp>::type>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static
|
||||
typename enable_if
|
||||
<
|
||||
(is_same<allocator_type, allocator<_Tp> >::value
|
||||
|| !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
|
||||
is_trivially_move_constructible<_Tp>::value,
|
||||
is_trivially_move_constructible<_DestTp>::value &&
|
||||
is_same<_RawSourceTp, _RawDestTp>::value &&
|
||||
(__is_default_allocator<allocator_type>::value ||
|
||||
!__has_construct<allocator_type, _DestTp*, _SourceTp&>::value),
|
||||
void
|
||||
>::type
|
||||
__construct_range_forward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2)
|
||||
__construct_range_forward(allocator_type&, _SourceTp* __begin1, _SourceTp* __end1, _DestTp*& __begin2)
|
||||
{
|
||||
typedef typename remove_const<_Tp>::type _Vp;
|
||||
ptrdiff_t _Np = __end1 - __begin1;
|
||||
if (_Np > 0)
|
||||
{
|
||||
_VSTD::memcpy(const_cast<_Vp*>(__begin2), __begin1, _Np * sizeof(_Tp));
|
||||
_VSTD::memcpy(const_cast<_RawDestTp*>(__begin2), __begin1, _Np * sizeof(_DestTp));
|
||||
__begin2 += _Np;
|
||||
}
|
||||
}
|
||||
@ -1685,7 +1687,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
|
||||
static
|
||||
typename enable_if
|
||||
<
|
||||
(is_same<allocator_type, allocator<_Tp> >::value
|
||||
(__is_default_allocator<allocator_type>::value
|
||||
|| !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
|
||||
is_trivially_move_constructible<_Tp>::value,
|
||||
void
|
||||
@ -1720,6 +1722,19 @@ private:
|
||||
{
|
||||
::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...);
|
||||
}
|
||||
#else // _LIBCPP_HAS_NO_VARIADICS
|
||||
template <class _Tp, class _A0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static void __construct(true_type, allocator_type& __a, _Tp* __p,
|
||||
const _A0& __a0)
|
||||
{__a.construct(__p, __a0);}
|
||||
template <class _Tp, class _A0>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
static void __construct(false_type, allocator_type&, _Tp* __p,
|
||||
const _A0& __a0)
|
||||
{
|
||||
::new ((void*)__p) _Tp(__a0);
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class _Tp>
|
||||
@ -1782,7 +1797,7 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
allocator() _NOEXCEPT {}
|
||||
|
||||
template <class _Up>
|
||||
template <class _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
allocator(const allocator<_Up>&) _NOEXCEPT {}
|
||||
|
||||
@ -1790,16 +1805,16 @@ public:
|
||||
{return _VSTD::addressof(__x);}
|
||||
_LIBCPP_INLINE_VISIBILITY const_pointer address(const_reference __x) const _NOEXCEPT
|
||||
{return _VSTD::addressof(__x);}
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
||||
pointer allocate(size_type __n, allocator<void>::const_pointer = 0)
|
||||
{
|
||||
if (__n > max_size())
|
||||
__throw_length_error("allocator<T>::allocate(size_t n)"
|
||||
" 'n' exceeds maximum supported size");
|
||||
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp)));
|
||||
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type) _NOEXCEPT
|
||||
{_VSTD::__libcpp_deallocate((void*)__p, __alignof(_Tp));}
|
||||
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) _NOEXCEPT
|
||||
{_VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));}
|
||||
_LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT
|
||||
{return size_type(~0) / sizeof(_Tp);}
|
||||
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
|
||||
@ -1887,7 +1902,7 @@ public:
|
||||
allocator() _NOEXCEPT {}
|
||||
|
||||
template <class _Up>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
|
||||
allocator(const allocator<_Up>&) _NOEXCEPT {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY const_pointer address(const_reference __x) const _NOEXCEPT
|
||||
@ -1897,10 +1912,10 @@ public:
|
||||
if (__n > max_size())
|
||||
__throw_length_error("allocator<const T>::allocate(size_t n)"
|
||||
" 'n' exceeds maximum supported size");
|
||||
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp)));
|
||||
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type) _NOEXCEPT
|
||||
{_VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __alignof(_Tp));}
|
||||
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) _NOEXCEPT
|
||||
{_VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));}
|
||||
_LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT
|
||||
{return size_type(~0) / sizeof(_Tp);}
|
||||
#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
|
||||
@ -1989,10 +2004,10 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY explicit raw_storage_iterator(_OutputIterator __x) : __x_(__x) {}
|
||||
_LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator*() {return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(const _Tp& __element)
|
||||
{::new(&*__x_) _Tp(__element); return *this;}
|
||||
{::new(_VSTD::addressof(*__x_)) _Tp(__element); return *this;}
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(_Tp&& __element)
|
||||
{::new(&*__x_) _Tp(_VSTD::move(__element)); return *this;}
|
||||
{::new(_VSTD::addressof(*__x_)) _Tp(_VSTD::move(__element)); return *this;}
|
||||
#endif
|
||||
_LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator++() {++__x_; return *this;}
|
||||
_LIBCPP_INLINE_VISIBILITY raw_storage_iterator operator++(int)
|
||||
@ -2003,7 +2018,7 @@ public:
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_NO_CFI
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_NO_CFI
|
||||
pair<_Tp*, ptrdiff_t>
|
||||
get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT
|
||||
{
|
||||
@ -2016,7 +2031,7 @@ get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT
|
||||
while (__n > 0)
|
||||
{
|
||||
#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
|
||||
if (__is_overaligned_for_new(__alignof(_Tp)))
|
||||
if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp)))
|
||||
{
|
||||
std::align_val_t __al =
|
||||
std::align_val_t(std::alignment_of<_Tp>::value);
|
||||
@ -2027,7 +2042,7 @@ get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT
|
||||
__n * sizeof(_Tp), nothrow));
|
||||
}
|
||||
#else
|
||||
if (__is_overaligned_for_new(__alignof(_Tp)))
|
||||
if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp)))
|
||||
{
|
||||
// Since aligned operator new is unavailable, return an empty
|
||||
// buffer rather than one with invalid alignment.
|
||||
@ -2051,18 +2066,18 @@ template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void return_temporary_buffer(_Tp* __p) _NOEXCEPT
|
||||
{
|
||||
_VSTD::__libcpp_deallocate((void*)__p, __alignof(_Tp));
|
||||
_VSTD::__libcpp_deallocate_unsized((void*)__p, _LIBCPP_ALIGNOF(_Tp));
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
|
||||
template <class _Tp>
|
||||
struct auto_ptr_ref
|
||||
struct _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr_ref
|
||||
{
|
||||
_Tp* __ptr_;
|
||||
};
|
||||
|
||||
template<class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS auto_ptr
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr
|
||||
{
|
||||
private:
|
||||
_Tp* __ptr_;
|
||||
@ -2106,7 +2121,7 @@ public:
|
||||
};
|
||||
|
||||
template <>
|
||||
class _LIBCPP_TEMPLATE_VIS auto_ptr<void>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr<void>
|
||||
{
|
||||
public:
|
||||
typedef void element_type;
|
||||
@ -2130,7 +2145,9 @@ struct __compressed_pair_elem {
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
constexpr explicit
|
||||
__compressed_pair_elem(_Up&& __u)
|
||||
: __value_(_VSTD::forward<_Up>(__u)){};
|
||||
: __value_(_VSTD::forward<_Up>(__u))
|
||||
{
|
||||
}
|
||||
|
||||
template <class... _Args, size_t... _Indexes>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
@ -2167,7 +2184,8 @@ struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp {
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
constexpr explicit
|
||||
__compressed_pair_elem(_Up&& __u)
|
||||
: __value_type(_VSTD::forward<_Up>(__u)){};
|
||||
: __value_type(_VSTD::forward<_Up>(__u))
|
||||
{}
|
||||
|
||||
template <class... _Args, size_t... _Indexes>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
@ -3682,7 +3700,7 @@ private:
|
||||
virtual void __on_zero_shared_weak() _NOEXCEPT;
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_Tp* get() _NOEXCEPT {return &__data_.second();}
|
||||
_Tp* get() _NOEXCEPT {return _VSTD::addressof(__data_.second());}
|
||||
};
|
||||
|
||||
template <class _Tp, class _Alloc>
|
||||
@ -5624,15 +5642,18 @@ template <class _Tp, class _Alloc>
|
||||
struct __temp_value {
|
||||
typedef allocator_traits<_Alloc> _Traits;
|
||||
|
||||
typename aligned_storage<sizeof(_Tp), alignof(_Tp)>::type __v;
|
||||
typename aligned_storage<sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)>::type __v;
|
||||
_Alloc &__a;
|
||||
|
||||
_Tp *__addr() { return reinterpret_cast<_Tp *>(addressof(__v)); }
|
||||
_Tp & get() { return *__addr(); }
|
||||
|
||||
template<class... _Args>
|
||||
__temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc)
|
||||
{ _Traits::construct(__a, __addr(), _VSTD::forward<_Args>(__args)...); }
|
||||
_LIBCPP_NO_CFI
|
||||
__temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) {
|
||||
_Traits::construct(__a, reinterpret_cast<_Tp*>(addressof(__v)),
|
||||
_VSTD::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
~__temp_value() { _Traits::destroy(__a, __addr()); }
|
||||
};
|
||||
|
@ -228,6 +228,10 @@ module std [system] {
|
||||
header "atomic"
|
||||
export *
|
||||
}
|
||||
module bit {
|
||||
header "bit"
|
||||
export *
|
||||
}
|
||||
module bitset {
|
||||
header "bitset"
|
||||
export string
|
||||
@ -520,10 +524,6 @@ module std [system] {
|
||||
header "experimental/deque"
|
||||
export *
|
||||
}
|
||||
module dynarray {
|
||||
header "experimental/dynarray"
|
||||
export *
|
||||
}
|
||||
module filesystem {
|
||||
header "experimental/filesystem"
|
||||
export *
|
||||
|
@ -194,6 +194,7 @@ template<class Callable, class ...Args>
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
#include <tuple>
|
||||
#endif
|
||||
#include <version>
|
||||
#include <__threading_support>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
@ -488,7 +489,7 @@ public:
|
||||
};
|
||||
|
||||
template <class _Mutex>
|
||||
class _LIBCPP_TEMPLATE_VIS scoped_lock<_Mutex> {
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
|
||||
public:
|
||||
typedef _Mutex mutex_type;
|
||||
private:
|
||||
|
175
include/new
175
include/new
@ -27,12 +27,6 @@ public:
|
||||
virtual const char* what() const noexcept;
|
||||
};
|
||||
|
||||
class bad_array_length : public bad_alloc // FIXME: Not part of C++
|
||||
{
|
||||
public:
|
||||
bad_array_length() noexcept;
|
||||
};
|
||||
|
||||
class bad_array_new_length : public bad_alloc // C++14
|
||||
{
|
||||
public:
|
||||
@ -91,6 +85,7 @@ void operator delete[](void* ptr, void*) noexcept;
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
#include <version>
|
||||
#ifdef _LIBCPP_NO_EXCEPTIONS
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
@ -103,23 +98,23 @@ void operator delete[](void* ptr, void*) noexcept;
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if !(defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_STD_VER >= 14 || \
|
||||
(defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309))
|
||||
#if !defined(__cpp_sized_deallocation) || __cpp_sized_deallocation < 201309L
|
||||
#define _LIBCPP_HAS_NO_LANGUAGE_SIZED_DEALLOCATION
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_BUILDING_LIBRARY) && _LIBCPP_STD_VER < 14 && \
|
||||
defined(_LIBCPP_HAS_NO_LANGUAGE_SIZED_DEALLOCATION)
|
||||
# define _LIBCPP_HAS_NO_LIBRARY_SIZED_DEALLOCATION
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_HAS_NO_LIBRARY_SIZED_DEALLOCATION) || \
|
||||
defined(_LIBCPP_HAS_NO_LANGUAGE_SIZED_DEALLOCATION)
|
||||
# define _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) && \
|
||||
(!(defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_STD_VER > 14 || \
|
||||
(defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606)))
|
||||
# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
#endif
|
||||
|
||||
|
||||
#if !__has_builtin(__builtin_operator_new) || \
|
||||
__has_builtin(__builtin_operator_new) < 201802L || \
|
||||
defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) || \
|
||||
!defined(__cpp_aligned_new) || __cpp_aligned_new < 201606
|
||||
#define _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE
|
||||
__has_builtin(__builtin_operator_new) < 201802L
|
||||
#define _LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE
|
||||
#endif
|
||||
|
||||
namespace std // purposefully not using versioning namespace
|
||||
@ -155,29 +150,14 @@ _LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT;
|
||||
|
||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_bad_alloc(); // not in C++ spec
|
||||
|
||||
#if defined(_LIBCPP_BUILDING_LIBRARY) || (_LIBCPP_STD_VER > 11)
|
||||
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
bad_array_length : public bad_alloc {
|
||||
public:
|
||||
bad_array_length() _NOEXCEPT;
|
||||
virtual ~bad_array_length() _NOEXCEPT;
|
||||
virtual const char* what() const _NOEXCEPT;
|
||||
};
|
||||
|
||||
#define _LIBCPP_BAD_ARRAY_LENGTH_DEFINED
|
||||
|
||||
#endif // defined(_LIBCPP_BUILDING_LIBRARY) || (_LIBCPP_STD_VER > 11)
|
||||
|
||||
#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME)
|
||||
#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) || _LIBCPP_STD_VER > 14
|
||||
#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) && \
|
||||
!defined(_LIBCPP_DEFER_NEW_TO_VCRUNTIME)
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
enum class _LIBCPP_ENUM_VIS align_val_t : size_t { };
|
||||
#else
|
||||
enum align_val_t { __zero = 0, __max = (size_t)-1 };
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // std
|
||||
|
||||
@ -187,13 +167,13 @@ enum align_val_t { __zero = 0, __max = (size_t)-1 };
|
||||
#define _THROW_BAD_ALLOC
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME)
|
||||
#if !defined(_LIBCPP_DEFER_NEW_TO_VCRUNTIME)
|
||||
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz) _THROW_BAD_ALLOC;
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
#ifndef _LIBCPP_HAS_NO_LIBRARY_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
@ -201,16 +181,16 @@ _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
#ifndef _LIBCPP_HAS_NO_LIBRARY_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete[](void* __p, std::size_t __sz) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
#ifndef _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::align_val_t) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
#ifndef _LIBCPP_HAS_NO_LIBRARY_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete(void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
@ -218,7 +198,7 @@ _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::align_val_t) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
#ifndef _LIBCPP_HAS_NO_LIBRARY_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete[](void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||
#endif
|
||||
#endif
|
||||
@ -228,7 +208,7 @@ _LIBCPP_NODISCARD_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void* operator ne
|
||||
inline _LIBCPP_INLINE_VISIBILITY void operator delete (void*, void*) _NOEXCEPT {}
|
||||
inline _LIBCPP_INLINE_VISIBILITY void operator delete[](void*, void*) _NOEXCEPT {}
|
||||
|
||||
#endif // !_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME
|
||||
#endif // !_LIBCPP_DEFER_NEW_TO_VCRUNTIME
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
@ -244,7 +224,7 @@ inline _LIBCPP_INLINE_VISIBILITY void *__libcpp_allocate(size_t __size, size_t _
|
||||
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
if (__is_overaligned_for_new(__align)) {
|
||||
const align_val_t __align_val = static_cast<align_val_t>(__align);
|
||||
# ifdef _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE
|
||||
# ifdef _LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE
|
||||
return ::operator new(__size, __align_val);
|
||||
# else
|
||||
return __builtin_operator_new(__size, __align_val);
|
||||
@ -260,43 +240,98 @@ inline _LIBCPP_INLINE_VISIBILITY void *__libcpp_allocate(size_t __size, size_t _
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __align) {
|
||||
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
if (__is_overaligned_for_new(__align)) {
|
||||
const align_val_t __align_val = static_cast<align_val_t>(__align);
|
||||
# ifdef _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE
|
||||
return ::operator delete(__ptr, __align_val);
|
||||
# else
|
||||
return __builtin_operator_delete(__ptr, __align_val);
|
||||
# endif
|
||||
struct _DeallocateCaller {
|
||||
static inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __do_deallocate_handle_size_align(void *__ptr, size_t __size, size_t __align) {
|
||||
#if defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
|
||||
((void)__align);
|
||||
return __do_deallocate_handle_size(__ptr, __size);
|
||||
#else
|
||||
if (__is_overaligned_for_new(__align)) {
|
||||
const align_val_t __align_val = static_cast<align_val_t>(__align);
|
||||
return __do_deallocate_handle_size(__ptr, __size, __align_val);
|
||||
} else {
|
||||
return __do_deallocate_handle_size(__ptr, __size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __do_deallocate_handle_align(void *__ptr, size_t __align) {
|
||||
#if defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
|
||||
((void)__align);
|
||||
return __do_call(__ptr);
|
||||
#else
|
||||
((void)__align);
|
||||
if (__is_overaligned_for_new(__align)) {
|
||||
const align_val_t __align_val = static_cast<align_val_t>(__align);
|
||||
return __do_call(__ptr, __align_val);
|
||||
} else {
|
||||
return __do_call(__ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
static inline void __do_deallocate_handle_size(void *__ptr, size_t __size) {
|
||||
#ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
((void)__size);
|
||||
return __do_call(__ptr);
|
||||
#else
|
||||
return __do_call(__ptr, __size);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
static inline void __do_deallocate_handle_size(void *__ptr, size_t __size, align_val_t __align) {
|
||||
#ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
((void)__size);
|
||||
return __do_call(__ptr, __align);
|
||||
#else
|
||||
return __do_call(__ptr, __size, __align);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
template <class _A1, class _A2>
|
||||
static inline void __do_call(void *__ptr, _A1 __a1, _A2 __a2) {
|
||||
#if defined(_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE) || \
|
||||
defined(_LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE)
|
||||
return ::operator delete(__ptr, __a1, __a2);
|
||||
#else
|
||||
return __builtin_operator_delete(__ptr, __a1, __a2);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
static inline void __do_call(void *__ptr, _A1 __a1) {
|
||||
#if defined(_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE) || \
|
||||
defined(_LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE)
|
||||
return ::operator delete(__ptr, __a1);
|
||||
#else
|
||||
return __builtin_operator_delete(__ptr, __a1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void __do_call(void *__ptr) {
|
||||
#ifdef _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE
|
||||
return ::operator delete(__ptr);
|
||||
return ::operator delete(__ptr);
|
||||
#else
|
||||
return __builtin_operator_delete(__ptr);
|
||||
return __builtin_operator_delete(__ptr);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __size, size_t __align) {
|
||||
_DeallocateCaller::__do_deallocate_handle_size_align(__ptr, __size, __align);
|
||||
}
|
||||
|
||||
#ifdef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED
|
||||
_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
_LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
#endif
|
||||
void __throw_bad_array_length()
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw bad_array_length();
|
||||
#else
|
||||
_VSTD::abort();
|
||||
#endif
|
||||
inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate_unsized(void* __ptr, size_t __align) {
|
||||
_DeallocateCaller::__do_deallocate_handle_align(__ptr, __align);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 inline
|
||||
_LIBCPP_NODISCARD_AFTER_CXX17 inline
|
||||
_LIBCPP_CONSTEXPR _Tp* __launder(_Tp* __p) _NOEXCEPT
|
||||
{
|
||||
static_assert (!(is_function<_Tp>::value), "can't launder functions" );
|
||||
|
@ -104,15 +104,15 @@ template<class InputIterator, class OutputIterator, class T,
|
||||
|
||||
template<class InputIterator, class OutputIterator,
|
||||
class BinaryOperation, class UnaryOperation>
|
||||
OutputIterator
|
||||
transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator
|
||||
transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result,
|
||||
BinaryOperation binary_op, UnaryOperation unary_op); // C++17
|
||||
|
||||
template<class InputIterator, class OutputIterator,
|
||||
class BinaryOperation, class UnaryOperation, class T>
|
||||
OutputIterator
|
||||
transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator
|
||||
transform_inclusive_scan(InputIterator first, InputIterator last,
|
||||
OutputIterator result,
|
||||
BinaryOperation binary_op, UnaryOperation unary_op,
|
||||
T init); // C++17
|
||||
@ -142,6 +142,7 @@ template <class M, class N>
|
||||
#include <iterator>
|
||||
#include <limits> // for numeric_limits
|
||||
#include <functional>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
|
@ -105,8 +105,8 @@ namespace std {
|
||||
|
||||
// 23.6.3.3, assignment
|
||||
optional &operator=(nullopt_t) noexcept;
|
||||
optional &operator=(const optional &);
|
||||
optional &operator=(optional &&) noexcept(see below );
|
||||
optional &operator=(const optional &); // constexpr in C++20
|
||||
optional &operator=(optional &&) noexcept(see below); // constexpr in C++20
|
||||
template <class U = T> optional &operator=(U &&);
|
||||
template <class U> optional &operator=(const optional<U> &);
|
||||
template <class U> optional &operator=(optional<U> &&);
|
||||
@ -156,6 +156,7 @@ template<class T>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -168,7 +169,7 @@ _LIBCPP_PUSH_MACROS
|
||||
namespace std // purposefully not using versioning namespace
|
||||
{
|
||||
|
||||
class _LIBCPP_EXCEPTION_ABI bad_optional_access
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
|
||||
: public exception
|
||||
{
|
||||
public:
|
||||
@ -185,6 +186,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
|
||||
void __throw_bad_optional_access() {
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw bad_optional_access();
|
||||
@ -932,6 +934,7 @@ public:
|
||||
using __base::__get;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
|
||||
constexpr value_type const& value() const&
|
||||
{
|
||||
if (!this->has_value())
|
||||
@ -940,6 +943,7 @@ public:
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
|
||||
constexpr value_type& value() &
|
||||
{
|
||||
if (!this->has_value())
|
||||
@ -948,6 +952,7 @@ public:
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
|
||||
constexpr value_type&& value() &&
|
||||
{
|
||||
if (!this->has_value())
|
||||
@ -956,6 +961,7 @@ public:
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
|
||||
constexpr value_type const&& value() const&&
|
||||
{
|
||||
if (!this->has_value())
|
||||
|
@ -140,6 +140,7 @@ template <class charT, class traits, class T>
|
||||
#include <locale>
|
||||
#include <iterator>
|
||||
#include <bitset>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -160,7 +161,7 @@ public:
|
||||
typedef typename traits_type::off_type off_type;
|
||||
|
||||
// 27.7.2.2 Constructor/destructor:
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
explicit basic_ostream(basic_streambuf<char_type, traits_type>* __sb)
|
||||
{ this->init(__sb); }
|
||||
virtual ~basic_ostream();
|
||||
@ -173,7 +174,7 @@ protected:
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_ostream& operator=(basic_ostream&& __rhs);
|
||||
#endif
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
void swap(basic_ostream& __rhs)
|
||||
{ basic_ios<char_type, traits_type>::swap(__rhs); }
|
||||
|
||||
@ -190,16 +191,16 @@ public:
|
||||
class _LIBCPP_TEMPLATE_VIS sentry;
|
||||
|
||||
// 27.7.2.6 Formatted output:
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_ostream& operator<<(basic_ostream& (*__pf)(basic_ostream&))
|
||||
{ return __pf(*this); }
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_ostream& operator<<(basic_ios<char_type, traits_type>&
|
||||
(*__pf)(basic_ios<char_type,traits_type>&))
|
||||
{ __pf(*this); return *this; }
|
||||
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_ostream& operator<<(ios_base& (*__pf)(ios_base&))
|
||||
{ __pf(*this); return *this; }
|
||||
|
||||
@ -224,11 +225,11 @@ public:
|
||||
basic_ostream& flush();
|
||||
|
||||
// 27.7.2.5 seeks:
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
pos_type tellp();
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_ostream& seekp(pos_type __pos);
|
||||
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
|
||||
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
|
||||
basic_ostream& seekp(off_type __off, ios_base::seekdir __dir);
|
||||
|
||||
protected:
|
||||
@ -1092,7 +1093,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x)
|
||||
use_facet<ctype<_CharT> >(__os.getloc()).widen('1'));
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_AVAILABILITY_NO_STREAMS_EXTERN_TEMPLATE
|
||||
#ifndef _LIBCPP_DO_NOT_ASSUME_STREAMS_EXPLICIT_INSTANTIATION_IN_DYLIB
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<char>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<wchar_t>)
|
||||
#endif
|
||||
|
@ -2337,7 +2337,7 @@ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b,
|
||||
for (size_t __i = 1; __i < __n; ++__i)
|
||||
if (__x_[__i] != 0)
|
||||
return;
|
||||
__x_[0] = _Max;
|
||||
__x_[0] = result_type(1) << (__w - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2363,7 +2363,7 @@ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b,
|
||||
for (size_t __i = 1; __i < __n; ++__i)
|
||||
if (__x_[__i] != 0)
|
||||
return;
|
||||
__x_[0] = _Max;
|
||||
__x_[0] = result_type(1) << (__w - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,6 +769,7 @@ typedef regex_token_iterator<wstring::const_iterator> wsregex_token_iterator;
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -989,6 +990,10 @@ public:
|
||||
|
||||
#if defined(__mips__) && defined(__GLIBC__)
|
||||
static const char_class_type __regex_word = static_cast<char_class_type>(_ISbit(15));
|
||||
#elif defined(__NetBSD__)
|
||||
// NetBSD defines classes up to 0x2000
|
||||
// see sys/ctype_bits.h, _CTYPE_Q
|
||||
static const char_class_type __regex_word = 0x8000;
|
||||
#else
|
||||
static const char_class_type __regex_word = 0x80;
|
||||
#endif
|
||||
@ -1351,9 +1356,9 @@ public:
|
||||
virtual ~__node() {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
virtual void __exec(__state&) const {};
|
||||
virtual void __exec(__state&) const {}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
virtual void __exec_split(bool, __state&) const {};
|
||||
virtual void __exec_split(bool, __state&) const {}
|
||||
};
|
||||
|
||||
// __end_state
|
||||
@ -2414,20 +2419,17 @@ __bracket_expression<_CharT, _Traits>::__exec(__state& __s) const
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
// set of "__found" chars =
|
||||
// When there's at least one of __neg_chars_ and __neg_mask_, the set
|
||||
// of "__found" chars is
|
||||
// union(complement(union(__neg_chars_, __neg_mask_)),
|
||||
// other cases...)
|
||||
//
|
||||
// __neg_chars_ and __neg_mask_'d better be handled together, as there
|
||||
// are no short circuit opportunities.
|
||||
//
|
||||
// In addition, when __neg_mask_/__neg_chars_ is empty, they should be
|
||||
// treated as all ones/all chars.
|
||||
// It doesn't make sense to check this when there are no __neg_chars_
|
||||
// and no __neg_mask_.
|
||||
if (!(__neg_mask_ == 0 && __neg_chars_.empty()))
|
||||
{
|
||||
const bool __in_neg_mask = (__neg_mask_ == 0) ||
|
||||
__traits_.isctype(__ch, __neg_mask_);
|
||||
const bool __in_neg_mask = __traits_.isctype(__ch, __neg_mask_);
|
||||
const bool __in_neg_chars =
|
||||
__neg_chars_.empty() ||
|
||||
std::find(__neg_chars_.begin(), __neg_chars_.end(), __ch) !=
|
||||
__neg_chars_.end();
|
||||
if (!(__in_neg_mask || __in_neg_chars))
|
||||
|
@ -108,6 +108,7 @@ template <class OuterA1, class OuterA2, class... InnerAllocs>
|
||||
|
||||
#include <__config>
|
||||
#include <memory>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
|
126
include/set
126
include/set
@ -128,6 +128,15 @@ public:
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void clear() noexcept;
|
||||
|
||||
template<class C2>
|
||||
void merge(set<Key, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(set<Key, C2, Allocator>&& source); // C++17
|
||||
template<class C2>
|
||||
void merge(multiset<Key, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(multiset<Key, C2, Allocator>&& source); // C++17
|
||||
|
||||
void swap(set& s)
|
||||
noexcept(
|
||||
__is_nothrow_swappable<key_compare>::value &&
|
||||
@ -207,6 +216,9 @@ void
|
||||
swap(set<Key, Compare, Allocator>& x, set<Key, Compare, Allocator>& y)
|
||||
noexcept(noexcept(x.swap(y)));
|
||||
|
||||
template <class Key, class Compare, class Allocator, class Predicate>
|
||||
void erase_if(set<Key, Compare, Allocator>& c, Predicate pred); // C++20
|
||||
|
||||
template <class Key, class Compare = less<Key>,
|
||||
class Allocator = allocator<Key>>
|
||||
class multiset
|
||||
@ -316,6 +328,15 @@ public:
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void clear() noexcept;
|
||||
|
||||
template<class C2>
|
||||
void merge(multiset<Key, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(multiset<Key, C2, Allocator>&& source); // C++17
|
||||
template<class C2>
|
||||
void merge(set<Key, C2, Allocator>& source); // C++17
|
||||
template<class C2>
|
||||
void merge(set<Key, C2, Allocator>&& source); // C++17
|
||||
|
||||
void swap(multiset& s)
|
||||
noexcept(
|
||||
__is_nothrow_swappable<key_compare>::value &&
|
||||
@ -394,6 +415,9 @@ void
|
||||
swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y)
|
||||
noexcept(noexcept(x.swap(y)));
|
||||
|
||||
template <class Key, class Compare, class Allocator, class Predicate>
|
||||
void erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20
|
||||
|
||||
} // std
|
||||
|
||||
*/
|
||||
@ -402,6 +426,7 @@ swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y)
|
||||
#include <__tree>
|
||||
#include <__node_handle>
|
||||
#include <functional>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
@ -409,6 +434,9 @@ swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y)
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Key, class _Compare, class _Allocator>
|
||||
class multiset;
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>,
|
||||
class _Allocator = allocator<_Key> >
|
||||
class _LIBCPP_TEMPLATE_VIS set
|
||||
@ -423,6 +451,7 @@ public:
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
|
||||
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
|
||||
"Allocator::value_type must be same type as value_type");
|
||||
|
||||
@ -448,6 +477,11 @@ public:
|
||||
typedef __insert_return_type<iterator, node_type> insert_return_type;
|
||||
#endif
|
||||
|
||||
template <class _Key2, class _Compare2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS set;
|
||||
template <class _Key2, class _Compare2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS multiset;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
set()
|
||||
_NOEXCEPT_(
|
||||
@ -486,7 +520,7 @@ public:
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
template <class _InputIterator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
set(_InputIterator __f, _InputIterator __l, const allocator_type& __a)
|
||||
: set(__f, __l, key_compare(), __a) {}
|
||||
#endif
|
||||
@ -542,7 +576,7 @@ public:
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
set(initializer_list<value_type> __il, const allocator_type& __a)
|
||||
: set(__il, key_compare(), __a) {}
|
||||
#endif
|
||||
@ -680,6 +714,38 @@ public:
|
||||
{
|
||||
return __tree_.template __node_handle_extract<node_type>(__it);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(set<key_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(set<key_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multiset<key_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multiset<key_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_unique(__source.__tree_);
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -852,6 +918,13 @@ swap(set<_Key, _Compare, _Allocator>& __x,
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Key, class _Compare, class _Allocator, class _Predicate>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred)
|
||||
{ __libcpp_erase_if_container(__c, __pred); }
|
||||
#endif
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>,
|
||||
class _Allocator = allocator<_Key> >
|
||||
class _LIBCPP_TEMPLATE_VIS multiset
|
||||
@ -866,6 +939,7 @@ public:
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
|
||||
static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
|
||||
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
|
||||
"Allocator::value_type must be same type as value_type");
|
||||
|
||||
@ -890,6 +964,11 @@ public:
|
||||
typedef __set_node_handle<typename __base::__node, allocator_type> node_type;
|
||||
#endif
|
||||
|
||||
template <class _Key2, class _Compare2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS set;
|
||||
template <class _Key2, class _Compare2, class _Alloc2>
|
||||
friend class _LIBCPP_TEMPLATE_VIS multiset;
|
||||
|
||||
// construct/copy/destroy:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
multiset()
|
||||
@ -920,7 +999,7 @@ public:
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
template <class _InputIterator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
multiset(_InputIterator __f, _InputIterator __l, const allocator_type& __a)
|
||||
: multiset(__f, __l, key_compare(), __a) {}
|
||||
#endif
|
||||
@ -984,7 +1063,7 @@ public:
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
multiset(initializer_list<value_type> __il, const allocator_type& __a)
|
||||
: multiset(__il, key_compare(), __a) {}
|
||||
#endif
|
||||
@ -1121,6 +1200,38 @@ public:
|
||||
{
|
||||
return __tree_.template __node_handle_extract<node_type>(__it);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multiset<key_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(multiset<key_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(set<key_type, _Compare2, allocator_type>& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
template <class _Compare2>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void merge(set<key_type, _Compare2, allocator_type>&& __source)
|
||||
{
|
||||
_LIBCPP_ASSERT(__source.get_allocator() == get_allocator(),
|
||||
"merging container with incompatible allocator");
|
||||
__tree_.__node_handle_merge_multi(__source.__tree_);
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -1294,6 +1405,13 @@ swap(multiset<_Key, _Compare, _Allocator>& __x,
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Key, class _Compare, class _Allocator, class _Predicate>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred)
|
||||
{ __libcpp_erase_if_container(__c, __pred); }
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_SET
|
||||
|
@ -124,6 +124,7 @@ template <class Mutex>
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <version>
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
@ -143,7 +144,8 @@ _LIBCPP_PUSH_MACROS
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX __shared_mutex_base
|
||||
struct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("shared_mutex"))
|
||||
__shared_mutex_base
|
||||
{
|
||||
mutex __mut_;
|
||||
condition_variable __gate1_;
|
||||
@ -160,14 +162,14 @@ struct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX __shared_mutex_base
|
||||
__shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
|
||||
|
||||
// Exclusive ownership
|
||||
void lock(); // blocking
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking
|
||||
bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
|
||||
void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
|
||||
|
||||
// Shared ownership
|
||||
void lock_shared(); // blocking
|
||||
bool try_lock_shared();
|
||||
void unlock_shared();
|
||||
void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking
|
||||
bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true));
|
||||
void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_shared_capability());
|
||||
|
||||
// typedef implementation-defined native_handle_type; // See 30.2.3
|
||||
// native_handle_type native_handle(); // See 30.2.3
|
||||
|
96
include/span
96
include/span
@ -23,27 +23,13 @@ inline constexpr ptrdiff_t dynamic_extent = -1;
|
||||
template <class ElementType, ptrdiff_t Extent = dynamic_extent>
|
||||
class span;
|
||||
|
||||
// [span.comparison], span comparison operators
|
||||
template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
|
||||
constexpr bool operator==(span<T, X> l, span<U, Y> r);
|
||||
template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
|
||||
constexpr bool operator!=(span<T, X> l, span<U, Y> r);
|
||||
template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
|
||||
constexpr bool operator<(span<T, X> l, span<U, Y> r);
|
||||
template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
|
||||
constexpr bool operator<=(span<T, X> l, span<U, Y> r);
|
||||
template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
|
||||
constexpr bool operator>(span<T, X> l, span<U, Y> r);
|
||||
template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
|
||||
constexpr bool operator>=(span<T, X> l, span<U, Y> r);
|
||||
|
||||
// [span.objectrep], views of object representation
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
|
||||
span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
|
||||
(static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
|
||||
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
span< byte, ((Extent == dynamic_extent) ? dynamic_extent :
|
||||
span< byte, ((Extent == dynamic_extent) ? dynamic_extent :
|
||||
(static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
|
||||
|
||||
|
||||
@ -123,7 +109,7 @@ private:
|
||||
|
||||
template<class T, size_t N>
|
||||
span(T (&)[N]) -> span<T, N>;
|
||||
|
||||
|
||||
template<class T, size_t N>
|
||||
span(array<T, N>&) -> span<T, N>;
|
||||
|
||||
@ -194,8 +180,8 @@ struct __is_span_compatible_container<_Tp, _ElementType,
|
||||
decltype(size(declval<_Tp>())),
|
||||
// remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
|
||||
typename enable_if<
|
||||
is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
|
||||
_ElementType(*)[]>,
|
||||
is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
|
||||
_ElementType(*)[]>,
|
||||
nullptr_t>::type
|
||||
>>
|
||||
: public true_type {};
|
||||
@ -221,7 +207,7 @@ public:
|
||||
static constexpr index_type extent = _Extent;
|
||||
static_assert (_Extent >= 0, "Can't have a span with an extent < 0");
|
||||
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}
|
||||
{ static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); }
|
||||
|
||||
@ -242,7 +228,7 @@ public:
|
||||
constexpr span( _Container& __c,
|
||||
enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
|
||||
: __data{_VSTD::data(__c)}
|
||||
{ _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (container))"); }
|
||||
{ _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (container)"); }
|
||||
|
||||
template <class _Container>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -287,7 +273,7 @@ public:
|
||||
static_assert(_Count <= _Extent, "Count out of range in span::last()");
|
||||
return {data() + size() - _Count, _Count};
|
||||
}
|
||||
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept
|
||||
{
|
||||
@ -315,7 +301,7 @@ public:
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr span<element_type, dynamic_extent>
|
||||
subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
|
||||
{
|
||||
{
|
||||
_LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)");
|
||||
_LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)");
|
||||
if (__count == dynamic_extent)
|
||||
@ -331,14 +317,14 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
|
||||
{
|
||||
_LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>[] index out of bounds");
|
||||
return __data[__idx];
|
||||
}
|
||||
return __data[__idx];
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept
|
||||
{
|
||||
_LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>() index out of bounds");
|
||||
return __data[__idx];
|
||||
}
|
||||
return __data[__idx];
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
|
||||
|
||||
@ -358,7 +344,7 @@ public:
|
||||
__data = __other.__data;
|
||||
__other.__data = __p;
|
||||
}
|
||||
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
|
||||
{ return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
|
||||
|
||||
@ -392,7 +378,7 @@ public:
|
||||
|
||||
static constexpr index_type extent = dynamic_extent;
|
||||
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {}
|
||||
|
||||
constexpr span (const span&) noexcept = default;
|
||||
@ -408,7 +394,7 @@ public:
|
||||
template <size_t _Sz>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr span(array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
|
||||
|
||||
|
||||
template <size_t _Sz>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
|
||||
@ -440,7 +426,7 @@ public:
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr span<element_type, _Count> first() const noexcept
|
||||
{
|
||||
static_assert(_Count >= 0);
|
||||
static_assert(_Count >= 0, "Count must be >= 0 in span::first()");
|
||||
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
|
||||
return {data(), _Count};
|
||||
}
|
||||
@ -449,7 +435,7 @@ public:
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr span<element_type, _Count> last() const noexcept
|
||||
{
|
||||
static_assert(_Count >= 0);
|
||||
static_assert(_Count >= 0, "Count must be >= 0 in span::last()");
|
||||
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
|
||||
return {data() + size() - _Count, _Count};
|
||||
}
|
||||
@ -460,7 +446,7 @@ public:
|
||||
_LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)");
|
||||
return {data(), __count};
|
||||
}
|
||||
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
constexpr span<element_type, dynamic_extent> last (index_type __count) const noexcept
|
||||
{
|
||||
@ -480,7 +466,7 @@ public:
|
||||
constexpr span<element_type, dynamic_extent>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
|
||||
{
|
||||
{
|
||||
_LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)");
|
||||
_LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "count out of range in span::subspan(offset, count)");
|
||||
if (__count == dynamic_extent)
|
||||
@ -496,14 +482,14 @@ public:
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
|
||||
{
|
||||
_LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>[] index out of bounds");
|
||||
return __data[__idx];
|
||||
}
|
||||
return __data[__idx];
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept
|
||||
{
|
||||
_LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>() index out of bounds");
|
||||
return __data[__idx];
|
||||
}
|
||||
return __data[__idx];
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
|
||||
|
||||
@ -539,39 +525,9 @@ private:
|
||||
index_type __size;
|
||||
};
|
||||
|
||||
template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
|
||||
constexpr bool
|
||||
operator==(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
|
||||
{ return equal(__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); }
|
||||
|
||||
template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
|
||||
constexpr bool
|
||||
operator!=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
|
||||
{ return !(__rhs == __lhs); }
|
||||
|
||||
template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
|
||||
constexpr bool
|
||||
operator< (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
|
||||
{ return lexicographical_compare (__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); }
|
||||
|
||||
template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
|
||||
constexpr bool
|
||||
operator<=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
|
||||
{ return !(__rhs < __lhs); }
|
||||
|
||||
template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
|
||||
constexpr bool
|
||||
operator> (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
|
||||
{ return __rhs < __lhs; }
|
||||
|
||||
template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
|
||||
constexpr bool
|
||||
operator>=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
|
||||
{ return !(__lhs < __rhs); }
|
||||
|
||||
// as_bytes & as_writeable_bytes
|
||||
template <class _Tp, ptrdiff_t _Extent>
|
||||
auto as_bytes(span<_Tp, _Extent> __s) noexcept
|
||||
auto as_bytes(span<_Tp, _Extent> __s) noexcept
|
||||
-> decltype(__s.__as_bytes())
|
||||
{ return __s.__as_bytes(); }
|
||||
|
||||
@ -588,7 +544,7 @@ template <class _Tp, ptrdiff_t _Extent>
|
||||
// Deduction guides
|
||||
template<class _Tp, size_t _Sz>
|
||||
span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
|
||||
|
||||
|
||||
template<class _Tp, size_t _Sz>
|
||||
span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
|
||||
|
||||
|
@ -473,12 +473,12 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::str(const string_type& __s)
|
||||
{
|
||||
while (__sz > INT_MAX)
|
||||
{
|
||||
this->pbump(INT_MAX);
|
||||
__sz -= INT_MAX;
|
||||
this->pbump(INT_MAX);
|
||||
__sz -= INT_MAX;
|
||||
}
|
||||
if (__sz > 0)
|
||||
this->pbump(__sz);
|
||||
}
|
||||
this->pbump(__sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ using std::nullptr_t;
|
||||
|
||||
// Re-use the compiler's <stddef.h> max_align_t where possible.
|
||||
#if !defined(__CLANG_MAX_ALIGN_T_DEFINED) && !defined(_GCC_MAX_ALIGN_T) && \
|
||||
!defined(__DEFINED_max_align_t)
|
||||
!defined(__DEFINED_max_align_t) && !defined(__NetBSD__)
|
||||
typedef long double max_align_t;
|
||||
#endif
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user