diff options
author | 2019-06-17 22:18:29 +0000 | |
---|---|---|
committer | 2019-06-17 22:18:29 +0000 | |
commit | 504b10ec5101b237e4c07e1f2de4b6c48138181e (patch) | |
tree | 979c9ce8ab11efd05e4413305758dc5d6bc76ab4 /lib | |
parent | A bit more KNF no binary change (diff) | |
download | wireguard-openbsd-504b10ec5101b237e4c07e1f2de4b6c48138181e.tar.xz wireguard-openbsd-504b10ec5101b237e4c07e1f2de4b6c48138181e.zip |
Import libc++ 8.0.0.
Diffstat (limited to 'lib')
194 files changed, 10590 insertions, 2657 deletions
diff --git a/lib/libcxx/CMakeLists.txt b/lib/libcxx/CMakeLists.txt index acb49565ce9..3a6c3c9df4d 100644 --- a/lib/libcxx/CMakeLists.txt +++ b/lib/libcxx/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.0) + set(PACKAGE_VERSION 8.0.0) 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,12 +121,8 @@ 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.") @@ -277,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 #=============================================================================== @@ -503,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() @@ -545,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 @@ -622,44 +651,63 @@ endif() # Sanitizer flags ============================================================= -# 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") +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 (LLVM_USE_SANITIZER AND NOT MSVC) - add_flags_if_supported("-fno-omit-frame-pointer") - add_flags_if_supported("-gline-tables-only") + 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") - add_flags_if_supported("-gline-tables-only") + NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO") + append_flags_if_supported(SANITIZER_FLAGS "-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") + 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 (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) + 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: ${LLVM_USE_SANITIZER}") + message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${USE_SANITIZER}") endif() - elseif(LLVM_USE_SANITIZER AND MSVC) + 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") +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) @@ -726,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) diff --git a/lib/libcxx/LICENSE.TXT b/lib/libcxx/LICENSE.TXT index c278f2c9283..190d9394d51 100644 --- a/lib/libcxx/LICENSE.TXT +++ b/lib/libcxx/LICENSE.TXT @@ -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. diff --git a/lib/libcxx/benchmarks/CMakeLists.txt b/lib/libcxx/benchmarks/CMakeLists.txt index f557d4aea39..3823b87b39e 100644 --- a/lib/libcxx/benchmarks/CMakeLists.txt +++ b/lib/libcxx/benchmarks/CMakeLists.txt @@ -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() diff --git a/lib/libcxx/benchmarks/CartesianBenchmarks.hpp b/lib/libcxx/benchmarks/CartesianBenchmarks.hpp new file mode 100644 index 00000000000..88a994c5551 --- /dev/null +++ b/lib/libcxx/benchmarks/CartesianBenchmarks.hpp @@ -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; +} + diff --git a/lib/libcxx/benchmarks/algorithms.bench.cpp b/lib/libcxx/benchmarks/algorithms.bench.cpp index 86315390e0d..eee8a4da2ab 100644 --- a/lib/libcxx/benchmarks/algorithms.bench.cpp +++ b/lib/libcxx/benchmarks/algorithms.bench.cpp @@ -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" + +namespace { + +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()); + } +} + +void fillValues(std::vector<std::string>& V, size_t N, Order O) { + + if (O == Order::SingleElement) { + V.resize(N, getRandomString(1024)); + } else { + while (V.size() < N) + V.push_back(getRandomString(1024)); + } +} + +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; + } +} + +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; -constexpr std::size_t TestNumInputs = 1024; - -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(); + 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 }; +} + +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(); +} + +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]; + + 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, random_uint32, - getRandomIntegerInputs<uint32_t>)->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()); + }); + } + + 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; -BENCHMARK_CAPTURE(BM_Sort, sorted_ascending_uint32, - getSortedIntegerInputs<uint32_t>)->Arg(TestNumInputs); + void run(benchmark::State& state) const { + runOpOnCopies<ValueType>(state, Quantity, Order(), false, [](auto& Copy) { + std::make_heap(Copy.begin(), Copy.end()); + }); + } -BENCHMARK_CAPTURE(BM_Sort, sorted_descending_uint32, - getReverseSortedIntegerInputs<uint32_t>)->Arg(TestNumInputs); + std::string name() const { + return "BM_MakeHeap" + ValueType::name() + Order::name() + "_" + + std::to_string(Quantity); + }; +}; -BENCHMARK_CAPTURE(BM_Sort, single_element_uint32, - getDuplicateIntegerInputs<uint32_t>)->Arg(TestNumInputs); +template <class ValueType> +struct SortHeap { + size_t Quantity; -BENCHMARK_CAPTURE(BM_Sort, pipe_organ_uint32, - getPipeOrganIntegerInputs<uint32_t>)->Arg(TestNumInputs); + void run(benchmark::State& state) const { + runOpOnCopies<ValueType>( + state, Quantity, Order::Heap, false, + [](auto& Copy) { std::sort_heap(Copy.begin(), Copy.end()); }); + } -BENCHMARK_CAPTURE(BM_Sort, random_strings, - getRandomStringInputs)->Arg(TestNumInputs); + std::string name() const { + return "BM_SortHeap" + ValueType::name() + "_" + std::to_string(Quantity); + }; +}; -BENCHMARK_CAPTURE(BM_Sort, sorted_ascending_strings, - getSortedStringInputs)->Arg(TestNumInputs); +template <class ValueType, class Order> +struct MakeThenSortHeap { + size_t Quantity; -BENCHMARK_CAPTURE(BM_Sort, sorted_descending_strings, - getReverseSortedStringInputs)->Arg(TestNumInputs); + 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()); + }); + } -BENCHMARK_CAPTURE(BM_Sort, single_element_strings, - getDuplicateStringInputs)->Arg(TestNumInputs); + 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; -BENCHMARK_MAIN(); + 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(); +} diff --git a/lib/libcxx/benchmarks/algorithms.partition_point.bench.cpp b/lib/libcxx/benchmarks/algorithms.partition_point.bench.cpp new file mode 100644 index 00000000000..00a3bb27267 --- /dev/null +++ b/lib/libcxx/benchmarks/algorithms.partition_point.bench.cpp @@ -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(); +} diff --git a/lib/libcxx/benchmarks/function.bench.cpp b/lib/libcxx/benchmarks/function.bench.cpp new file mode 100644 index 00000000000..4f0e1fd80fa --- /dev/null +++ b/lib/libcxx/benchmarks/function.bench.cpp @@ -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(); +} diff --git a/lib/libcxx/benchmarks/lit.cfg.py b/lib/libcxx/benchmarks/lit.cfg.py new file mode 100644 index 00000000000..84857d570d7 --- /dev/null +++ b/lib/libcxx/benchmarks/lit.cfg.py @@ -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)
\ No newline at end of file diff --git a/lib/libcxx/benchmarks/lit.site.cfg.py.in b/lib/libcxx/benchmarks/lit.site.cfg.py.in new file mode 100644 index 00000000000..e3ce8b22263 --- /dev/null +++ b/lib/libcxx/benchmarks/lit.site.cfg.py.in @@ -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")
\ No newline at end of file diff --git a/lib/libcxx/benchmarks/ordered_set.bench.cpp b/lib/libcxx/benchmarks/ordered_set.bench.cpp new file mode 100644 index 00000000000..b2ef0725b7b --- /dev/null +++ b/lib/libcxx/benchmarks/ordered_set.bench.cpp @@ -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(); +} diff --git a/lib/libcxx/benchmarks/string.bench.cpp b/lib/libcxx/benchmarks/string.bench.cpp index 8a09e738d9b..b8f97e6e2c1 100644 --- a/lib/libcxx/benchmarks/string.bench.cpp +++ b/lib/libcxx/benchmarks/string.bench.cpp @@ -1,9 +1,12 @@ -#include <unordered_set> -#include <vector> + #include <cstdint> +#include <new> +#include <vector> -#include "benchmark/benchmark.h" +#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-"; + } +} + +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); } } -BENCHMARK(BM_StringCtorCStr)->Arg(1)->Arg(8)->Range(16, MAX_STRING_LEN / 4); -BENCHMARK_MAIN(); +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(); +} diff --git a/lib/libcxx/benchmarks/stringstream.bench.cpp b/lib/libcxx/benchmarks/stringstream.bench.cpp index 75a7a284e07..828ef4b405f 100644 --- a/lib/libcxx/benchmarks/stringstream.bench.cpp +++ b/lib/libcxx/benchmarks/stringstream.bench.cpp @@ -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[] = { diff --git a/lib/libcxx/benchmarks/unordered_set_operations.bench.cpp b/lib/libcxx/benchmarks/unordered_set_operations.bench.cpp index ee0ea29b8d2..1fee6d362c4 100644 --- a/lib/libcxx/benchmarks/unordered_set_operations.bench.cpp +++ b/lib/libcxx/benchmarks/unordered_set_operations.bench.cpp @@ -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)); } diff --git a/lib/libcxx/cmake/Modules/HandleCompilerRT.cmake b/lib/libcxx/cmake/Modules/HandleCompilerRT.cmake index 2e0e69e5e08..1ce25657494 100644 --- a/lib/libcxx/cmake/Modules/HandleCompilerRT.cmake +++ b/lib/libcxx/cmake/Modules/HandleCompilerRT.cmake @@ -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 diff --git a/lib/libcxx/cmake/Modules/HandleLibcxxFlags.cmake b/lib/libcxx/cmake/Modules/HandleLibcxxFlags.cmake index 65f7d187f3b..fb60318a330 100644 --- a/lib/libcxx/cmake/Modules/HandleLibcxxFlags.cmake +++ b/lib/libcxx/cmake/Modules/HandleLibcxxFlags.cmake @@ -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}) diff --git a/lib/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake b/lib/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake index 70eed1d70ba..11c13315585 100644 --- a/lib/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake +++ b/lib/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake @@ -116,7 +116,7 @@ macro(configure_out_of_tree_llvm) # Required LIT Configuration ------------------------------------------------ # Define the default arguments to use with 'lit', and an option for the user # to override. - set(LLVM_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") + set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported") if (MSVC OR XCODE) set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") diff --git a/lib/libcxx/docs/BuildingLibcxx.rst b/lib/libcxx/docs/BuildingLibcxx.rst index daf9229a0d0..a498c0027bd 100644 --- a/lib/libcxx/docs/BuildingLibcxx.rst +++ b/lib/libcxx/docs/BuildingLibcxx.rst @@ -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**:: ``""`` @@ -360,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**: ``""`` diff --git a/lib/libcxx/docs/DesignDocs/AvailabilityMarkup.rst b/lib/libcxx/docs/DesignDocs/AvailabilityMarkup.rst index b8b44509790..4e6d80b50bf 100644 --- a/lib/libcxx/docs/DesignDocs/AvailabilityMarkup.rst +++ b/lib/libcxx/docs/DesignDocs/AvailabilityMarkup.rst @@ -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). diff --git a/lib/libcxx/docs/DesignDocs/CapturingConfigInfo.rst b/lib/libcxx/docs/DesignDocs/CapturingConfigInfo.rst index 88102251d93..29156bff8bc 100644 --- a/lib/libcxx/docs/DesignDocs/CapturingConfigInfo.rst +++ b/lib/libcxx/docs/DesignDocs/CapturingConfigInfo.rst @@ -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. diff --git a/lib/libcxx/docs/DesignDocs/FeatureTestMacros.rst b/lib/libcxx/docs/DesignDocs/FeatureTestMacros.rst new file mode 100644 index 00000000000..d55af96c674 --- /dev/null +++ b/lib/libcxx/docs/DesignDocs/FeatureTestMacros.rst @@ -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.
\ No newline at end of file diff --git a/lib/libcxx/docs/DesignDocs/VisibilityMacros.rst b/lib/libcxx/docs/DesignDocs/VisibilityMacros.rst index ab577df1364..d0d4f0adb22 100644 --- a/lib/libcxx/docs/DesignDocs/VisibilityMacros.rst +++ b/lib/libcxx/docs/DesignDocs/VisibilityMacros.rst @@ -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 @@ -44,6 +44,21 @@ Visibility Macros Mark a function as not being part of the ABI of any final linked image that 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 @@ -67,9 +82,9 @@ Visibility Macros **_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 overriden by users. + `_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 overriden by users. + `_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 @@ -77,7 +92,7 @@ Visibility Macros appropriately. By default, this macro is not defined, which means that per TU ABI insulation - is not provided unless explicitly overriden by users. + is not provided unless explicitly overridden by users. **_LIBCPP_TYPE_VIS** Mark a type's typeinfo, vtable and members as having default visibility. @@ -172,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*. diff --git a/lib/libcxx/docs/FeatureTestMacroTable.rst b/lib/libcxx/docs/FeatureTestMacroTable.rst new file mode 100644 index 00000000000..d900497eba7 --- /dev/null +++ b/lib/libcxx/docs/FeatureTestMacroTable.rst @@ -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* + ================================================= ================= + + diff --git a/lib/libcxx/docs/ReleaseNotes.rst b/lib/libcxx/docs/ReleaseNotes.rst new file mode 100644 index 00000000000..ca5a534ae84 --- /dev/null +++ b/lib/libcxx/docs/ReleaseNotes.rst @@ -0,0 +1,48 @@ +========================== +Libc++ 8.0.0 Release Notes +========================== + +.. contents:: + :local: + :depth: 2 + +Written by the `Libc++ Team <https://libcxx.llvm.org>`_ + +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://releases.llvm.org/>`_. + +For more information about libc++, please see the `Libc++ Web Site +<https://libcxx.llvm.org>`_ or the `LLVM Web Site <https://llvm.org>`_. + +What's New in Libc++ 8.0.0? +=========================== + +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. diff --git a/lib/libcxx/docs/TestingLibcxx.rst b/lib/libcxx/docs/TestingLibcxx.rst index 43c0684dc7d..ebbbf628ac0 100644 --- a/lib/libcxx/docs/TestingLibcxx.rst +++ b/lib/libcxx/docs/TestingLibcxx.rst @@ -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. diff --git a/lib/libcxx/docs/UsingLibcxx.rst b/lib/libcxx/docs/UsingLibcxx.rst index e10a27c598a..899656cca1d 100644 --- a/lib/libcxx/docs/UsingLibcxx.rst +++ b/lib/libcxx/docs/UsingLibcxx.rst @@ -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`` diff --git a/lib/libcxx/docs/conf.py b/lib/libcxx/docs/conf.py index 4c1ea3653cd..50b372cf84e 100644 --- a/lib/libcxx/docs/conf.py +++ b/lib/libcxx/docs/conf.py @@ -40,16 +40,16 @@ master_doc = 'index' # General information about the project. project = u'libc++' -copyright = u'2011-2017, LLVM Project' +copyright = u'2011-2018, LLVM Project' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '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_documents = [ #texinfo_show_urls = 'footnote' -# FIXME: Define intersphinx configration. +# FIXME: Define intersphinx configuration. intersphinx_mapping = {} diff --git a/lib/libcxx/docs/index.rst b/lib/libcxx/docs/index.rst index e4b3a879da9..fddf74b66a9 100644 --- a/lib/libcxx/docs/index.rst +++ b/lib/libcxx/docs/index.rst @@ -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/>`_ diff --git a/lib/libcxx/include/CMakeLists.txt b/lib/libcxx/include/CMakeLists.txt index d9def18d725..73f7cfc4d8e 100644 --- a/lib/libcxx/include/CMakeLists.txt +++ b/lib/libcxx/include/CMakeLists.txt @@ -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 diff --git a/lib/libcxx/include/__bit_reference b/lib/libcxx/include/__bit_reference index 3e4a21d261f..c208af2b4d7 100644 --- a/lib/libcxx/include/__bit_reference +++ b/lib/libcxx/include/__bit_reference @@ -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; } diff --git a/lib/libcxx/include/__config_site.in b/lib/libcxx/include/__config_site.in index 7c7c226c492..580a6aa4c07 100644 --- a/lib/libcxx/include/__config_site.in +++ b/lib/libcxx/include/__config_site.in @@ -28,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@ diff --git a/lib/libcxx/include/__debug b/lib/libcxx/include/__debug index d01bacdf7ed..a8788f68f8f 100644 --- a/lib/libcxx/include/__debug +++ b/lib/libcxx/include/__debug @@ -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 diff --git a/lib/libcxx/include/__functional_base b/lib/libcxx/include/__functional_base index 57fdf2b9f66..032be99bf6a 100644 --- a/lib/libcxx/include/__functional_base +++ b/lib/libcxx/include/__functional_base @@ -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 diff --git a/lib/libcxx/include/__hash_table b/lib/libcxx/include/__hash_table index c77de961be6..6f5b183105e 100644 --- a/lib/libcxx/include/__hash_table +++ b/lib/libcxx/include/__hash_table @@ -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(); + rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), + size_type(ceil(float(size() + 1) / max_load_factor())))); + } + 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> +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; } -__done: #if _LIBCPP_DEBUG_LEVEL >= 2 - return pair<iterator, bool>(iterator(__ndptr, this), __inserted); + return pair<iterator, bool>(iterator(__existing_node, this), __inserted); #else - return pair<iterator, bool>(iterator(__ndptr), __inserted); + 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>::iterator -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) +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,20 +1970,9 @@ __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) - { - __pn =__p1_.first().__ptr(); - __cp->__next_ = __pn->__next_; - __pn->__next_ = __cp->__ptr(); - // fix up __bucket_list_ - __bucket_list_[__chash] = __pn; - if (__cp->__next_ != nullptr) - __bucket_list_[__constrain_hash(__cp->__next_->__hash(), __bc)] - = __cp->__ptr(); - } - else + if (__pn != nullptr) { for (bool __found = false; __pn->__next_ != nullptr && __constrain_hash(__pn->__next_->__hash(), __bc) == __chash; @@ -1947,8 +1983,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __c // 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 != (__pn->__next_->__hash() == __cp_hash && + key_eq()(__pn->__next_->__upcast()->__value_, __cp_val))) { if (!__found) __found = true; @@ -1956,6 +1992,35 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __c 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(); + __cp->__next_ = __pn->__next_; + __pn->__next_ = __cp->__ptr(); + // fix up __bucket_list_ + __bucket_list_[__chash] = __pn; + if (__cp->__next_ != nullptr) + __bucket_list_[__constrain_hash(__cp->__next_->__hash(), __bc)] + = __cp->__ptr(); + } + else + { __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 @@ -2217,6 +2293,32 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract( } template <class _Tp, class _Hash, class _Equal, class _Alloc> +template <class _Table> +_LIBCPP_INLINE_VISIBILITY +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique( + _Table& __source) +{ + static_assert(is_same<__node, typename _Table::__node>::value, ""); + + for (typename _Table::iterator __it = __source.begin(); + __it != __source.end();) + { + __node_pointer __src_ptr = __it.__node_->__upcast(); + size_t __hash = hash_function()(__src_ptr->__value_); + __next_pointer __existing_node = + __node_insert_unique_prepare(__hash, __src_ptr->__value_); + auto __prev_iter = __it++; + if (__existing_node == nullptr) + { + (void)__source.remove(__prev_iter).release(); + __src_ptr->__hash_ = __hash; + __node_insert_unique_perform(__src_ptr); + } + } +} + +template <class _Tp, class _Hash, class _Equal, class _Alloc> template <class _NodeHandle> _LIBCPP_INLINE_VISIBILITY typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator @@ -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> diff --git a/lib/libcxx/include/__libcpp_version b/lib/libcxx/include/__libcpp_version index 2bdc6533bec..e002b3628b3 100644 --- a/lib/libcxx/include/__libcpp_version +++ b/lib/libcxx/include/__libcpp_version @@ -1 +1 @@ -7000 +8000 diff --git a/lib/libcxx/include/__mutex_base b/lib/libcxx/include/__mutex_base index 4659ca9298c..da21a5f8eb6 100644 --- a/lib/libcxx/include/__mutex_base +++ b/lib/libcxx/include/__mutex_base @@ -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 diff --git a/lib/libcxx/include/__node_handle b/lib/libcxx/include/__node_handle index 567f8b047a3..a9cf3b7217a 100644 --- a/lib/libcxx/include/__node_handle +++ b/lib/libcxx/include/__node_handle @@ -26,9 +26,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -// FIXME: Uncomment this when we support the 'merge' functionality. -// #define __cpp_lib_node_extract 201606L - // Specialized in __tree & __hash_table for their _NodeType. template <class _NodeType, class _Alloc> struct __generic_container_node_destructor; diff --git a/lib/libcxx/include/__sso_allocator b/lib/libcxx/include/__sso_allocator index 40027363a18..8aca0495d75 100644 --- a/lib/libcxx/include/__sso_allocator +++ b/lib/libcxx/include/__sso_allocator @@ -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);} diff --git a/lib/libcxx/include/__string b/lib/libcxx/include/__string index 44c55987f9f..1ddeec7149f 100644 --- a/lib/libcxx/include/__string +++ b/lib/libcxx/include/__string @@ -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 <> diff --git a/lib/libcxx/include/__threading_support b/lib/libcxx/include/__threading_support index 3c1eff22f53..20249006272 100644 --- a/lib/libcxx/include/__threading_support +++ b/lib/libcxx/include/__threading_support @@ -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 diff --git a/lib/libcxx/include/__tree b/lib/libcxx/include/__tree index af9b9616df8..814851085b9 100644 --- a/lib/libcxx/include/__tree +++ b/lib/libcxx/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; @@ -2472,6 +2462,30 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p) } template <class _Tp, class _Compare, class _Allocator> +template <class _Tree> +_LIBCPP_INLINE_VISIBILITY +void +__tree<_Tp, _Compare, _Allocator>::__node_handle_merge_unique(_Tree& __source) +{ + static_assert(is_same<typename _Tree::__node_pointer, __node_pointer>::value, ""); + + for (typename _Tree::iterator __i = __source.begin(); + __i != __source.end();) + { + __node_pointer __src_ptr = __i.__get_np(); + __parent_pointer __parent; + __node_base_pointer& __child = + __find_equal(__parent, _NodeTypes::__get_key(__src_ptr->__value_)); + ++__i; + if (__child != nullptr) + continue; + __source.__remove_node_pointer(__src_ptr); + __insert_node_at(__parent, __child, + static_cast<__node_base_pointer>(__src_ptr)); + } +} + +template <class _Tp, class _Compare, class _Allocator> template <class _NodeHandle> _LIBCPP_INLINE_VISIBILITY typename __tree<_Tp, _Compare, _Allocator>::iterator @@ -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> diff --git a/lib/libcxx/include/__tuple b/lib/libcxx/include/__tuple index 69d6ee96111..3b23d78afa1 100644 --- a/lib/libcxx/include/__tuple +++ b/lib/libcxx/include/__tuple @@ -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)> { }; diff --git a/lib/libcxx/include/algorithm b/lib/libcxx/include/algorithm index 90f1d246c63..d102899f2df 100644 --- a/lib/libcxx/include/algorithm +++ b/lib/libcxx/include/algorithm @@ -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_)) diff --git a/lib/libcxx/include/any b/lib/libcxx/include/any index 9bd2f53c560..781eee7869c 100644 --- a/lib/libcxx/include/any +++ b/lib/libcxx/include/any @@ -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>; diff --git a/lib/libcxx/include/array b/lib/libcxx/include/array index 1e6a650198b..56f6887655a 100644 --- a/lib/libcxx/include/array +++ b/lib/libcxx/include/array @@ -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> diff --git a/lib/libcxx/include/atomic b/lib/libcxx/include/atomic index 809f78a06d3..d37e7b4b035 100644 --- a/lib/libcxx/include/atomic +++ b/lib/libcxx/include/atomic @@ -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 || \ diff --git a/lib/libcxx/include/bit b/lib/libcxx/include/bit new file mode 100644 index 00000000000..db3812e5b5b --- /dev/null +++ b/lib/libcxx/include/bit @@ -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 diff --git a/lib/libcxx/include/bitset b/lib/libcxx/include/bitset index cd6c289b4c4..98947e027c1 100644 --- a/lib/libcxx/include/bitset +++ b/lib/libcxx/include/bitset @@ -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> diff --git a/lib/libcxx/include/charconv b/lib/libcxx/include/charconv index 7cb790e1bee..064f2e11c3f 100644 --- a/lib/libcxx/include/charconv +++ b/lib/libcxx/include/charconv @@ -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 diff --git a/lib/libcxx/include/chrono b/lib/libcxx/include/chrono index f6a6f4b2434..96759f9860e 100644 --- a/lib/libcxx/include/chrono +++ b/lib/libcxx/include/chrono @@ -33,9 +33,9 @@ template <class Rep> struct duration_values { public: - static constexpr Rep zero(); - static constexpr Rep max(); - static constexpr Rep min(); + static constexpr Rep zero(); // noexcept in C++20 + static constexpr Rep max(); // noexcept in C++20 + static constexpr Rep min(); // noexcept in C++20 }; // duration @@ -77,22 +77,24 @@ public: constexpr common_type<duration>::type operator+() const; constexpr common_type<duration>::type operator-() const; - constexpr duration& operator++(); - constexpr duration operator++(int); - constexpr duration& operator--(); - constexpr duration operator--(int); + constexpr duration& operator++(); // constexpr in C++17 + constexpr duration operator++(int); // constexpr in C++17 + constexpr duration& operator--(); // constexpr in C++17 + constexpr duration operator--(int); // constexpr in C++17 - constexpr duration& operator+=(const duration& d); - constexpr duration& operator-=(const duration& d); + constexpr duration& operator+=(const duration& d); // constexpr in C++17 + constexpr duration& operator-=(const duration& d); // constexpr in C++17 - duration& operator*=(const rep& rhs); - duration& operator/=(const rep& rhs); + duration& operator*=(const rep& rhs); // constexpr in C++17 + duration& operator/=(const rep& rhs); // constexpr in C++17 + duration& operator%=(const rep& rhs); // constexpr in C++17 + duration& operator%=(const duration& rhs); // constexpr in C++17 // special values - static constexpr duration zero(); - static constexpr duration min(); - static constexpr duration max(); + static constexpr duration zero(); // noexcept in C++20 + static constexpr duration min(); // noexcept in C++20 + static constexpr duration max(); // noexcept in C++20 }; typedef duration<long long, nano> nanoseconds; @@ -127,13 +129,13 @@ public: // arithmetic - time_point& operator+=(const duration& d); - time_point& operator-=(const duration& d); + time_point& operator+=(const duration& d); // constexpr in C++17 + time_point& operator-=(const duration& d); // constexpr in C++17 // special values - static constexpr time_point min(); - static constexpr time_point max(); + static constexpr time_point min(); // noexcept in C++20 + static constexpr time_point max(); // noexcept in C++20 }; } // chrono @@ -323,7 +325,7 @@ struct clock_time_conversion; template<class DestClock, class SourceClock, class Duration> auto clock_cast(const time_point<SourceClock, Duration>& t); - + // 25.8.2, class last_spec // C++20 struct last_spec; @@ -528,7 +530,7 @@ constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; - + // 25.8.18, civil calendar conventional syntax operators // C++20 constexpr year_month operator/(const year& y, const month& m) noexcept; @@ -609,7 +611,7 @@ constexpr year_month_weekday_last constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, const year& y) noexcept; constexpr year_month_weekday_last - operator/(const month_weekday_last& mwdl, int y) noexcept; + operator/(const month_weekday_last& mwdl, int y) noexcept; // 25.9, class template time_of_day // C++20 template<class Duration> class time_of_day; @@ -640,7 +642,7 @@ class ambiguous_local_time; // 25.10.4, information classes // C++20 struct sys_info; struct local_info; - + // 25.10.5, class time_zone // C++20 enum class choose {earliest, latest}; class time_zone; @@ -650,7 +652,7 @@ bool operator<(const time_zone& x, const time_zone& y) noexcept; bool operator>(const time_zone& x, const time_zone& y) noexcept; bool operator<=(const time_zone& x, const time_zone& y) noexcept; bool operator>=(const time_zone& x, const time_zone& y) noexcept; - + // 25.10.6, class template zoned_traits // C++20 template<class T> struct zoned_traits; @@ -724,7 +726,7 @@ template<class charT, class traits, class Alloc, class Streamable> template<class charT, class traits, class Alloc, class Streamable> basic_string<charT, traits, Alloc> format(const locale& loc, const basic_string<charT, traits, Alloc>& fmt, - const Streamable& s); + const Streamable& s); // 25.12, parsing // C++20 template<class charT, class traits, class Alloc, class Parsable> @@ -746,7 +748,8 @@ unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); -inline constexpr last_spec last{}; // C++20 +// calendrical constants +inline constexpr last_spec last{}; // C++20 inline constexpr chrono::weekday Sunday{0}; // C++20 inline constexpr chrono::weekday Monday{1}; // C++20 inline constexpr chrono::weekday Tuesday{2}; // C++20 @@ -796,6 +799,7 @@ constexpr chrono::year operator ""y(unsigned lo #include <type_traits> #include <ratio> #include <limits> +#include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -804,6 +808,11 @@ constexpr chrono::year operator ""y(unsigned lo _LIBCPP_PUSH_MACROS #include <__undef_macros> +#ifndef _LIBCPP_CXX03_LANG +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM +struct _FilesystemClock; +_LIBCPP_END_NAMESPACE_FILESYSTEM +#endif // !_LIBCPP_CXX03_LANG _LIBCPP_BEGIN_NAMESPACE_STD @@ -920,9 +929,9 @@ template <class _Rep> struct _LIBCPP_TEMPLATE_VIS duration_values { public: - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep zero() {return _Rep(0);} - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep max() {return numeric_limits<_Rep>::max();} - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep min() {return numeric_limits<_Rep>::lowest();} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT {return _Rep(0);} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT {return numeric_limits<_Rep>::max();} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT {return numeric_limits<_Rep>::lowest();} }; #if _LIBCPP_STD_VER > 14 @@ -1015,7 +1024,7 @@ class _LIBCPP_TEMPLATE_VIS duration typedef ratio<__mul<__n1, __d2, !value>::value, __mul<__n2, __d1, !value>::value> type; }; - + public: typedef _Rep rep; typedef typename _Period::type period; @@ -1077,9 +1086,9 @@ public: // special values - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration zero() {return duration(duration_values<rep>::zero());} - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration min() {return duration(duration_values<rep>::min());} - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration max() {return duration(duration_values<rep>::max());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration zero() _NOEXCEPT {return duration(duration_values<rep>::zero());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration min() _NOEXCEPT {return duration(duration_values<rep>::min());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR duration max() _NOEXCEPT {return duration(duration_values<rep>::max());} }; typedef duration<long long, nano> nanoseconds; @@ -1088,7 +1097,12 @@ typedef duration<long long, milli> milliseconds; typedef duration<long long > seconds; typedef duration< long, ratio< 60> > minutes; typedef duration< long, ratio<3600> > hours; - +#if _LIBCPP_STD_VER > 17 +typedef duration< int, ratio_multiply<ratio<24>, hours::period>> days; +typedef duration< int, ratio_multiply<ratio<7>, days::period>> weeks; +typedef duration< int, ratio_multiply<ratio<146097, 400>, days::period>> years; +typedef duration< int, ratio_divide<years::period, ratio<12>>> months; +#endif // Duration == template <class _LhsDuration, class _RhsDuration> @@ -1355,13 +1369,13 @@ public: // arithmetic - _LIBCPP_INLINE_VISIBILITY time_point& operator+=(const duration& __d) {__d_ += __d; return *this;} - _LIBCPP_INLINE_VISIBILITY time_point& operator-=(const duration& __d) {__d_ -= __d; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 time_point& operator+=(const duration& __d) {__d_ += __d; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 time_point& operator-=(const duration& __d) {__d_ -= __d; return *this;} // special values - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point min() {return time_point(duration::min());} - _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point max() {return time_point(duration::max());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point min() _NOEXCEPT {return time_point(duration::min());} + _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR time_point max() _NOEXCEPT {return time_point(duration::max());} }; } // chrono @@ -1571,12 +1585,1158 @@ typedef steady_clock high_resolution_clock; typedef system_clock high_resolution_clock; #endif +#if _LIBCPP_STD_VER > 17 +// [time.clock.file], type file_clock +using file_clock = _VSTD_FS::_FilesystemClock; + +template<class _Duration> +using file_time = time_point<file_clock, _Duration>; + + +template <class _Duration> +using sys_time = time_point<system_clock, _Duration>; +using sys_seconds = sys_time<seconds>; +using sys_days = sys_time<days>; + +struct local_t {}; +template<class Duration> +using local_time = time_point<local_t, Duration>; +using local_seconds = local_time<seconds>; +using local_days = local_time<days>; + + +struct _LIBCPP_TYPE_VIS last_spec { explicit last_spec() = default; }; + +class _LIBCPP_TYPE_VIS day { +private: + unsigned char __d; +public: + day() = default; + explicit inline constexpr day(unsigned __val) noexcept : __d(static_cast<unsigned char>(__val)) {} + inline constexpr day& operator++() noexcept { ++__d; return *this; } + inline constexpr day operator++(int) noexcept { day __tmp = *this; ++(*this); return __tmp; } + inline constexpr day& operator--() noexcept { --__d; return *this; } + inline constexpr day operator--(int) noexcept { day __tmp = *this; --(*this); return __tmp; } + constexpr day& operator+=(const days& __dd) noexcept; + constexpr day& operator-=(const days& __dd) noexcept; + explicit inline constexpr operator unsigned() const noexcept { return __d; } + inline constexpr bool ok() const noexcept { return __d >= 1 && __d <= 31; } + }; + + +inline constexpr +bool operator==(const day& __lhs, const day& __rhs) noexcept +{ return static_cast<unsigned>(__lhs) == static_cast<unsigned>(__rhs); } + +inline constexpr +bool operator!=(const day& __lhs, const day& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const day& __lhs, const day& __rhs) noexcept +{ return static_cast<unsigned>(__lhs) < static_cast<unsigned>(__rhs); } + +inline constexpr +bool operator> (const day& __lhs, const day& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const day& __lhs, const day& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const day& __lhs, const day& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +day operator+ (const day& __lhs, const days& __rhs) noexcept +{ return day(static_cast<unsigned>(__lhs) + __rhs.count()); } + +inline constexpr +day operator+ (const days& __lhs, const day& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +day operator- (const day& __lhs, const days& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +days operator-(const day& __lhs, const day& __rhs) noexcept +{ return days(static_cast<int>(static_cast<unsigned>(__lhs)) - + static_cast<int>(static_cast<unsigned>(__rhs))); } + +inline constexpr day& day::operator+=(const days& __dd) noexcept +{ *this = *this + __dd; return *this; } + +inline constexpr day& day::operator-=(const days& __dd) noexcept +{ *this = *this - __dd; return *this; } + + +class _LIBCPP_TYPE_VIS month { +private: + unsigned char __m; +public: + month() = default; + explicit inline constexpr month(unsigned __val) noexcept : __m(static_cast<unsigned char>(__val)) {} + inline constexpr month& operator++() noexcept { ++__m; return *this; } + inline constexpr month operator++(int) noexcept { month __tmp = *this; ++(*this); return __tmp; } + inline constexpr month& operator--() noexcept { --__m; return *this; } + inline constexpr month operator--(int) noexcept { month __tmp = *this; --(*this); return __tmp; } + constexpr month& operator+=(const months& __m1) noexcept; + constexpr month& operator-=(const months& __m1) noexcept; + explicit inline constexpr operator unsigned() const noexcept { return __m; } + inline constexpr bool ok() const noexcept { return __m >= 1 && __m <= 12; } +}; + + +inline constexpr +bool operator==(const month& __lhs, const month& __rhs) noexcept +{ return static_cast<unsigned>(__lhs) == static_cast<unsigned>(__rhs); } + +inline constexpr +bool operator!=(const month& __lhs, const month& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const month& __lhs, const month& __rhs) noexcept +{ return static_cast<unsigned>(__lhs) < static_cast<unsigned>(__rhs); } + +inline constexpr +bool operator> (const month& __lhs, const month& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const month& __lhs, const month& __rhs) noexcept +{ return !(__rhs < __lhs); } + +inline constexpr +bool operator>=(const month& __lhs, const month& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +month operator+ (const month& __lhs, const months& __rhs) noexcept +{ + auto const __mu = static_cast<long long>(static_cast<unsigned>(__lhs)) + (__rhs.count() - 1); + auto const __yr = (__mu >= 0 ? __mu : __mu - 11) / 12; + return month{static_cast<unsigned>(__mu - __yr * 12 + 1)}; +} + +inline constexpr +month operator+ (const months& __lhs, const month& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +month operator- (const month& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +months operator-(const month& __lhs, const month& __rhs) noexcept +{ + auto const __dm = static_cast<unsigned>(__lhs) - static_cast<unsigned>(__rhs); + return months(__dm <= 11 ? __dm : __dm + 12); +} + +inline constexpr month& month::operator+=(const months& __dm) noexcept +{ *this = *this + __dm; return *this; } + +inline constexpr month& month::operator-=(const months& __dm) noexcept +{ *this = *this - __dm; return *this; } + + +class _LIBCPP_TYPE_VIS year { +private: + short __y; +public: + year() = default; + explicit inline constexpr year(int __val) noexcept : __y(static_cast<short>(__val)) {} + + inline constexpr year& operator++() noexcept { ++__y; return *this; }; + inline constexpr year operator++(int) noexcept { year __tmp = *this; ++(*this); return __tmp; }; + inline constexpr year& operator--() noexcept { --__y; return *this; }; + inline constexpr year operator--(int) noexcept { year __tmp = *this; --(*this); return __tmp; }; + constexpr year& operator+=(const years& __dy) noexcept; + constexpr year& operator-=(const years& __dy) noexcept; + inline constexpr year operator+() const noexcept { return *this; } + inline constexpr year operator-() const noexcept { return year{-__y}; }; + + inline constexpr bool is_leap() const noexcept { return __y % 4 == 0 && (__y % 100 != 0 || __y % 400 == 0); } + explicit inline constexpr operator int() const noexcept { return __y; } + constexpr bool ok() const noexcept; + static inline constexpr year min() noexcept { return year{-32767}; } + static inline constexpr year max() noexcept { return year{ 32767}; } +}; + + +inline constexpr +bool operator==(const year& __lhs, const year& __rhs) noexcept +{ return static_cast<int>(__lhs) == static_cast<int>(__rhs); } + +inline constexpr +bool operator!=(const year& __lhs, const year& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year& __lhs, const year& __rhs) noexcept +{ return static_cast<int>(__lhs) < static_cast<int>(__rhs); } + +inline constexpr +bool operator> (const year& __lhs, const year& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year& __lhs, const year& __rhs) noexcept +{ return !(__rhs < __lhs); } + +inline constexpr +bool operator>=(const year& __lhs, const year& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +year operator+ (const year& __lhs, const years& __rhs) noexcept +{ return year(static_cast<int>(__lhs) + __rhs.count()); } + +inline constexpr +year operator+ (const years& __lhs, const year& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year operator- (const year& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +years operator-(const year& __lhs, const year& __rhs) noexcept +{ return years{static_cast<int>(__lhs) - static_cast<int>(__rhs)}; } + + +inline constexpr year& year::operator+=(const years& __dy) noexcept +{ *this = *this + __dy; return *this; } + +inline constexpr year& year::operator-=(const years& __dy) noexcept +{ *this = *this - __dy; return *this; } + +inline constexpr bool year::ok() const noexcept +{ return static_cast<int>(min()) <= __y && __y <= static_cast<int>(max()); } + +class _LIBCPP_TYPE_VIS weekday_indexed; +class _LIBCPP_TYPE_VIS weekday_last; + +class _LIBCPP_TYPE_VIS weekday { +private: + unsigned char __wd; +public: + weekday() = default; + inline explicit constexpr weekday(unsigned __val) noexcept : __wd(static_cast<unsigned char>(__val)) {} + inline constexpr weekday(const sys_days& __sysd) noexcept + : __wd(__weekday_from_days(__sysd.time_since_epoch().count())) {} + inline explicit constexpr weekday(const local_days& __locd) noexcept + : __wd(__weekday_from_days(__locd.time_since_epoch().count())) {} + + inline constexpr weekday& operator++() noexcept { __wd = (__wd == 6 ? 0 : __wd + 1); return *this; } + inline constexpr weekday operator++(int) noexcept { weekday __tmp = *this; ++(*this); return __tmp; } + inline constexpr weekday& operator--() noexcept { __wd = (__wd == 0 ? 6 : __wd - 1); return *this; } + inline constexpr weekday operator--(int) noexcept { weekday __tmp = *this; --(*this); return __tmp; } + constexpr weekday& operator+=(const days& __dd) noexcept; + constexpr weekday& operator-=(const days& __dd) noexcept; + inline explicit constexpr operator unsigned() const noexcept { return __wd; } + inline constexpr bool ok() const noexcept { return __wd <= 6; } + constexpr weekday_indexed operator[](unsigned __index) const noexcept; + constexpr weekday_last operator[](last_spec) const noexcept; + + static constexpr unsigned char __weekday_from_days(int __days) noexcept; +}; + + +// https://howardhinnant.github.io/date_algorithms.html#weekday_from_days +inline constexpr +unsigned char weekday::__weekday_from_days(int __days) noexcept +{ + return static_cast<unsigned char>( + static_cast<unsigned>(__days >= -4 ? (__days+4) % 7 : (__days+5) % 7 + 6) + ); +} + +inline constexpr +bool operator==(const weekday& __lhs, const weekday& __rhs) noexcept +{ return static_cast<unsigned>(__lhs) == static_cast<unsigned>(__rhs); } + +inline constexpr +bool operator!=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const weekday& __lhs, const weekday& __rhs) noexcept +{ return static_cast<unsigned>(__lhs) < static_cast<unsigned>(__rhs); } + +inline constexpr +bool operator> (const weekday& __lhs, const weekday& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const weekday& __lhs, const weekday& __rhs) noexcept +{ return !(__lhs < __rhs); } + +constexpr weekday operator+(const weekday& __lhs, const days& __rhs) noexcept +{ + auto const __mu = static_cast<long long>(static_cast<unsigned>(__lhs)) + __rhs.count(); + auto const __yr = (__mu >= 0 ? __mu : __mu - 6) / 7; + return weekday{static_cast<unsigned>(__mu - __yr * 7)}; +} + +constexpr weekday operator+(const days& __lhs, const weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +constexpr weekday operator-(const weekday& __lhs, const days& __rhs) noexcept +{ return __lhs + -__rhs; } + +constexpr days operator-(const weekday& __lhs, const weekday& __rhs) noexcept +{ + const int __wdu = static_cast<unsigned>(__lhs) - static_cast<unsigned>(__rhs); + const int __wk = (__wdu >= 0 ? __wdu : __wdu-6) / 7; + return days{__wdu - __wk * 7}; +} + +inline constexpr weekday& weekday::operator+=(const days& __dd) noexcept +{ *this = *this + __dd; return *this; } + +inline constexpr weekday& weekday::operator-=(const days& __dd) noexcept +{ *this = *this - __dd; return *this; } + + +class _LIBCPP_TYPE_VIS weekday_indexed { +private: + _VSTD::chrono::weekday __wd; + unsigned char __idx; +public: + weekday_indexed() = default; + inline constexpr weekday_indexed(const _VSTD::chrono::weekday& __wdval, unsigned __idxval) noexcept + : __wd{__wdval}, __idx(__idxval) {} + inline constexpr _VSTD::chrono::weekday weekday() const noexcept { return __wd; } + inline constexpr unsigned index() const noexcept { return __idx; } + inline constexpr bool ok() const noexcept { return __wd.ok() && __idx >= 1 && __idx <= 5; } +}; + +inline constexpr +bool operator==(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept +{ return __lhs.weekday() == __rhs.weekday() && __lhs.index() == __rhs.index(); } + +inline constexpr +bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +class _LIBCPP_TYPE_VIS weekday_last { +private: + _VSTD::chrono::weekday __wd; +public: + explicit constexpr weekday_last(const _VSTD::chrono::weekday& __val) noexcept + : __wd{__val} {} + constexpr _VSTD::chrono::weekday weekday() const noexcept { return __wd; } + constexpr bool ok() const noexcept { return __wd.ok(); } +}; + +inline constexpr +bool operator==(const weekday_last& __lhs, const weekday_last& __rhs) noexcept +{ return __lhs.weekday() == __rhs.weekday(); } + +inline constexpr +bool operator!=(const weekday_last& __lhs, const weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +weekday_indexed weekday::operator[](unsigned __index) const noexcept { return weekday_indexed{*this, __index}; } + +inline constexpr +weekday_last weekday::operator[](last_spec) const noexcept { return weekday_last{*this}; } + + +inline constexpr last_spec last{}; +inline constexpr weekday Sunday{0}; +inline constexpr weekday Monday{1}; +inline constexpr weekday Tuesday{2}; +inline constexpr weekday Wednesday{3}; +inline constexpr weekday Thursday{4}; +inline constexpr weekday Friday{5}; +inline constexpr weekday Saturday{6}; + +inline constexpr month January{1}; +inline constexpr month February{2}; +inline constexpr month March{3}; +inline constexpr month April{4}; +inline constexpr month May{5}; +inline constexpr month June{6}; +inline constexpr month July{7}; +inline constexpr month August{8}; +inline constexpr month September{9}; +inline constexpr month October{10}; +inline constexpr month November{11}; +inline constexpr month December{12}; + + +class _LIBCPP_TYPE_VIS month_day { +private: + chrono::month __m; + chrono::day __d; +public: + month_day() = default; + constexpr month_day(const chrono::month& __mval, const chrono::day& __dval) noexcept + : __m{__mval}, __d{__dval} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::day day() const noexcept { return __d; } + constexpr bool ok() const noexcept; +}; + +inline constexpr +bool month_day::ok() const noexcept +{ + if (!__m.ok()) return false; + const unsigned __dval = static_cast<unsigned>(__d); + if (__dval < 1 || __dval > 31) return false; + if (__dval <= 29) return true; +// Now we've got either 30 or 31 + const unsigned __mval = static_cast<unsigned>(__m); + if (__mval == 2) return false; + if (__mval == 4 || __mval == 6 || __mval == 9 || __mval == 11) + return __dval == 30; + return true; +} + +inline constexpr +bool operator==(const month_day& __lhs, const month_day& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } + +inline constexpr +bool operator!=(const month_day& __lhs, const month_day& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +month_day operator/(const month& __lhs, const day& __rhs) noexcept +{ return month_day{__lhs, __rhs}; } + +constexpr +month_day operator/(const day& __lhs, const month& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +month_day operator/(const month& __lhs, int __rhs) noexcept +{ return __lhs / day(__rhs); } + +constexpr +month_day operator/(int __lhs, const day& __rhs) noexcept +{ return month(__lhs) / __rhs; } + +constexpr +month_day operator/(const day& __lhs, int __rhs) noexcept +{ return month(__rhs) / __lhs; } + + +inline constexpr +bool operator< (const month_day& __lhs, const month_day& __rhs) noexcept +{ return __lhs.month() != __rhs.month() ? __lhs.month() < __rhs.month() : __lhs.day() < __rhs.day(); } + +inline constexpr +bool operator> (const month_day& __lhs, const month_day& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const month_day& __lhs, const month_day& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const month_day& __lhs, const month_day& __rhs) noexcept +{ return !(__lhs < __rhs); } + + + +class _LIBCPP_TYPE_VIS month_day_last { +private: + chrono::month __m; +public: + explicit constexpr month_day_last(const chrono::month& __val) noexcept + : __m{__val} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr bool ok() const noexcept { return __m.ok(); } +}; + +inline constexpr +bool operator==(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return __lhs.month() == __rhs.month(); } + +inline constexpr +bool operator!=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return __lhs.month() < __rhs.month(); } + +inline constexpr +bool operator> (const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +month_day_last operator/(const month& __lhs, last_spec) noexcept +{ return month_day_last{__lhs}; } + +inline constexpr +month_day_last operator/(last_spec, const month& __rhs) noexcept +{ return month_day_last{__rhs}; } + +inline constexpr +month_day_last operator/(int __lhs, last_spec) noexcept +{ return month_day_last{month(__lhs)}; } + +inline constexpr +month_day_last operator/(last_spec, int __rhs) noexcept +{ return month_day_last{month(__rhs)}; } + + +class _LIBCPP_TYPE_VIS month_weekday { +private: + chrono::month __m; + chrono::weekday_indexed __wdi; +public: + month_weekday() = default; + constexpr month_weekday(const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept + : __m{__mval}, __wdi{__wdival} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; } + inline constexpr bool ok() const noexcept { return __m.ok() && __wdi.ok(); } +}; + +inline constexpr +bool operator==(const month_weekday& __lhs, const month_weekday& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } + +inline constexpr +bool operator!=(const month_weekday& __lhs, const month_weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +month_weekday operator/(const month& __lhs, const weekday_indexed& __rhs) noexcept +{ return month_weekday{__lhs, __rhs}; } + +inline constexpr +month_weekday operator/(int __lhs, const weekday_indexed& __rhs) noexcept +{ return month_weekday{month(__lhs), __rhs}; } + +inline constexpr +month_weekday operator/(const weekday_indexed& __lhs, const month& __rhs) noexcept +{ return month_weekday{__rhs, __lhs}; } + +inline constexpr +month_weekday operator/(const weekday_indexed& __lhs, int __rhs) noexcept +{ return month_weekday{month(__rhs), __lhs}; } + + +class _LIBCPP_TYPE_VIS month_weekday_last { + chrono::month __m; + chrono::weekday_last __wdl; + public: + constexpr month_weekday_last(const chrono::month& __mval, const chrono::weekday_last& __wdlval) noexcept + : __m{__mval}, __wdl{__wdlval} {} + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; } + inline constexpr bool ok() const noexcept { return __m.ok() && __wdl.ok(); } +}; + +inline constexpr +bool operator==(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept +{ return __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } + +inline constexpr +bool operator!=(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +inline constexpr +month_weekday_last operator/(const month& __lhs, const weekday_last& __rhs) noexcept +{ return month_weekday_last{__lhs, __rhs}; } + +inline constexpr +month_weekday_last operator/(int __lhs, const weekday_last& __rhs) noexcept +{ return month_weekday_last{month(__lhs), __rhs}; } + +inline constexpr +month_weekday_last operator/(const weekday_last& __lhs, const month& __rhs) noexcept +{ return month_weekday_last{__rhs, __lhs}; } + +inline constexpr +month_weekday_last operator/(const weekday_last& __lhs, int __rhs) noexcept +{ return month_weekday_last{month(__rhs), __lhs}; } + + +class _LIBCPP_TYPE_VIS year_month { + chrono::year __y; + chrono::month __m; +public: + year_month() = default; + constexpr year_month(const chrono::year& __yval, const chrono::month& __mval) noexcept + : __y{__yval}, __m{__mval} {} + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m += __dm; return *this; } + inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m -= __dm; return *this; } + inline constexpr year_month& operator+=(const years& __dy) noexcept { this->__y += __dy; return *this; } + inline constexpr year_month& operator-=(const years& __dy) noexcept { this->__y -= __dy; return *this; } + inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok(); } +}; + +inline constexpr +year_month operator/(const year& __y, const month& __m) noexcept { return year_month{__y, __m}; } + +inline constexpr +year_month operator/(const year& __y, int __m) noexcept { return year_month{__y, month(__m)}; } + +inline constexpr +bool operator==(const year_month& __lhs, const year_month& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month(); } + +inline constexpr +bool operator!=(const year_month& __lhs, const year_month& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year_month& __lhs, const year_month& __rhs) noexcept +{ return __lhs.year() != __rhs.year() ? __lhs.year() < __rhs.year() : __lhs.month() < __rhs.month(); } + +inline constexpr +bool operator> (const year_month& __lhs, const year_month& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year_month& __lhs, const year_month& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const year_month& __lhs, const year_month& __rhs) noexcept +{ return !(__lhs < __rhs); } + +constexpr year_month operator+(const year_month& __lhs, const months& __rhs) noexcept +{ + int __dmi = static_cast<int>(static_cast<unsigned>(__lhs.month())) - 1 + __rhs.count(); + const int __dy = (__dmi >= 0 ? __dmi : __dmi-11) / 12; + __dmi = __dmi - __dy * 12 + 1; + return (__lhs.year() + years(__dy)) / month(static_cast<unsigned>(__dmi)); +} + +constexpr year_month operator+(const months& __lhs, const year_month& __rhs) noexcept +{ return __rhs + __lhs; } + +constexpr year_month operator+(const year_month& __lhs, const years& __rhs) noexcept +{ return (__lhs.year() + __rhs) / __lhs.month(); } + +constexpr year_month operator+(const years& __lhs, const year_month& __rhs) noexcept +{ return __rhs + __lhs; } + +constexpr months operator-(const year_month& __lhs, const year_month& __rhs) noexcept +{ return (__lhs.year() - __rhs.year()) + months(static_cast<unsigned>(__lhs.month()) - static_cast<unsigned>(__rhs.month())); } + +constexpr year_month operator-(const year_month& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +constexpr year_month operator-(const year_month& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +class year_month_day_last; + +class _LIBCPP_TYPE_VIS year_month_day { +private: + chrono::year __y; + chrono::month __m; + chrono::day __d; +public: + year_month_day() = default; + inline constexpr year_month_day( + const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept + : __y{__yval}, __m{__mval}, __d{__dval} {} + constexpr year_month_day(const year_month_day_last& __ymdl) noexcept; + inline constexpr year_month_day(const sys_days& __sysd) noexcept + : year_month_day(__from_days(__sysd.time_since_epoch())) {} + inline explicit constexpr year_month_day(const local_days& __locd) noexcept + : year_month_day(__from_days(__locd.time_since_epoch())) {} + + constexpr year_month_day& operator+=(const months& __dm) noexcept; + constexpr year_month_day& operator-=(const months& __dm) noexcept; + constexpr year_month_day& operator+=(const years& __dy) noexcept; + constexpr year_month_day& operator-=(const years& __dy) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::day day() const noexcept { return __d; } + inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + + constexpr bool ok() const noexcept; + + static constexpr year_month_day __from_days(days __d) noexcept; + constexpr days __to_days() const noexcept; +}; + + +// https://howardhinnant.github.io/date_algorithms.html#civil_from_days +inline constexpr +year_month_day +year_month_day::__from_days(days __d) noexcept +{ + static_assert(std::numeric_limits<unsigned>::digits >= 18, ""); + static_assert(std::numeric_limits<int>::digits >= 20 , ""); + const int __z = __d.count() + 719468; + const int __era = (__z >= 0 ? __z : __z - 146096) / 146097; + const unsigned __doe = static_cast<unsigned>(__z - __era * 146097); // [0, 146096] + const unsigned __yoe = (__doe - __doe/1460 + __doe/36524 - __doe/146096) / 365; // [0, 399] + const int __yr = static_cast<int>(__yoe) + __era * 400; + const unsigned __doy = __doe - (365 * __yoe + __yoe/4 - __yoe/100); // [0, 365] + const unsigned __mp = (5 * __doy + 2)/153; // [0, 11] + const unsigned __dy = __doy - (153 * __mp + 2)/5 + 1; // [1, 31] + const unsigned __mth = __mp + (__mp < 10 ? 3 : -9); // [1, 12] + return year_month_day{chrono::year{__yr + (__mth <= 2)}, chrono::month{__mth}, chrono::day{__dy}}; +} + +// https://howardhinnant.github.io/date_algorithms.html#days_from_civil +inline constexpr days year_month_day::__to_days() const noexcept +{ + static_assert(std::numeric_limits<unsigned>::digits >= 18, ""); + static_assert(std::numeric_limits<int>::digits >= 20 , ""); + + const int __yr = static_cast<int>(__y) - (__m <= February); + const unsigned __mth = static_cast<unsigned>(__m); + const unsigned __dy = static_cast<unsigned>(__d); + + const int __era = (__yr >= 0 ? __yr : __yr - 399) / 400; + const unsigned __yoe = static_cast<unsigned>(__yr - __era * 400); // [0, 399] + const unsigned __doy = (153 * (__mth + (__mth > 2 ? -3 : 9)) + 2) / 5 + __dy-1; // [0, 365] + const unsigned __doe = __yoe * 365 + __yoe/4 - __yoe/100 + __doy; // [0, 146096] + return days{__era * 146097 + static_cast<int>(__doe) - 719468}; +} + +inline constexpr +bool operator==(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); } + +inline constexpr +bool operator!=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ + if (__lhs.year() < __rhs.year()) return true; + if (__lhs.year() > __rhs.year()) return false; + if (__lhs.month() < __rhs.month()) return true; + if (__lhs.month() > __rhs.month()) return false; + return __lhs.day() < __rhs.day(); +} + +inline constexpr +bool operator> (const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr +year_month_day operator/(const year_month& __lhs, const day& __rhs) noexcept +{ return year_month_day{__lhs.year(), __lhs.month(), __rhs}; } + +inline constexpr +year_month_day operator/(const year_month& __lhs, int __rhs) noexcept +{ return __lhs / day(__rhs); } + +inline constexpr +year_month_day operator/(const year& __lhs, const month_day& __rhs) noexcept +{ return __lhs / __rhs.month() / __rhs.day(); } + +inline constexpr +year_month_day operator/(int __lhs, const month_day& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +inline constexpr +year_month_day operator/(const month_day& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +year_month_day operator/(const month_day& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +inline constexpr +year_month_day operator+(const year_month_day& __lhs, const months& __rhs) noexcept +{ return (__lhs.year()/__lhs.month() + __rhs)/__lhs.day(); } + +inline constexpr +year_month_day operator+(const months& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day operator-(const year_month_day& __lhs, const months& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr +year_month_day operator+(const year_month_day& __lhs, const years& __rhs) noexcept +{ return (__lhs.year() + __rhs) / __lhs.month() / __lhs.day(); } + +inline constexpr +year_month_day operator+(const years& __lhs, const year_month_day& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day operator-(const year_month_day& __lhs, const years& __rhs) noexcept +{ return __lhs + -__rhs; } + +inline constexpr year_month_day& year_month_day::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_day& year_month_day::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_day& year_month_day::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_day& year_month_day::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +class _LIBCPP_TYPE_VIS year_month_day_last { +private: + chrono::year __y; + chrono::month_day_last __mdl; +public: + constexpr year_month_day_last(const year& __yval, const month_day_last& __mdlval) noexcept + : __y{__yval}, __mdl{__mdlval} {} + + constexpr year_month_day_last& operator+=(const months& __m) noexcept; + constexpr year_month_day_last& operator-=(const months& __m) noexcept; + constexpr year_month_day_last& operator+=(const years& __y) noexcept; + constexpr year_month_day_last& operator-=(const years& __y) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __mdl.month(); } + inline constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl; } + constexpr chrono::day day() const noexcept; + inline constexpr operator sys_days() const noexcept { return sys_days{year()/month()/day()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{year()/month()/day()}; } + inline constexpr bool ok() const noexcept { return __y.ok() && __mdl.ok(); } +}; + +inline constexpr +chrono::day year_month_day_last::day() const noexcept +{ + constexpr chrono::day __d[] = + { + chrono::day(31), chrono::day(28), chrono::day(31), + chrono::day(30), chrono::day(31), chrono::day(30), + chrono::day(31), chrono::day(31), chrono::day(30), + chrono::day(31), chrono::day(30), chrono::day(31) + }; + return month() != February || !__y.is_leap() ? + __d[static_cast<unsigned>(month()) - 1] : chrono::day{29}; +} + +inline constexpr +bool operator==(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month_day_last() == __rhs.month_day_last(); } + +inline constexpr +bool operator!=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +bool operator< (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ + if (__lhs.year() < __rhs.year()) return true; + if (__lhs.year() > __rhs.year()) return false; + return __lhs.month_day_last() < __rhs.month_day_last(); +} + +inline constexpr +bool operator> (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs < __lhs; } + +inline constexpr +bool operator<=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__rhs < __lhs);} + +inline constexpr +bool operator>=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept +{ return !(__lhs < __rhs); } + +inline constexpr year_month_day_last operator/(const year_month& __lhs, last_spec) noexcept +{ return year_month_day_last{__lhs.year(), month_day_last{__lhs.month()}}; } + +inline constexpr year_month_day_last operator/(const year& __lhs, const month_day_last& __rhs) noexcept +{ return year_month_day_last{__lhs, __rhs}; } + +inline constexpr year_month_day_last operator/(int __lhs, const month_day_last& __rhs) noexcept +{ return year_month_day_last{year{__lhs}, __rhs}; } + +inline constexpr year_month_day_last operator/(const month_day_last& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr year_month_day_last operator/(const month_day_last& __lhs, int __rhs) noexcept +{ return year{__rhs} / __lhs; } + + +inline constexpr +year_month_day_last operator+(const year_month_day_last& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / last; } + +inline constexpr +year_month_day_last operator+(const months& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day_last operator-(const year_month_day_last& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr +year_month_day_last operator+(const year_month_day_last& __lhs, const years& __rhs) noexcept +{ return year_month_day_last{__lhs.year() + __rhs, __lhs.month_day_last()}; } + +inline constexpr +year_month_day_last operator+(const years& __lhs, const year_month_day_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_day_last operator-(const year_month_day_last& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr year_month_day_last& year_month_day_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_day_last& year_month_day_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_day_last& year_month_day_last::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_day_last& year_month_day_last::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +inline constexpr year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept + : __y{__ymdl.year()}, __m{__ymdl.month()}, __d{__ymdl.day()} {} + +inline constexpr bool year_month_day::ok() const noexcept +{ + if (!__y.ok() || !__m.ok()) return false; + return chrono::day{1} <= __d && __d <= (__y / __m / last).day(); +} + +class _LIBCPP_TYPE_VIS year_month_weekday { + chrono::year __y; + chrono::month __m; + chrono::weekday_indexed __wdi; +public: + year_month_weekday() = default; + constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval, + const chrono::weekday_indexed& __wdival) noexcept + : __y{__yval}, __m{__mval}, __wdi{__wdival} {} + constexpr year_month_weekday(const sys_days& __sysd) noexcept + : year_month_weekday(__from_days(__sysd.time_since_epoch())) {} + inline explicit constexpr year_month_weekday(const local_days& __locd) noexcept + : year_month_weekday(__from_days(__locd.time_since_epoch())) {} + constexpr year_month_weekday& operator+=(const months& m) noexcept; + constexpr year_month_weekday& operator-=(const months& m) noexcept; + constexpr year_month_weekday& operator+=(const years& y) noexcept; + constexpr year_month_weekday& operator-=(const years& y) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday weekday() const noexcept { return __wdi.weekday(); } + inline constexpr unsigned index() const noexcept { return __wdi.index(); } + inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; } + + inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + inline constexpr bool ok() const noexcept + { + if (!__y.ok() || !__m.ok() || !__wdi.ok()) return false; + // TODO: make sure it's a valid date + return true; + } + + static constexpr year_month_weekday __from_days(days __d) noexcept; + constexpr days __to_days() const noexcept; +}; + +inline constexpr +year_month_weekday year_month_weekday::__from_days(days __d) noexcept +{ + const sys_days __sysd{__d}; + const chrono::weekday __wd = chrono::weekday(__sysd); + const year_month_day __ymd = year_month_day(__sysd); + return year_month_weekday{__ymd.year(), __ymd.month(), + __wd[(static_cast<unsigned>(__ymd.day())-1)/7+1]}; +} + +inline constexpr +days year_month_weekday::__to_days() const noexcept +{ + const sys_days __sysd = sys_days(__y/__m/1); + return (__sysd + (__wdi.weekday() - chrono::weekday(__sysd) + days{(__wdi.index()-1)*7})) + .time_since_epoch(); +} + +inline constexpr +bool operator==(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } + +inline constexpr +bool operator!=(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept +{ return !(__lhs == __rhs); } + +inline constexpr +year_month_weekday operator/(const year_month& __lhs, const weekday_indexed& __rhs) noexcept +{ return year_month_weekday{__lhs.year(), __lhs.month(), __rhs}; } + +inline constexpr +year_month_weekday operator/(const year& __lhs, const month_weekday& __rhs) noexcept +{ return year_month_weekday{__lhs, __rhs.month(), __rhs.weekday_indexed()}; } + +inline constexpr +year_month_weekday operator/(int __lhs, const month_weekday& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +inline constexpr +year_month_weekday operator/(const month_weekday& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +year_month_weekday operator/(const month_weekday& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +inline constexpr +year_month_weekday operator+(const year_month_weekday& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_indexed(); } + +inline constexpr +year_month_weekday operator+(const months& __lhs, const year_month_weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday operator-(const year_month_weekday& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr +year_month_weekday operator+(const year_month_weekday& __lhs, const years& __rhs) noexcept +{ return year_month_weekday{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_indexed()}; } + +inline constexpr +year_month_weekday operator+(const years& __lhs, const year_month_weekday& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday operator-(const year_month_weekday& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + + +inline constexpr year_month_weekday& year_month_weekday::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_weekday& year_month_weekday::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_weekday& year_month_weekday::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_weekday& year_month_weekday::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +class _LIBCPP_TYPE_VIS year_month_weekday_last { +private: + chrono::year __y; + chrono::month __m; + chrono::weekday_last __wdl; +public: + constexpr year_month_weekday_last(const chrono::year& __yval, const chrono::month& __mval, + const chrono::weekday_last& __wdlval) noexcept + : __y{__yval}, __m{__mval}, __wdl{__wdlval} {} + constexpr year_month_weekday_last& operator+=(const months& __dm) noexcept; + constexpr year_month_weekday_last& operator-=(const months& __dm) noexcept; + constexpr year_month_weekday_last& operator+=(const years& __dy) noexcept; + constexpr year_month_weekday_last& operator-=(const years& __dy) noexcept; + + inline constexpr chrono::year year() const noexcept { return __y; } + inline constexpr chrono::month month() const noexcept { return __m; } + inline constexpr chrono::weekday weekday() const noexcept { return __wdl.weekday(); } + inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; } + inline constexpr operator sys_days() const noexcept { return sys_days{__to_days()}; } + inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; } + inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok() && __wdl.ok(); } + + constexpr days __to_days() const noexcept; + +}; + +inline constexpr +days year_month_weekday_last::__to_days() const noexcept +{ + const sys_days __last = sys_days{__y/__m/last}; + return (__last - (chrono::weekday{__last} - __wdl.weekday())).time_since_epoch(); + +} + +inline constexpr +bool operator==(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } + +inline constexpr +bool operator!=(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return !(__lhs == __rhs); } + + +inline constexpr +year_month_weekday_last operator/(const year_month& __lhs, const weekday_last& __rhs) noexcept +{ return year_month_weekday_last{__lhs.year(), __lhs.month(), __rhs}; } + +inline constexpr +year_month_weekday_last operator/(const year& __lhs, const month_weekday_last& __rhs) noexcept +{ return year_month_weekday_last{__lhs, __rhs.month(), __rhs.weekday_last()}; } + +inline constexpr +year_month_weekday_last operator/(int __lhs, const month_weekday_last& __rhs) noexcept +{ return year(__lhs) / __rhs; } + +inline constexpr +year_month_weekday_last operator/(const month_weekday_last& __lhs, const year& __rhs) noexcept +{ return __rhs / __lhs; } + +inline constexpr +year_month_weekday_last operator/(const month_weekday_last& __lhs, int __rhs) noexcept +{ return year(__rhs) / __lhs; } + + +inline constexpr +year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const months& __rhs) noexcept +{ return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_last(); } + +inline constexpr +year_month_weekday_last operator+(const months& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const months& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr +year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const years& __rhs) noexcept +{ return year_month_weekday_last{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_last()}; } + +inline constexpr +year_month_weekday_last operator+(const years& __lhs, const year_month_weekday_last& __rhs) noexcept +{ return __rhs + __lhs; } + +inline constexpr +year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const years& __rhs) noexcept +{ return __lhs + (-__rhs); } + +inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; } +inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; } +inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } +inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +#endif // _LIBCPP_STD_VER > 17 } // chrono #if _LIBCPP_STD_VER > 11 // Suffixes for duration literals [time.duration.literals] inline namespace literals -{ +{ inline namespace chrono_literals { @@ -1633,7 +2793,7 @@ inline namespace literals { return chrono::duration<long double, micro> (__us); } - + constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) { @@ -1645,6 +2805,17 @@ inline namespace literals return chrono::duration<long double, nano> (__ns); } +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX20_CHRONO_LITERALS) + constexpr chrono::day operator ""d(unsigned long long __d) noexcept + { + return chrono::day(static_cast<unsigned>(__d)); + } + + constexpr chrono::year operator ""y(unsigned long long __y) noexcept + { + return chrono::year(static_cast<int>(__y)); + } +#endif }} namespace chrono { // hoist the literals into namespace std::chrono @@ -1655,6 +2826,40 @@ namespace chrono { // hoist the literals into namespace std::chrono _LIBCPP_END_NAMESPACE_STD +#ifndef _LIBCPP_CXX03_LANG +_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)); + } +}; +_LIBCPP_END_NAMESPACE_FILESYSTEM +#endif // !_LIBCPP_CXX03_LANG + _LIBCPP_POP_MACROS #endif // _LIBCPP_CHRONO diff --git a/lib/libcxx/include/cmath b/lib/libcxx/include/cmath index ffb1c46c7b6..f5f62adcfb8 100644 --- a/lib/libcxx/include/cmath +++ b/lib/libcxx/include/cmath @@ -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 diff --git a/lib/libcxx/include/complex b/lib/libcxx/include/complex index d692ee31920..8cf6a946d71 100644 --- a/lib/libcxx/include/complex +++ b/lib/libcxx/include/complex @@ -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 diff --git a/lib/libcxx/include/cstddef b/lib/libcxx/include/cstddef index adeefdac9be..b4c42b19ddb 100644 --- a/lib/libcxx/include/cstddef +++ b/lib/libcxx/include/cstddef @@ -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 diff --git a/lib/libcxx/include/deque b/lib/libcxx/include/deque index bfbd3a5ef54..6f7d04be52b 100644 --- a/lib/libcxx/include/deque +++ b/lib/libcxx/include/deque @@ -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 diff --git a/lib/libcxx/include/exception b/lib/libcxx/include/exception index b517486b5a8..fdd83d10c3d 100644 --- a/lib/libcxx/include/exception +++ b/lib/libcxx/include/exception @@ -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)); diff --git a/lib/libcxx/include/experimental/any b/lib/libcxx/include/experimental/any index 1dcdd0f25ec..d9c95342589 100644 --- a/lib/libcxx/include/experimental/any +++ b/lib/libcxx/include/experimental/any @@ -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 diff --git a/lib/libcxx/include/experimental/chrono b/lib/libcxx/include/experimental/chrono index 591cf7160c1..30c7e4a9d5a 100644 --- a/lib/libcxx/include/experimental/chrono +++ b/lib/libcxx/include/experimental/chrono @@ -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 diff --git a/lib/libcxx/include/experimental/coroutine b/lib/libcxx/include/experimental/coroutine index 1eb224a535a..7cb39b81b48 100644 --- a/lib/libcxx/include/experimental/coroutine +++ b/lib/libcxx/include/experimental/coroutine @@ -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; } diff --git a/lib/libcxx/include/experimental/memory_resource b/lib/libcxx/include/experimental/memory_resource index 221ce5b8eac..83781d46203 100644 --- a/lib/libcxx/include/experimental/memory_resource +++ b/lib/libcxx/include/experimental/memory_resource @@ -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 diff --git a/lib/libcxx/include/experimental/numeric b/lib/libcxx/include/experimental/numeric index 14a664011b5..19c65313f0f 100644 --- a/lib/libcxx/include/experimental/numeric +++ b/lib/libcxx/include/experimental/numeric @@ -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 diff --git a/lib/libcxx/include/experimental/optional b/lib/libcxx/include/experimental/optional index d68cefdf6c1..6eb4a2618d2 100644 --- a/lib/libcxx/include/experimental/optional +++ b/lib/libcxx/include/experimental/optional @@ -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 diff --git a/lib/libcxx/include/experimental/ratio b/lib/libcxx/include/experimental/ratio index 9c2bf2e4624..52c12004dba 100644 --- a/lib/libcxx/include/experimental/ratio +++ b/lib/libcxx/include/experimental/ratio @@ -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 diff --git a/lib/libcxx/include/experimental/string_view b/lib/libcxx/include/experimental/string_view index f13bff54d53..100bdfe7273 100644 --- a/lib/libcxx/include/experimental/string_view +++ b/lib/libcxx/include/experimental/string_view @@ -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 diff --git a/lib/libcxx/include/experimental/system_error b/lib/libcxx/include/experimental/system_error index 7937357fa14..1cf84ee0125 100644 --- a/lib/libcxx/include/experimental/system_error +++ b/lib/libcxx/include/experimental/system_error @@ -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 diff --git a/lib/libcxx/include/experimental/tuple b/lib/libcxx/include/experimental/tuple index 1f37a6293ba..6d71bb559b0 100644 --- a/lib/libcxx/include/experimental/tuple +++ b/lib/libcxx/include/experimental/tuple @@ -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 diff --git a/lib/libcxx/include/filesystem b/lib/libcxx/include/filesystem index aa1d7180072..af713a06358 100644 --- a/lib/libcxx/include/filesystem +++ b/lib/libcxx/include/filesystem @@ -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 diff --git a/lib/libcxx/include/forward_list b/lib/libcxx/include/forward_list index 571afdc925b..b506acd1ff2 100644 --- a/lib/libcxx/include/forward_list +++ b/lib/libcxx/include/forward_list @@ -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 diff --git a/lib/libcxx/include/fstream b/lib/libcxx/include/fstream index 332b4747c1a..711e484e2dc 100644 --- a/lib/libcxx/include/fstream +++ b/lib/libcxx/include/fstream @@ -702,6 +702,7 @@ basic_filebuf<_CharT, _Traits>::close() __file_ = 0; else __rt = 0; + setbuf(0, 0); } return __rt; } diff --git a/lib/libcxx/include/functional b/lib/libcxx/include/functional index 6b70f731e1c..95491879b0c 100644 --- a/lib/libcxx/include/functional +++ b/lib/libcxx/include/functional @@ -68,6 +68,11 @@ template <class T> reference_wrapper<const T> cref(const T& t) noexcept; template <class T> void cref(const T&& t) = delete; template <class T> reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept; +template <class T> struct unwrap_reference; // since C++20 +template <class T> struct unwrap_ref_decay : unwrap_reference<decay_t<T>> { }; // since C++20 +template <class T> using unwrap_reference_t = typename unwrap_reference<T>::type; // since C++20 +template <class T> using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type; // since C++20 + template <class T> // <class T=void> in C++14 struct plus : binary_function<T, T, T> { @@ -183,7 +188,7 @@ struct bit_xor : unary_function<T, bool> }; template <class Predicate> -class unary_negate +class unary_negate // deprecated in C++17 : public unary_function<typename Predicate::argument_type, bool> { public: @@ -191,10 +196,11 @@ public: bool operator()(const typename Predicate::argument_type& x) const; }; -template <class Predicate> unary_negate<Predicate> not1(const Predicate& pred); +template <class Predicate> // deprecated in C++17 +unary_negate<Predicate> not1(const Predicate& pred); template <class Predicate> -class binary_negate +class binary_negate // deprecated in C++17 : public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool> @@ -205,7 +211,8 @@ public: const typename Predicate::second_argument_type& y) const; }; -template <class Predicate> binary_negate<Predicate> not2(const Predicate& pred); +template <class Predicate> // deprecated in C++17 +binary_negate<Predicate> not2(const Predicate& pred); template <class F> unspecified not_fn(F&& f); // C++17 @@ -487,6 +494,7 @@ POLICY: For non-variadic implementations, the number of arguments is limited #include <memory> #include <tuple> #include <utility> +#include <version> #include <__functional_base> @@ -980,7 +988,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_not<void> #endif template <class _Predicate> -class _LIBCPP_TEMPLATE_VIS unary_negate +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 unary_negate : public unary_function<typename _Predicate::argument_type, bool> { _Predicate __pred_; @@ -994,19 +1002,19 @@ public: }; template <class _Predicate> -inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY unary_negate<_Predicate> not1(const _Predicate& __pred) {return unary_negate<_Predicate>(__pred);} template <class _Predicate> -class _LIBCPP_TEMPLATE_VIS binary_negate +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 binary_negate : public binary_function<typename _Predicate::first_argument_type, typename _Predicate::second_argument_type, bool> { _Predicate __pred_; public: - _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11 + _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11 binary_negate(const _Predicate& __pred) : __pred_(__pred) {} _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY @@ -1016,13 +1024,13 @@ public: }; template <class _Predicate> -inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX17 inline _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY binary_negate<_Predicate> not2(const _Predicate& __pred) {return binary_negate<_Predicate>(__pred);} #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template <class __Operation> -class _LIBCPP_TEMPLATE_VIS binder1st +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder1st : public unary_function<typename __Operation::second_argument_type, typename __Operation::result_type> { @@ -1042,13 +1050,13 @@ public: }; template <class __Operation, class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY binder1st<__Operation> bind1st(const __Operation& __op, const _Tp& __x) {return binder1st<__Operation>(__op, __x);} template <class __Operation> -class _LIBCPP_TEMPLATE_VIS binder2nd +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder2nd : public unary_function<typename __Operation::first_argument_type, typename __Operation::result_type> { @@ -1068,13 +1076,13 @@ public: }; template <class __Operation, class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY binder2nd<__Operation> bind2nd(const __Operation& __op, const _Tp& __x) {return binder2nd<__Operation>(__op, __x);} template <class _Arg, class _Result> -class _LIBCPP_TEMPLATE_VIS pointer_to_unary_function +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function : public unary_function<_Arg, _Result> { _Result (*__f_)(_Arg); @@ -1086,13 +1094,13 @@ public: }; template <class _Arg, class _Result> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY pointer_to_unary_function<_Arg,_Result> ptr_fun(_Result (*__f)(_Arg)) {return pointer_to_unary_function<_Arg,_Result>(__f);} template <class _Arg1, class _Arg2, class _Result> -class _LIBCPP_TEMPLATE_VIS pointer_to_binary_function +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function : public binary_function<_Arg1, _Arg2, _Result> { _Result (*__f_)(_Arg1, _Arg2); @@ -1104,13 +1112,14 @@ public: }; template <class _Arg1, class _Arg2, class _Result> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY pointer_to_binary_function<_Arg1,_Arg2,_Result> ptr_fun(_Result (*__f)(_Arg1,_Arg2)) {return pointer_to_binary_function<_Arg1,_Arg2,_Result>(__f);} template<class _Sp, class _Tp> -class _LIBCPP_TEMPLATE_VIS mem_fun_t : public unary_function<_Tp*, _Sp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_t + : public unary_function<_Tp*, _Sp> { _Sp (_Tp::*__p_)(); public: @@ -1121,7 +1130,8 @@ public: }; template<class _Sp, class _Tp, class _Ap> -class _LIBCPP_TEMPLATE_VIS mem_fun1_t : public binary_function<_Tp*, _Ap, _Sp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_t + : public binary_function<_Tp*, _Ap, _Sp> { _Sp (_Tp::*__p_)(_Ap); public: @@ -1132,19 +1142,20 @@ public: }; template<class _Sp, class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY mem_fun_t<_Sp,_Tp> mem_fun(_Sp (_Tp::*__f)()) {return mem_fun_t<_Sp,_Tp>(__f);} template<class _Sp, class _Tp, class _Ap> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY mem_fun1_t<_Sp,_Tp,_Ap> mem_fun(_Sp (_Tp::*__f)(_Ap)) {return mem_fun1_t<_Sp,_Tp,_Ap>(__f);} template<class _Sp, class _Tp> -class _LIBCPP_TEMPLATE_VIS mem_fun_ref_t : public unary_function<_Tp, _Sp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun_ref_t + : public unary_function<_Tp, _Sp> { _Sp (_Tp::*__p_)(); public: @@ -1155,7 +1166,8 @@ public: }; template<class _Sp, class _Tp, class _Ap> -class _LIBCPP_TEMPLATE_VIS mem_fun1_ref_t : public binary_function<_Tp, _Ap, _Sp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 mem_fun1_ref_t + : public binary_function<_Tp, _Ap, _Sp> { _Sp (_Tp::*__p_)(_Ap); public: @@ -1166,19 +1178,20 @@ public: }; template<class _Sp, class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY mem_fun_ref_t<_Sp,_Tp> mem_fun_ref(_Sp (_Tp::*__f)()) {return mem_fun_ref_t<_Sp,_Tp>(__f);} template<class _Sp, class _Tp, class _Ap> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY mem_fun1_ref_t<_Sp,_Tp,_Ap> mem_fun_ref(_Sp (_Tp::*__f)(_Ap)) {return mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} template <class _Sp, class _Tp> -class _LIBCPP_TEMPLATE_VIS const_mem_fun_t : public unary_function<const _Tp*, _Sp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_t + : public unary_function<const _Tp*, _Sp> { _Sp (_Tp::*__p_)() const; public: @@ -1189,7 +1202,8 @@ public: }; template <class _Sp, class _Tp, class _Ap> -class _LIBCPP_TEMPLATE_VIS const_mem_fun1_t : public binary_function<const _Tp*, _Ap, _Sp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t + : public binary_function<const _Tp*, _Ap, _Sp> { _Sp (_Tp::*__p_)(_Ap) const; public: @@ -1200,19 +1214,20 @@ public: }; template <class _Sp, class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY const_mem_fun_t<_Sp,_Tp> mem_fun(_Sp (_Tp::*__f)() const) {return const_mem_fun_t<_Sp,_Tp>(__f);} template <class _Sp, class _Tp, class _Ap> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY const_mem_fun1_t<_Sp,_Tp,_Ap> mem_fun(_Sp (_Tp::*__f)(_Ap) const) {return const_mem_fun1_t<_Sp,_Tp,_Ap>(__f);} template <class _Sp, class _Tp> -class _LIBCPP_TEMPLATE_VIS const_mem_fun_ref_t : public unary_function<_Tp, _Sp> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun_ref_t + : public unary_function<_Tp, _Sp> { _Sp (_Tp::*__p_)() const; public: @@ -1223,7 +1238,7 @@ public: }; template <class _Sp, class _Tp, class _Ap> -class _LIBCPP_TEMPLATE_VIS const_mem_fun1_ref_t +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_ref_t : public binary_function<_Tp, _Ap, _Sp> { _Sp (_Tp::*__p_)(_Ap) const; @@ -1235,13 +1250,13 @@ public: }; template <class _Sp, class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY const_mem_fun_ref_t<_Sp,_Tp> mem_fun_ref(_Sp (_Tp::*__f)() const) {return const_mem_fun_ref_t<_Sp,_Tp>(__f);} template <class _Sp, class _Tp, class _Ap> -inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY const_mem_fun1_ref_t<_Sp,_Tp,_Ap> mem_fun_ref(_Sp (_Tp::*__f)(_Ap) const) {return const_mem_fun1_ref_t<_Sp,_Tp,_Ap>(__f);} @@ -1405,7 +1420,7 @@ void __throw_bad_function_call() #ifndef _LIBCPP_NO_EXCEPTIONS throw bad_function_call(); #else - _VSTD::abort(); + _VSTD::abort(); #endif } @@ -1458,6 +1473,81 @@ bool __not_null(function<_Fp> const& __f) { return !!__f; } namespace __function { +// __alloc_func holds a functor and an allocator. + +template <class _Fp, class _Ap, class _FB> class __alloc_func; + +template <class _Fp, class _Ap, class _Rp, class... _ArgTypes> +class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> +{ + __compressed_pair<_Fp, _Ap> __f_; + + public: + typedef _Fp _Target; + typedef _Ap _Alloc; + + _LIBCPP_INLINE_VISIBILITY + const _Target& __target() const { return __f_.first(); } + + _LIBCPP_INLINE_VISIBILITY + const _Alloc& __allocator() const { return __f_.second(); } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(_Target&& __f) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), + _VSTD::forward_as_tuple()) + { + } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(const _Target& __f, const _Alloc& __a) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), + _VSTD::forward_as_tuple(__a)) + { + } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(const _Target& __f, _Alloc&& __a) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), + _VSTD::forward_as_tuple(_VSTD::move(__a))) + { + } + + _LIBCPP_INLINE_VISIBILITY + explicit __alloc_func(_Target&& __f, _Alloc&& __a) + : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), + _VSTD::forward_as_tuple(_VSTD::move(__a))) + { + } + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes&&... __arg) + { + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), + _VSTD::forward<_ArgTypes>(__arg)...); + } + + _LIBCPP_INLINE_VISIBILITY + __alloc_func* __clone() const + { + typedef allocator_traits<_Alloc> __alloc_traits; + typedef + typename __rebind_alloc_helper<__alloc_traits, __alloc_func>::type + _AA; + _AA __a(__f_.second()); + typedef __allocator_destructor<_AA> _Dp; + unique_ptr<__alloc_func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new ((void*)__hold.get()) __alloc_func(__f_.first(), _Alloc(__a)); + return __hold.release(); + } + + _LIBCPP_INLINE_VISIBILITY + void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); } +}; + +// __base provides an abstract interface for copyable functors. + template<class _Fp> class __base; template<class _Rp, class ..._ArgTypes> @@ -1479,37 +1569,37 @@ public: #endif // _LIBCPP_NO_RTTI }; +// __func implements __base for a given functor type. + template<class _FD, class _Alloc, class _FB> class __func; template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> class __func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __base<_Rp(_ArgTypes...)> { - __compressed_pair<_Fp, _Alloc> __f_; + __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> __f_; public: _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp&& __f) - : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), - _VSTD::forward_as_tuple()) {} + : __f_(_VSTD::move(__f)) {} + _LIBCPP_INLINE_VISIBILITY explicit __func(const _Fp& __f, const _Alloc& __a) - : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), - _VSTD::forward_as_tuple(__a)) {} + : __f_(__f, __a) {} _LIBCPP_INLINE_VISIBILITY explicit __func(const _Fp& __f, _Alloc&& __a) - : __f_(piecewise_construct, _VSTD::forward_as_tuple(__f), - _VSTD::forward_as_tuple(_VSTD::move(__a))) {} + : __f_(__f, _VSTD::move(__a)) {} _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp&& __f, _Alloc&& __a) - : __f_(piecewise_construct, _VSTD::forward_as_tuple(_VSTD::move(__f)), - _VSTD::forward_as_tuple(_VSTD::move(__a))) {} + : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} + virtual __base<_Rp(_ArgTypes...)>* __clone() const; virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; virtual void destroy() _NOEXCEPT; virtual void destroy_deallocate() _NOEXCEPT; - virtual _Rp operator()(_ArgTypes&& ... __arg); + virtual _Rp operator()(_ArgTypes&&... __arg); #ifndef _LIBCPP_NO_RTTI virtual const void* target(const type_info&) const _NOEXCEPT; virtual const std::type_info& target_type() const _NOEXCEPT; @@ -1522,10 +1612,10 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone() const { typedef allocator_traits<_Alloc> __alloc_traits; typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; - _Ap __a(__f_.second()); + _Ap __a(__f_.__allocator()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new (__hold.get()) __func(__f_.first(), _Alloc(__a)); + ::new ((void*)__hold.get()) __func(__f_.__target(), _Alloc(__a)); return __hold.release(); } @@ -1533,14 +1623,14 @@ template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__clone(__base<_Rp(_ArgTypes...)>* __p) const { - ::new (__p) __func(__f_.first(), __f_.second()); + ::new (__p) __func(__f_.__target(), __f_.__allocator()); } template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> void __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() _NOEXCEPT { - __f_.~__compressed_pair<_Fp, _Alloc>(); + __f_.destroy(); } template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> @@ -1549,8 +1639,8 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate() _NOEXCEPT { typedef allocator_traits<_Alloc> __alloc_traits; typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; - _Ap __a(__f_.second()); - __f_.~__compressed_pair<_Fp, _Alloc>(); + _Ap __a(__f_.__allocator()); + __f_.destroy(); __a.deallocate(this, 1); } @@ -1558,8 +1648,7 @@ template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> _Rp __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) { - typedef __invoke_void_return_wrapper<_Rp> _Invoker; - return _Invoker::__call(__f_.first(), _VSTD::forward<_ArgTypes>(__arg)...); + return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } #ifndef _LIBCPP_NO_RTTI @@ -1569,7 +1658,7 @@ const void* __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target(const type_info& __ti) const _NOEXCEPT { if (__ti == typeid(_Fp)) - return &__f_.first(); + return &__f_.__target(); return (const void*)0; } @@ -1582,6 +1671,493 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT #endif // _LIBCPP_NO_RTTI +// __value_func creates a value-type from a __func. + +template <class _Fp> class __value_func; + +template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> +{ + typename aligned_storage<3 * sizeof(void*)>::type __buf_; + + typedef __base<_Rp(_ArgTypes...)> __func; + __func* __f_; + + _LIBCPP_NO_CFI static __func* __as_base(void* p) + { + return reinterpret_cast<__func*>(p); + } + + public: + _LIBCPP_INLINE_VISIBILITY + __value_func() _NOEXCEPT : __f_(0) {} + + template <class _Fp, class _Alloc> + _LIBCPP_INLINE_VISIBILITY __value_func(_Fp&& __f, const _Alloc __a) + : __f_(0) + { + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; + typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type + _FunAlloc; + + if (__function::__not_null(__f)) + { + _FunAlloc __af(__a); + if (sizeof(_Fun) <= sizeof(__buf_) && + is_nothrow_copy_constructible<_Fp>::value && + is_nothrow_copy_constructible<_FunAlloc>::value) + { + __f_ = + ::new ((void*)&__buf_) _Fun(_VSTD::move(__f), _Alloc(__af)); + } + else + { + typedef __allocator_destructor<_FunAlloc> _Dp; + unique_ptr<__func, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); + ::new ((void*)__hold.get()) _Fun(_VSTD::move(__f), _Alloc(__a)); + __f_ = __hold.release(); + } + } + } + + _LIBCPP_INLINE_VISIBILITY + __value_func(const __value_func& __f) + { + if (__f.__f_ == 0) + __f_ = 0; + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f_ = __as_base(&__buf_); + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); + } + + _LIBCPP_INLINE_VISIBILITY + __value_func(__value_func&& __f) _NOEXCEPT + { + if (__f.__f_ == 0) + __f_ = 0; + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f_ = __as_base(&__buf_); + __f.__f_->__clone(__f_); + } + else + { + __f_ = __f.__f_; + __f.__f_ = 0; + } + } + + _LIBCPP_INLINE_VISIBILITY + ~__value_func() + { + if ((void*)__f_ == &__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); + } + + _LIBCPP_INLINE_VISIBILITY + __value_func& operator=(__value_func&& __f) + { + *this = nullptr; + if (__f.__f_ == 0) + __f_ = 0; + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f_ = __as_base(&__buf_); + __f.__f_->__clone(__f_); + } + else + { + __f_ = __f.__f_; + __f.__f_ = 0; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __value_func& operator=(nullptr_t) + { + __func* __f = __f_; + __f_ = 0; + if ((void*)__f == &__buf_) + __f->destroy(); + else if (__f) + __f->destroy_deallocate(); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes&&... __args) const + { + if (__f_ == 0) + __throw_bad_function_call(); + return (*__f_)(_VSTD::forward<_ArgTypes>(__args)...); + } + + _LIBCPP_INLINE_VISIBILITY + void swap(__value_func& __f) _NOEXCEPT + { + if (&__f == this) + return; + if ((void*)__f_ == &__buf_ && (void*)__f.__f_ == &__f.__buf_) + { + typename aligned_storage<sizeof(__buf_)>::type __tempbuf; + __func* __t = __as_base(&__tempbuf); + __f_->__clone(__t); + __f_->destroy(); + __f_ = 0; + __f.__f_->__clone(__as_base(&__buf_)); + __f.__f_->destroy(); + __f.__f_ = 0; + __f_ = __as_base(&__buf_); + __t->__clone(__as_base(&__f.__buf_)); + __t->destroy(); + __f.__f_ = __as_base(&__f.__buf_); + } + else if ((void*)__f_ == &__buf_) + { + __f_->__clone(__as_base(&__f.__buf_)); + __f_->destroy(); + __f_ = __f.__f_; + __f.__f_ = __as_base(&__f.__buf_); + } + else if ((void*)__f.__f_ == &__f.__buf_) + { + __f.__f_->__clone(__as_base(&__buf_)); + __f.__f_->destroy(); + __f.__f_ = __f_; + __f_ = __as_base(&__buf_); + } + else + _VSTD::swap(__f_, __f.__f_); + } + + _LIBCPP_INLINE_VISIBILITY + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT { return __f_ != 0; } + +#ifndef _LIBCPP_NO_RTTI + _LIBCPP_INLINE_VISIBILITY + const std::type_info& target_type() const _NOEXCEPT + { + if (__f_ == 0) + return typeid(void); + return __f_->target_type(); + } + + template <typename _Tp> + _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT + { + if (__f_ == 0) + return 0; + return (const _Tp*)__f_->target(typeid(_Tp)); + } +#endif // _LIBCPP_NO_RTTI +}; + +// Storage for a functor object, to be used with __policy to manage copy and +// destruction. +union __policy_storage +{ + mutable char __small[sizeof(void*) * 2]; + void* __large; +}; + +// True if _Fun can safely be held in __policy_storage.__small. +template <typename _Fun> +struct __use_small_storage + : public _VSTD::integral_constant< + bool, sizeof(_Fun) <= sizeof(__policy_storage) && + _LIBCPP_ALIGNOF(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage) && + _VSTD::is_trivially_copy_constructible<_Fun>::value && + _VSTD::is_trivially_destructible<_Fun>::value> {}; + +// Policy contains information about how to copy, destroy, and move the +// underlying functor. You can think of it as a vtable of sorts. +struct __policy +{ + // Used to copy or destroy __large values. null for trivial objects. + void* (*const __clone)(const void*); + void (*const __destroy)(void*); + + // True if this is the null policy (no value). + const bool __is_null; + + // The target type. May be null if RTTI is disabled. + const std::type_info* const __type_info; + + // Returns a pointer to a static policy object suitable for the functor + // type. + template <typename _Fun> + _LIBCPP_INLINE_VISIBILITY static const __policy* __create() + { + return __choose_policy<_Fun>(__use_small_storage<_Fun>()); + } + + _LIBCPP_INLINE_VISIBILITY + static const __policy* __create_empty() + { + static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, + true, +#ifndef _LIBCPP_NO_RTTI + &typeid(void) +#else + nullptr +#endif + }; + return &__policy_; + } + + private: + template <typename _Fun> static void* __large_clone(const void* __s) + { + const _Fun* __f = static_cast<const _Fun*>(__s); + return __f->__clone(); + } + + template <typename _Fun> static void __large_destroy(void* __s) + { + typedef allocator_traits<typename _Fun::_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type + _FunAlloc; + _Fun* __f = static_cast<_Fun*>(__s); + _FunAlloc __a(__f->__allocator()); + __f->destroy(); + __a.deallocate(__f, 1); + } + + template <typename _Fun> + _LIBCPP_INLINE_VISIBILITY static const __policy* + __choose_policy(/* is_small = */ false_type) + { + static const _LIBCPP_CONSTEXPR __policy __policy_ = { + &__large_clone<_Fun>, &__large_destroy<_Fun>, false, +#ifndef _LIBCPP_NO_RTTI + &typeid(typename _Fun::_Target) +#else + nullptr +#endif + }; + return &__policy_; + } + + template <typename _Fun> + _LIBCPP_INLINE_VISIBILITY static const __policy* + __choose_policy(/* is_small = */ true_type) + { + static const _LIBCPP_CONSTEXPR __policy __policy_ = { + nullptr, nullptr, false, +#ifndef _LIBCPP_NO_RTTI + &typeid(typename _Fun::_Target) +#else + nullptr +#endif + }; + return &__policy_; + } +}; + +// Used to choose between perfect forwarding or pass-by-value. Pass-by-value is +// faster for types that can be passed in registers. +template <typename _Tp> +using __fast_forward = + typename _VSTD::conditional<_VSTD::is_scalar<_Tp>::value, _Tp, _Tp&&>::type; + +// __policy_invoker calls an instance of __alloc_func held in __policy_storage. + +template <class _Fp> struct __policy_invoker; + +template <class _Rp, class... _ArgTypes> +struct __policy_invoker<_Rp(_ArgTypes...)> +{ + typedef _Rp (*__Call)(const __policy_storage*, + __fast_forward<_ArgTypes>...); + + __Call __call_; + + // Creates an invoker that throws bad_function_call. + _LIBCPP_INLINE_VISIBILITY + __policy_invoker() : __call_(&__call_empty) {} + + // Creates an invoker that calls the given instance of __func. + template <typename _Fun> + _LIBCPP_INLINE_VISIBILITY static __policy_invoker __create() + { + return __policy_invoker(&__call_impl<_Fun>); + } + + private: + _LIBCPP_INLINE_VISIBILITY + explicit __policy_invoker(__Call __c) : __call_(__c) {} + + static _Rp __call_empty(const __policy_storage*, + __fast_forward<_ArgTypes>...) + { + __throw_bad_function_call(); + } + + template <typename _Fun> + static _Rp __call_impl(const __policy_storage* __buf, + __fast_forward<_ArgTypes>... __args) + { + _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value + ? &__buf->__small + : __buf->__large); + return (*__f)(_VSTD::forward<_ArgTypes>(__args)...); + } +}; + +// __policy_func uses a __policy and __policy_invoker to create a type-erased, +// copyable functor. + +template <class _Fp> class __policy_func; + +template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> +{ + // Inline storage for small objects. + __policy_storage __buf_; + + // Calls the value stored in __buf_. This could technically be part of + // policy, but storing it here eliminates a level of indirection inside + // operator(). + typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker; + __invoker __invoker_; + + // The policy that describes how to move / copy / destroy __buf_. Never + // null, even if the function is empty. + const __policy* __policy_; + + public: + _LIBCPP_INLINE_VISIBILITY + __policy_func() : __policy_(__policy::__create_empty()) {} + + template <class _Fp, class _Alloc> + _LIBCPP_INLINE_VISIBILITY __policy_func(_Fp&& __f, const _Alloc& __a) + : __policy_(__policy::__create_empty()) + { + typedef __alloc_func<_Fp, _Alloc, _Rp(_ArgTypes...)> _Fun; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, _Fun>::type + _FunAlloc; + + if (__function::__not_null(__f)) + { + __invoker_ = __invoker::template __create<_Fun>(); + __policy_ = __policy::__create<_Fun>(); + + _FunAlloc __af(__a); + if (__use_small_storage<_Fun>()) + { + ::new ((void*)&__buf_.__small) + _Fun(_VSTD::move(__f), _Alloc(__af)); + } + else + { + typedef __allocator_destructor<_FunAlloc> _Dp; + unique_ptr<_Fun, _Dp> __hold(__af.allocate(1), _Dp(__af, 1)); + ::new ((void*)__hold.get()) + _Fun(_VSTD::move(__f), _Alloc(__af)); + __buf_.__large = __hold.release(); + } + } + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func(const __policy_func& __f) + : __buf_(__f.__buf_), __invoker_(__f.__invoker_), + __policy_(__f.__policy_) + { + if (__policy_->__clone) + __buf_.__large = __policy_->__clone(__f.__buf_.__large); + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func(__policy_func&& __f) + : __buf_(__f.__buf_), __invoker_(__f.__invoker_), + __policy_(__f.__policy_) + { + if (__policy_->__destroy) + { + __f.__policy_ = __policy::__create_empty(); + __f.__invoker_ = __invoker(); + } + } + + _LIBCPP_INLINE_VISIBILITY + ~__policy_func() + { + if (__policy_->__destroy) + __policy_->__destroy(__buf_.__large); + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func& operator=(__policy_func&& __f) + { + *this = nullptr; + __buf_ = __f.__buf_; + __invoker_ = __f.__invoker_; + __policy_ = __f.__policy_; + __f.__policy_ = __policy::__create_empty(); + __f.__invoker_ = __invoker(); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __policy_func& operator=(nullptr_t) + { + const __policy* __p = __policy_; + __policy_ = __policy::__create_empty(); + __invoker_ = __invoker(); + if (__p->__destroy) + __p->__destroy(__buf_.__large); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + _Rp operator()(_ArgTypes&&... __args) const + { + return __invoker_.__call_(_VSTD::addressof(__buf_), + _VSTD::forward<_ArgTypes>(__args)...); + } + + _LIBCPP_INLINE_VISIBILITY + void swap(__policy_func& __f) + { + _VSTD::swap(__invoker_, __f.__invoker_); + _VSTD::swap(__policy_, __f.__policy_); + _VSTD::swap(__buf_, __f.__buf_); + } + + _LIBCPP_INLINE_VISIBILITY + explicit operator bool() const _NOEXCEPT + { + return !__policy_->__is_null; + } + +#ifndef _LIBCPP_NO_RTTI + _LIBCPP_INLINE_VISIBILITY + const std::type_info& target_type() const _NOEXCEPT + { + return *__policy_->__type_info; + } + + template <typename _Tp> + _LIBCPP_INLINE_VISIBILITY const _Tp* target() const _NOEXCEPT + { + if (__policy_->__is_null || typeid(_Tp) != *__policy_->__type_info) + return nullptr; + if (__policy_->__clone) // Out of line storage. + return reinterpret_cast<const _Tp*>(__buf_.__large); + else + return reinterpret_cast<const _Tp*>(&__buf_.__small); + } +#endif // _LIBCPP_NO_RTTI +}; + } // __function template<class _Rp, class ..._ArgTypes> @@ -1589,13 +2165,13 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> : public __function::__maybe_derive_from_unary_function<_Rp(_ArgTypes...)>, public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> { - typedef __function::__base<_Rp(_ArgTypes...)> __base; - typename aligned_storage<3*sizeof(void*)>::type __buf_; - __base* __f_; +#ifndef _LIBCPP_ABI_OPTIMIZED_FUNCTION + typedef __function::__value_func<_Rp(_ArgTypes...)> __func; +#else + typedef __function::__policy_func<_Rp(_ArgTypes...)> __func; +#endif - _LIBCPP_NO_CFI static __base *__as_base(void *p) { - return reinterpret_cast<__base*>(p); - } + __func __f_; template <class _Fp, bool = __lazy_and< integral_constant<bool, !is_same<__uncvref_t<_Fp>, function>::value>, @@ -1622,9 +2198,9 @@ public: // construct/copy/destroy: _LIBCPP_INLINE_VISIBILITY - function() _NOEXCEPT : __f_(0) {} + function() _NOEXCEPT { } _LIBCPP_INLINE_VISIBILITY - function(nullptr_t) _NOEXCEPT : __f_(0) {} + function(nullptr_t) _NOEXCEPT {} function(const function&); function(function&&) _NOEXCEPT; template<class _Fp, class = _EnableIfCallable<_Fp>> @@ -1633,10 +2209,10 @@ public: #if _LIBCPP_STD_VER <= 14 template<class _Alloc> _LIBCPP_INLINE_VISIBILITY - function(allocator_arg_t, const _Alloc&) _NOEXCEPT : __f_(0) {} + function(allocator_arg_t, const _Alloc&) _NOEXCEPT {} template<class _Alloc> _LIBCPP_INLINE_VISIBILITY - function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT : __f_(0) {} + function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT {} template<class _Alloc> function(allocator_arg_t, const _Alloc&, const function&); template<class _Alloc> @@ -1665,7 +2241,9 @@ public: // function capacity: _LIBCPP_INLINE_VISIBILITY - _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __f_;} + _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT { + return static_cast<bool>(__f_); + } // deleted overloads close possible hole in the type system template<class _R2, class... _ArgTypes2> @@ -1685,125 +2263,38 @@ public: }; template<class _Rp, class ..._ArgTypes> -function<_Rp(_ArgTypes...)>::function(const function& __f) -{ - if (__f.__f_ == 0) - __f_ = 0; - else if ((void *)__f.__f_ == &__f.__buf_) - { - __f_ = __as_base(&__buf_); - __f.__f_->__clone(__f_); - } - else - __f_ = __f.__f_->__clone(); -} +function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {} #if _LIBCPP_STD_VER <= 14 template<class _Rp, class ..._ArgTypes> template <class _Alloc> function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, - const function& __f) -{ - if (__f.__f_ == 0) - __f_ = 0; - else if ((void *)__f.__f_ == &__f.__buf_) - { - __f_ = __as_base(&__buf_); - __f.__f_->__clone(__f_); - } - else - __f_ = __f.__f_->__clone(); -} + const function& __f) : __f_(__f.__f_) {} #endif -template<class _Rp, class ..._ArgTypes> +template <class _Rp, class... _ArgTypes> function<_Rp(_ArgTypes...)>::function(function&& __f) _NOEXCEPT -{ - if (__f.__f_ == 0) - __f_ = 0; - else if ((void *)__f.__f_ == &__f.__buf_) - { - __f_ = __as_base(&__buf_); - __f.__f_->__clone(__f_); - } - else - { - __f_ = __f.__f_; - __f.__f_ = 0; - } -} + : __f_(_VSTD::move(__f.__f_)) {} #if _LIBCPP_STD_VER <= 14 template<class _Rp, class ..._ArgTypes> template <class _Alloc> function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&, - function&& __f) -{ - if (__f.__f_ == 0) - __f_ = 0; - else if ((void *)__f.__f_ == &__f.__buf_) - { - __f_ = __as_base(&__buf_); - __f.__f_->__clone(__f_); - } - else - { - __f_ = __f.__f_; - __f.__f_ = 0; - } -} + function&& __f) + : __f_(_VSTD::move(__f.__f_)) {} #endif -template<class _Rp, class ..._ArgTypes> +template <class _Rp, class... _ArgTypes> template <class _Fp, class> function<_Rp(_ArgTypes...)>::function(_Fp __f) - : __f_(0) -{ - if (__function::__not_null(__f)) - { - typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_ArgTypes...)> _FF; - if (sizeof(_FF) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) - { - __f_ = ::new((void*)&__buf_) _FF(_VSTD::move(__f)); - } - else - { - typedef allocator<_FF> _Ap; - _Ap __a; - typedef __allocator_destructor<_Ap> _Dp; - unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new (__hold.get()) _FF(_VSTD::move(__f), allocator<_Fp>(__a)); - __f_ = __hold.release(); - } - } -} + : __f_(_VSTD::move(__f), allocator<_Fp>()) {} #if _LIBCPP_STD_VER <= 14 -template<class _Rp, class ..._ArgTypes> +template <class _Rp, class... _ArgTypes> template <class _Fp, class _Alloc, class> -function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f) - : __f_(0) -{ - typedef allocator_traits<_Alloc> __alloc_traits; - if (__function::__not_null(__f)) - { - typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _FF; - typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; - _Ap __a(__a0); - if (sizeof(_FF) <= sizeof(__buf_) && - is_nothrow_copy_constructible<_Fp>::value && is_nothrow_copy_constructible<_Ap>::value) - { - __f_ = ::new((void*)&__buf_) _FF(_VSTD::move(__f), _Alloc(__a)); - } - else - { - typedef __allocator_destructor<_Ap> _Dp; - unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); - ::new (__hold.get()) _FF(_VSTD::move(__f), _Alloc(__a)); - __f_ = __hold.release(); - } - } -} +function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a, + _Fp __f) + : __f_(_VSTD::move(__f), __a) {} #endif template<class _Rp, class ..._ArgTypes> @@ -1818,19 +2309,7 @@ template<class _Rp, class ..._ArgTypes> function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT { - *this = nullptr; - if (__f.__f_ == 0) - __f_ = 0; - else if ((void *)__f.__f_ == &__f.__buf_) - { - __f_ = __as_base(&__buf_); - __f.__f_->__clone(__f_); - } - else - { - __f_ = __f.__f_; - __f.__f_ = 0; - } + __f_ = std::move(__f.__f_); return *this; } @@ -1838,12 +2317,7 @@ template<class _Rp, class ..._ArgTypes> function<_Rp(_ArgTypes...)>& function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT { - __base* __t = __f_; - __f_ = 0; - if ((void *)__t == &__buf_) - __t->destroy(); - else if (__t) - __t->destroy_deallocate(); + __f_ = nullptr; return *this; } @@ -1857,60 +2331,20 @@ function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) } template<class _Rp, class ..._ArgTypes> -function<_Rp(_ArgTypes...)>::~function() -{ - if ((void *)__f_ == &__buf_) - __f_->destroy(); - else if (__f_) - __f_->destroy_deallocate(); -} +function<_Rp(_ArgTypes...)>::~function() {} template<class _Rp, class ..._ArgTypes> void function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT { - if (_VSTD::addressof(__f) == this) - return; - if ((void *)__f_ == &__buf_ && (void *)__f.__f_ == &__f.__buf_) - { - typename aligned_storage<sizeof(__buf_)>::type __tempbuf; - __base* __t = __as_base(&__tempbuf); - __f_->__clone(__t); - __f_->destroy(); - __f_ = 0; - __f.__f_->__clone(__as_base(&__buf_)); - __f.__f_->destroy(); - __f.__f_ = 0; - __f_ = __as_base(&__buf_); - __t->__clone(__as_base(&__f.__buf_)); - __t->destroy(); - __f.__f_ = __as_base(&__f.__buf_); - } - else if ((void *)__f_ == &__buf_) - { - __f_->__clone(__as_base(&__f.__buf_)); - __f_->destroy(); - __f_ = __f.__f_; - __f.__f_ = __as_base(&__f.__buf_); - } - else if ((void *)__f.__f_ == &__f.__buf_) - { - __f.__f_->__clone(__as_base(&__buf_)); - __f.__f_->destroy(); - __f.__f_ = __f_; - __f_ = __as_base(&__buf_); - } - else - _VSTD::swap(__f_, __f.__f_); + __f_.swap(__f.__f_); } template<class _Rp, class ..._ArgTypes> _Rp function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const { - if (__f_ == 0) - __throw_bad_function_call(); - return (*__f_)(_VSTD::forward<_ArgTypes>(__arg)...); + return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } #ifndef _LIBCPP_NO_RTTI @@ -1919,9 +2353,7 @@ template<class _Rp, class ..._ArgTypes> const std::type_info& function<_Rp(_ArgTypes...)>::target_type() const _NOEXCEPT { - if (__f_ == 0) - return typeid(void); - return __f_->target_type(); + return __f_.target_type(); } template<class _Rp, class ..._ArgTypes> @@ -1929,9 +2361,7 @@ template <typename _Tp> _Tp* function<_Rp(_ArgTypes...)>::target() _NOEXCEPT { - if (__f_ == 0) - return nullptr; - return (_Tp*) const_cast<void *>(__f_->target(typeid(_Tp))); + return (_Tp*)(__f_.template target<_Tp>()); } template<class _Rp, class ..._ArgTypes> @@ -1939,9 +2369,7 @@ template <typename _Tp> const _Tp* function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT { - if (__f_ == 0) - return nullptr; - return (const _Tp*)__f_->target(typeid(_Tp)); + return __f_.template target<_Tp>(); } #endif // _LIBCPP_NO_RTTI @@ -2105,53 +2533,53 @@ __mu(_Ti& __ti, _Uj&) template <class _Ti, bool IsReferenceWrapper, bool IsBindEx, bool IsPh, class _TupleUj> -struct ____mu_return; +struct __mu_return_impl; template <bool _Invokable, class _Ti, class ..._Uj> -struct ____mu_return_invokable // false +struct __mu_return_invokable // false { typedef __nat type; }; template <class _Ti, class ..._Uj> -struct ____mu_return_invokable<true, _Ti, _Uj...> +struct __mu_return_invokable<true, _Ti, _Uj...> { typedef typename __invoke_of<_Ti&, _Uj...>::type type; }; template <class _Ti, class ..._Uj> -struct ____mu_return<_Ti, false, true, false, tuple<_Uj...> > - : public ____mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...> +struct __mu_return_impl<_Ti, false, true, false, tuple<_Uj...> > + : public __mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...> { }; template <class _Ti, class _TupleUj> -struct ____mu_return<_Ti, false, false, true, _TupleUj> +struct __mu_return_impl<_Ti, false, false, true, _TupleUj> { typedef typename tuple_element<is_placeholder<_Ti>::value - 1, _TupleUj>::type&& type; }; template <class _Ti, class _TupleUj> -struct ____mu_return<_Ti, true, false, false, _TupleUj> +struct __mu_return_impl<_Ti, true, false, false, _TupleUj> { typedef typename _Ti::type& type; }; template <class _Ti, class _TupleUj> -struct ____mu_return<_Ti, false, false, false, _TupleUj> +struct __mu_return_impl<_Ti, false, false, false, _TupleUj> { typedef _Ti& type; }; template <class _Ti, class _TupleUj> struct __mu_return - : public ____mu_return<_Ti, - __is_reference_wrapper<_Ti>::value, - is_bind_expression<_Ti>::value, - 0 < is_placeholder<_Ti>::value && - is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value, - _TupleUj> + : public __mu_return_impl<_Ti, + __is_reference_wrapper<_Ti>::value, + is_bind_expression<_Ti>::value, + 0 < is_placeholder<_Ti>::value && + is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value, + _TupleUj> { }; @@ -2340,8 +2768,6 @@ bind(_Fp&& __f, _BoundArgs&&... __bound_args) #if _LIBCPP_STD_VER > 14 -#define __cpp_lib_invoke 201411 - template <class _Fn, class ..._Args> result_of_t<_Fn&&(_Args&&...)> invoke(_Fn&& __f, _Args&&... __args) @@ -2497,7 +2923,7 @@ template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> class _LIBCPP_TYPE_VIS default_searcher { public: _LIBCPP_INLINE_VISIBILITY - default_searcher(_ForwardIterator __f, _ForwardIterator __l, + default_searcher(_ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate()) : __first_(__f), __last_(__l), __pred_(__p) {} @@ -2519,6 +2945,26 @@ private: #endif // _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER > 17 +template <class _Tp> +using unwrap_reference_t = typename unwrap_reference<_Tp>::type; + +template <class _Tp> +using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; +#endif // > C++17 + +template <class _Container, class _Predicate> +inline void __libcpp_erase_if_container( _Container& __c, _Predicate __pred) +{ + for (typename _Container::iterator __iter = __c.begin(), __last = __c.end(); __iter != __last;) + { + if (__pred(*__iter)) + __iter = __c.erase(__iter); + else + ++__iter; + } +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_FUNCTIONAL diff --git a/lib/libcxx/include/future b/lib/libcxx/include/future index 0f6d42678ef..b3ffc7e3517 100644 --- a/lib/libcxx/include/future +++ b/lib/libcxx/include/future @@ -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> diff --git a/lib/libcxx/include/iomanip b/lib/libcxx/include/iomanip index a6bee736f45..36c11167a44 100644 --- a/lib/libcxx/include/iomanip +++ b/lib/libcxx/include/iomanip @@ -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 diff --git a/lib/libcxx/include/iosfwd b/lib/libcxx/include/iosfwd index d4384859e41..31f1902e5f5 100644 --- a/lib/libcxx/include/iosfwd +++ b/lib/libcxx/include/iosfwd @@ -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; diff --git a/lib/libcxx/include/istream b/lib/libcxx/include/istream index 71c162b0d41..30ee4f4b871 100644 --- a/lib/libcxx/include/istream +++ b/lib/libcxx/include/istream @@ -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>) diff --git a/lib/libcxx/include/iterator b/lib/libcxx/include/iterator index 9415e0b8396..bda177e11e6 100644 --- a/lib/libcxx/include/iterator +++ b/lib/libcxx/include/iterator @@ -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 @@ -437,6 +438,23 @@ struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator 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 { private: @@ -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*> diff --git a/lib/libcxx/include/limits b/lib/libcxx/include/limits index f530507f724..5ea9a9e6fdf 100644 --- a/lib/libcxx/include/limits +++ b/lib/libcxx/include/limits @@ -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 diff --git a/lib/libcxx/include/list b/lib/libcxx/include/list index d2e78cd66af..c69e31d93a4 100644 --- a/lib/libcxx/include/list +++ b/lib/libcxx/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 diff --git a/lib/libcxx/include/locale b/lib/libcxx/include/locale index e240799f383..2043892fa2d 100644 --- a/lib/libcxx/include/locale +++ b/lib/libcxx/include/locale @@ -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 } diff --git a/lib/libcxx/include/map b/lib/libcxx/include/map index 559ec484aca..616bb46cfcc 100644 --- a/lib/libcxx/include/map +++ b/lib/libcxx/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 diff --git a/lib/libcxx/include/memory b/lib/libcxx/include/memory index adfe4f4fbbe..ce2c3576623 100644 --- a/lib/libcxx/include/memory +++ b/lib/libcxx/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 ..._Args> -struct __has_construct - : false_type -{ -}; - -#else // _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 {}; -#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) @@ -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 @@ -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()); } }; diff --git a/lib/libcxx/include/module.modulemap b/lib/libcxx/include/module.modulemap index 089505586fb..6d88f52113c 100644 --- a/lib/libcxx/include/module.modulemap +++ b/lib/libcxx/include/module.modulemap @@ -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 * diff --git a/lib/libcxx/include/mutex b/lib/libcxx/include/mutex index 52e39b0fb1f..6d2de2b460e 100644 --- a/lib/libcxx/include/mutex +++ b/lib/libcxx/include/mutex @@ -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: diff --git a/lib/libcxx/include/new b/lib/libcxx/include/new index 5a658c7a2f2..24ffcad5a6b 100644 --- a/lib/libcxx/include/new +++ b/lib/libcxx/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,16 +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 !__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 @@ -148,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 @@ -180,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 @@ -194,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 @@ -211,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 @@ -221,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 @@ -237,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); @@ -253,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 -#ifdef _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE - return ::operator delete(__ptr); + } + + 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 __builtin_operator_delete(__ptr); + return __do_call(__ptr, __size); #endif -} + } -#ifdef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_NO_EXCEPTIONS -_LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH +#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 -void __throw_bad_array_length() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw bad_array_length(); + } +#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 - _VSTD::abort(); + 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); +#else + 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); +} + +inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate_unsized(void* __ptr, size_t __align) { + _DeallocateCaller::__do_deallocate_handle_align(__ptr, __align); +} 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" ); diff --git a/lib/libcxx/include/numeric b/lib/libcxx/include/numeric index b33b6a398eb..4e68239d059 100644 --- a/lib/libcxx/include/numeric +++ b/lib/libcxx/include/numeric @@ -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 diff --git a/lib/libcxx/include/optional b/lib/libcxx/include/optional index a76f8d18976..70422068e28 100644 --- a/lib/libcxx/include/optional +++ b/lib/libcxx/include/optional @@ -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()) diff --git a/lib/libcxx/include/ostream b/lib/libcxx/include/ostream index 5404e0dca6c..d700a369b34 100644 --- a/lib/libcxx/include/ostream +++ b/lib/libcxx/include/ostream @@ -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 diff --git a/lib/libcxx/include/random b/lib/libcxx/include/random index 89664a6ca33..724bd0fc215 100644 --- a/lib/libcxx/include/random +++ b/lib/libcxx/include/random @@ -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); } } diff --git a/lib/libcxx/include/regex b/lib/libcxx/include/regex index dcdb14af9af..bd83d7c10ca 100644 --- a/lib/libcxx/include/regex +++ b/lib/libcxx/include/regex @@ -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 diff --git a/lib/libcxx/include/scoped_allocator b/lib/libcxx/include/scoped_allocator index 4760d946def..bdbb0136b5c 100644 --- a/lib/libcxx/include/scoped_allocator +++ b/lib/libcxx/include/scoped_allocator @@ -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 diff --git a/lib/libcxx/include/set b/lib/libcxx/include/set index 108a9e97f88..a0155f0b275 100644 --- a/lib/libcxx/include/set +++ b/lib/libcxx/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 diff --git a/lib/libcxx/include/shared_mutex b/lib/libcxx/include/shared_mutex index a7735d6732c..3daf74d26c7 100644 --- a/lib/libcxx/include/shared_mutex +++ b/lib/libcxx/include/shared_mutex @@ -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 diff --git a/lib/libcxx/include/span b/lib/libcxx/include/span index db8f836f918..cebe98760f2 100644 --- a/lib/libcxx/include/span +++ b/lib/libcxx/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>; diff --git a/lib/libcxx/include/sstream b/lib/libcxx/include/sstream index b01f47b6872..9c3ee13bfba 100644 --- a/lib/libcxx/include/sstream +++ b/lib/libcxx/include/sstream @@ -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); + } } } diff --git a/lib/libcxx/include/stddef.h b/lib/libcxx/include/stddef.h index faf8552d8ce..f65065d869a 100644 --- a/lib/libcxx/include/stddef.h +++ b/lib/libcxx/include/stddef.h @@ -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 diff --git a/lib/libcxx/include/stdexcept b/lib/libcxx/include/stdexcept index 6533497e4ea..3ec79349aa9 100644 --- a/lib/libcxx/include/stdexcept +++ b/lib/libcxx/include/stdexcept @@ -192,7 +192,7 @@ void __throw_logic_error(const char*__msg) throw logic_error(__msg); #else ((void)__msg); - _VSTD::abort(); + _VSTD::abort(); #endif } @@ -203,7 +203,7 @@ void __throw_domain_error(const char*__msg) throw domain_error(__msg); #else ((void)__msg); - _VSTD::abort(); + _VSTD::abort(); #endif } @@ -214,7 +214,7 @@ void __throw_invalid_argument(const char*__msg) throw invalid_argument(__msg); #else ((void)__msg); - _VSTD::abort(); + _VSTD::abort(); #endif } @@ -225,7 +225,7 @@ void __throw_length_error(const char*__msg) throw length_error(__msg); #else ((void)__msg); - _VSTD::abort(); + _VSTD::abort(); #endif } @@ -236,7 +236,7 @@ void __throw_out_of_range(const char*__msg) throw out_of_range(__msg); #else ((void)__msg); - _VSTD::abort(); + _VSTD::abort(); #endif } @@ -247,7 +247,7 @@ void __throw_range_error(const char*__msg) throw range_error(__msg); #else ((void)__msg); - _VSTD::abort(); + _VSTD::abort(); #endif } diff --git a/lib/libcxx/include/streambuf b/lib/libcxx/include/streambuf index 37a65323716..dd293dc639b 100644 --- a/lib/libcxx/include/streambuf +++ b/lib/libcxx/include/streambuf @@ -138,7 +138,7 @@ public: virtual ~basic_streambuf(); // 27.6.2.2.1 locales: - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 locale pubimbue(const locale& __loc) { imbue(__loc); locale __r = __loc_; @@ -146,70 +146,70 @@ public: return __r; } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 locale getloc() const { return __loc_; } // 27.6.2.2.2 buffer and positioning: - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_streambuf* pubsetbuf(char_type* __s, streamsize __n) { return setbuf(__s, __n); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type pubseekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which = ios_base::in | ios_base::out) { return seekoff(__off, __way, __which); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type pubseekpos(pos_type __sp, ios_base::openmode __which = ios_base::in | ios_base::out) { return seekpos(__sp, __which); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int pubsync() { return sync(); } // Get and put areas: // 27.6.2.2.3 Get area: - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize in_avail() { if (__ninp_ < __einp_) return static_cast<streamsize>(__einp_ - __ninp_); return showmanyc(); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type snextc() { if (sbumpc() == traits_type::eof()) return traits_type::eof(); return sgetc(); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sbumpc() { if (__ninp_ == __einp_) return uflow(); return traits_type::to_int_type(*__ninp_++); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sgetc() { if (__ninp_ == __einp_) return underflow(); return traits_type::to_int_type(*__ninp_); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize sgetn(char_type* __s, streamsize __n) { return xsgetn(__s, __n); } // 27.6.2.2.4 Putback: - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sputbackc(char_type __c) { if (__binp_ == __ninp_ || !traits_type::eq(__c, __ninp_[-1])) return pbackfail(traits_type::to_int_type(__c)); return traits_type::to_int_type(*--__ninp_); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sungetc() { if (__binp_ == __ninp_) return pbackfail(); @@ -217,7 +217,7 @@ public: } // 27.6.2.2.5 Put area: - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 int_type sputc(char_type __c) { if (__nout_ == __eout_) return overflow(traits_type::to_int_type(__c)); @@ -225,7 +225,7 @@ public: return traits_type::to_int_type(__c); } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 streamsize sputn(const char_type* __s, streamsize __n) { return xsputn(__s, __n); } @@ -240,10 +240,10 @@ protected: _LIBCPP_INLINE_VISIBILITY char_type* gptr() const {return __ninp_;} _LIBCPP_INLINE_VISIBILITY char_type* egptr() const {return __einp_;} - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void gbump(int __n) { __ninp_ += __n; } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void setg(char_type* __gbeg, char_type* __gnext, char_type* __gend) { __binp_ = __gbeg; __ninp_ = __gnext; @@ -255,13 +255,13 @@ protected: _LIBCPP_INLINE_VISIBILITY char_type* pptr() const {return __nout_;} _LIBCPP_INLINE_VISIBILITY char_type* epptr() const {return __eout_;} - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void pbump(int __n) { __nout_ += __n; } _LIBCPP_INLINE_VISIBILITY void __pbump(streamsize __n) { __nout_ += __n; } - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void setp(char_type* __pbeg, char_type* __pend) { __bout_ = __nout_ = __pbeg; __eout_ = __pend; @@ -486,7 +486,7 @@ basic_streambuf<_CharT, _Traits>::overflow(int_type) return traits_type::eof(); } -#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_streambuf<char>) _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<wchar_t>) diff --git a/lib/libcxx/include/string b/lib/libcxx/include/string index 162e54058c4..fb838d1e5dd 100644 --- a/lib/libcxx/include/string +++ b/lib/libcxx/include/string @@ -437,6 +437,11 @@ template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); +template<class charT, class traits, class Allocator, class U> +void erase(basic_string<charT, traits, Allocator>& c, const U& value); // C++20 +template<class charT, class traits, class Allocator, class Predicate> +void erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20 + typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; typedef basic_string<char16_t> u16string; @@ -510,6 +515,7 @@ basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); // C++1 #include <type_traits> #include <initializer_list> #include <__functional_base> +#include <version> #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS #include <cstdint> #endif @@ -579,6 +585,7 @@ basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __x, const basic_string<_CharT,_Traits,_Allocator>& __y); template<class _CharT, class _Traits, class _Allocator> +inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y); @@ -806,7 +813,9 @@ public: basic_string(basic_string&& __str, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES template <class = typename enable_if<__is_allocator<_Allocator>::value, nullptr_t>::type> +#endif _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s) { _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); @@ -816,7 +825,9 @@ public: # endif } +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES template <class = typename enable_if<__is_allocator<_Allocator>::value, nullptr_t>::type> +#endif _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, const _Allocator& __a); @@ -827,7 +838,9 @@ public: _LIBCPP_INLINE_VISIBILITY basic_string(size_type __n, _CharT __c); +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES template <class = typename enable_if<__is_allocator<_Allocator>::value, nullptr_t>::type> +#endif _LIBCPP_INLINE_VISIBILITY basic_string(size_type __n, _CharT __c, const _Allocator& __a); @@ -948,7 +961,11 @@ public: void resize(size_type __n, value_type __c); _LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {resize(__n, value_type());} - void reserve(size_type __res_arg = 0); + void reserve(size_type __res_arg); + _LIBCPP_INLINE_VISIBILITY void __resize_default_init(size_type __n); + + _LIBCPP_INLINE_VISIBILITY + void reserve() _NOEXCEPT {reserve(0);} _LIBCPP_INLINE_VISIBILITY void shrink_to_fit() _NOEXCEPT {reserve();} _LIBCPP_INLINE_VISIBILITY @@ -1002,6 +1019,10 @@ public: basic_string& append(const value_type* __s, size_type __n); basic_string& append(const value_type* __s); basic_string& append(size_type __n, value_type __c); + + _LIBCPP_INLINE_VISIBILITY + void __append_default_init(size_type __n); + template <class _ForwardIterator> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator); @@ -1664,7 +1685,7 @@ basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _ template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::__invalidate_all_iterators() { @@ -1674,7 +1695,7 @@ basic_string<_CharT, _Traits, _Allocator>::__invalidate_all_iterators() } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type #if _LIBCPP_DEBUG_LEVEL >= 2 @@ -1704,7 +1725,7 @@ basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) { @@ -1715,7 +1736,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string() } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value) @@ -1780,7 +1801,9 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty } template <class _CharT, class _Traits, class _Allocator> +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES template <class> +#endif basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a) : __r_(__second_tag(), __a) { @@ -1792,7 +1815,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n) { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); @@ -1803,7 +1826,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_ } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n, const _Allocator& __a) : __r_(__second_tag(), __a) { @@ -1844,7 +1867,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string( #ifndef _LIBCPP_CXX03_LANG template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) @@ -1862,7 +1885,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str) } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a) : __r_(__second_tag(), __a) { @@ -1907,7 +1930,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c) } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c) { __init(__n, __c); @@ -1917,7 +1940,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __ } template <class _CharT, class _Traits, class _Allocator> +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES template <class> +#endif basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a) : __r_(__second_tag(), __a) { @@ -1943,7 +1968,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a) : __r_(__second_tag(), __a) @@ -2054,7 +2079,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _For template <class _CharT, class _Traits, class _Allocator> template<class _InputIterator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last) { __init(__first, __last); @@ -2065,7 +2090,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, template <class _CharT, class _Traits, class _Allocator> template<class _InputIterator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __r_(__second_tag(), __a) @@ -2079,7 +2104,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, #ifndef _LIBCPP_CXX03_LANG template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string( initializer_list<_CharT> __il) { @@ -2090,7 +2115,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string( } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>::basic_string( initializer_list<_CharT> __il, const _Allocator& __a) @@ -2254,7 +2279,7 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) #ifndef _LIBCPP_CXX03_LANG template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) @@ -2266,7 +2291,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, fa } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type) #if _LIBCPP_STD_VER > 14 @@ -2282,7 +2307,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) @@ -2416,6 +2441,23 @@ basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c) } template <class _CharT, class _Traits, class _Allocator> +inline void +basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n) +{ + if (__n) + { + size_type __cap = capacity(); + size_type __sz = size(); + if (__cap - __sz < __n) + __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); + pointer __p = __get_pointer(); + __sz += __n; + __set_size(__sz); + traits_type::assign(__p[__sz], value_type()); + } +} + +template <class _CharT, class _Traits, class _Allocator> void basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) { @@ -2499,7 +2541,7 @@ basic_string<_CharT, _Traits, _Allocator>::__append_forward_unsafe( } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str) { @@ -2676,7 +2718,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _Forward } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str) { @@ -2746,7 +2788,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_ty } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, size_type __n, value_type __c) { @@ -2866,7 +2908,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_it } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str) { @@ -2910,7 +2952,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __ } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const basic_string& __str) { @@ -2919,7 +2961,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_it } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n) { @@ -2927,7 +2969,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_it } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s) { @@ -2935,7 +2977,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_it } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c) { @@ -2967,7 +3009,7 @@ basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) { @@ -2985,7 +3027,7 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) { @@ -3002,7 +3044,7 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_i } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::pop_back() { @@ -3024,7 +3066,7 @@ basic_string<_CharT, _Traits, _Allocator>::pop_back() } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT { @@ -3042,7 +3084,7 @@ basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::__erase_to_end(size_type __pos) { @@ -3071,7 +3113,18 @@ basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c) } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void +basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n) +{ + size_type __sz = size(); + if (__n > __sz) { + __append_default_init(__n - __sz); + } else + __erase_to_end(__n); +} + +template <class _CharT, class _Traits, class _Allocator> +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::max_size() const _NOEXCEPT { @@ -3147,7 +3200,7 @@ basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __res_arg) } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) const _NOEXCEPT { @@ -3156,7 +3209,7 @@ basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) const _NO } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) _NOEXCEPT { @@ -3183,7 +3236,7 @@ basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::front() { @@ -3192,7 +3245,7 @@ basic_string<_CharT, _Traits, _Allocator>::front() } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::front() const { @@ -3201,7 +3254,7 @@ basic_string<_CharT, _Traits, _Allocator>::front() const } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::back() { @@ -3210,7 +3263,7 @@ basic_string<_CharT, _Traits, _Allocator>::back() } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::back() const { @@ -3231,7 +3284,7 @@ basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline basic_string<_CharT, _Traits, _Allocator> basic_string<_CharT, _Traits, _Allocator>::substr(size_type __pos, size_type __n) const { @@ -3239,7 +3292,7 @@ basic_string<_CharT, _Traits, _Allocator>::substr(size_type __pos, size_type __n } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 @@ -3287,7 +3340,7 @@ basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, size_type __pos) const _NOEXCEPT @@ -3312,7 +3365,7 @@ basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT @@ -3345,7 +3398,7 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, size_type __pos) const _NOEXCEPT @@ -3370,7 +3423,7 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT @@ -3403,7 +3456,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str, size_type __pos) const _NOEXCEPT @@ -3428,7 +3481,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT @@ -3439,7 +3492,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c, size_type __pos) const _NOEXCEPT @@ -3461,7 +3514,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str, size_type __pos) const _NOEXCEPT @@ -3486,7 +3539,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT @@ -3497,7 +3550,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c, size_type __pos) const _NOEXCEPT @@ -3519,7 +3572,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* _ } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT @@ -3544,7 +3597,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT @@ -3555,7 +3608,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* _ } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c, size_type __pos) const _NOEXCEPT @@ -3578,7 +3631,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __ } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT @@ -3603,7 +3656,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT @@ -3614,7 +3667,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __ } template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, size_type __pos) const _NOEXCEPT @@ -3649,7 +3702,7 @@ basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline int basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT { @@ -3695,7 +3748,7 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, } template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, @@ -3753,7 +3806,7 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, // __invariants template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline bool basic_string<_CharT, _Traits, _Allocator>::__invariants() const { @@ -3771,7 +3824,7 @@ basic_string<_CharT, _Traits, _Allocator>::__invariants() const // __clear_and_shrink template<class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_INLINE_VISIBILITY +inline void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { @@ -4025,6 +4078,7 @@ operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Allocator>& __rhs) } template<class _CharT, class _Traits, class _Allocator> +inline basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { @@ -4121,11 +4175,13 @@ swap(basic_string<_CharT, _Traits, _Allocator>& __lhs, __lhs.swap(__rhs); } -#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS +#ifndef _LIBCPP_NO_HAS_CHAR8_T +typedef basic_string<char8_t> u8string; +#endif +#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS typedef basic_string<char16_t> u16string; typedef basic_string<char32_t> u32string; - #endif // _LIBCPP_HAS_NO_UNICODE_CHARS _LIBCPP_FUNC_VIS int stoi (const string& __str, size_t* __idx = 0, int __base = 10); @@ -4225,6 +4281,18 @@ getline(basic_istream<_CharT, _Traits>&& __is, #endif // _LIBCPP_CXX03_LANG +#if _LIBCPP_STD_VER > 17 +template<class _CharT, class _Traits, class _Allocator, class _Up> +inline _LIBCPP_INLINE_VISIBILITY +void erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) +{ __str.erase(_VSTD::remove(__str.begin(), __str.end(), __v), __str.end()); } + +template<class _CharT, class _Traits, class _Allocator, class _Predicate> +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred) +{ __str.erase(_VSTD::remove_if(__str.begin(), __str.end(), __pred), __str.end()); } +#endif + #if _LIBCPP_DEBUG_LEVEL >= 2 template<class _CharT, class _Traits, class _Allocator> @@ -4282,6 +4350,14 @@ inline namespace literals return basic_string<wchar_t> (__str, __len); } +#ifndef _LIBCPP_NO_HAS_CHAR8_T + inline _LIBCPP_INLINE_VISIBILITY + basic_string<char8_t> operator "" s(const char8_t *__str, size_t __len) _NOEXCEPT + { + return basic_string<char8_t> (__str, __len); + } +#endif + inline _LIBCPP_INLINE_VISIBILITY basic_string<char16_t> operator "" s( const char16_t *__str, size_t __len ) { diff --git a/lib/libcxx/include/string_view b/lib/libcxx/include/string_view index 6377aeb6d64..7d783122f12 100644 --- a/lib/libcxx/include/string_view +++ b/lib/libcxx/include/string_view @@ -178,6 +178,7 @@ namespace std { #include <iterator> #include <limits> #include <stdexcept> +#include <version> #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -768,6 +769,9 @@ bool operator>=(typename common_type<basic_string_view<_CharT, _Traits> >::type } typedef basic_string_view<char> string_view; +#ifndef _LIBCPP_NO_HAS_CHAR8_T +typedef basic_string_view<char8_t> u8string_view; +#endif typedef basic_string_view<char16_t> u16string_view; typedef basic_string_view<char32_t> u32string_view; typedef basic_string_view<wchar_t> wstring_view; @@ -777,17 +781,12 @@ template<class _CharT, class _Traits> struct _LIBCPP_TEMPLATE_VIS hash<basic_string_view<_CharT, _Traits> > : public unary_function<basic_string_view<_CharT, _Traits>, size_t> { - size_t operator()(const basic_string_view<_CharT, _Traits> __val) const _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + size_t operator()(const basic_string_view<_CharT, _Traits> __val) const _NOEXCEPT { + return __do_string_hash(__val.data(), __val.data() + __val.size()); + } }; -template<class _CharT, class _Traits> -size_t -hash<basic_string_view<_CharT, _Traits> >::operator()( - const basic_string_view<_CharT, _Traits> __val) const _NOEXCEPT -{ - return __do_string_hash(__val.data(), __val.data() + __val.size()); -} - #if _LIBCPP_STD_VER > 11 inline namespace literals @@ -806,6 +805,14 @@ inline namespace literals return basic_string_view<wchar_t> (__str, __len); } +#ifndef _LIBCPP_NO_HAS_CHAR8_T + inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + basic_string_view<char8_t> operator "" sv(const char8_t *__str, size_t __len) _NOEXCEPT + { + return basic_string_view<char8_t> (__str, __len); + } +#endif + inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR basic_string_view<char16_t> operator "" sv(const char16_t *__str, size_t __len) _NOEXCEPT { diff --git a/lib/libcxx/include/support/win32/locale_win32.h b/lib/libcxx/include/support/win32/locale_win32.h index 68682c9624b..c7c6d786cb8 100644 --- a/lib/libcxx/include/support/win32/locale_win32.h +++ b/lib/libcxx/include/support/win32/locale_win32.h @@ -35,8 +35,8 @@ public: : __locale(nullptr), __locale_str(nullptr) {} locale_t(std::nullptr_t) : __locale(nullptr), __locale_str(nullptr) {} - locale_t(_locale_t __locale, const char* __locale_str) - : __locale(__locale), __locale_str(__locale_str) {} + locale_t(_locale_t __xlocale, const char* __xlocale_str) + : __locale(__xlocale), __locale_str(__xlocale_str) {} friend bool operator==(const locale_t& __left, const locale_t& __right) { return __left.__locale == __right.__locale; diff --git a/lib/libcxx/include/thread b/lib/libcxx/include/thread index 0629d70efda..8c0115f8708 100644 --- a/lib/libcxx/include/thread +++ b/lib/libcxx/include/thread @@ -151,7 +151,7 @@ class __thread_specific_ptr __thread_specific_ptr(const __thread_specific_ptr&); __thread_specific_ptr& operator=(const __thread_specific_ptr&); - static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); + _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); public: typedef _Tp* pointer; diff --git a/lib/libcxx/include/tuple b/lib/libcxx/include/tuple index b3a17e7b735..4cc69030b9a 100644 --- a/lib/libcxx/include/tuple +++ b/lib/libcxx/include/tuple @@ -65,7 +65,7 @@ public: template <class U1, class U2> tuple& operator=(const pair<U1, U2>&); // iff sizeof...(T) == 2 template <class U1, class U2> - tuple& operator=(pair<U1, U2>&&); //iffsizeof...(T) == 2 + tuple& operator=(pair<U1, U2>&&); // iff sizeof...(T) == 2 void swap(tuple&) noexcept(AND(swap(declval<T&>(), declval<T&>())...)); }; @@ -84,8 +84,8 @@ template <class T, class Tuple> constexpr T make_from_tuple(Tuple&& t); // C++17 // 20.4.1.4, tuple helper classes: -template <class T> class tuple_size; // undefined -template <class... T> class tuple_size<tuple<T...>>; +template <class T> struct tuple_size; // undefined +template <class... T> struct tuple_size<tuple<T...>>; template <class T> inline constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17 template <size_t I, class T> class tuple_element; // undefined @@ -141,6 +141,7 @@ template <class... Types> #include <type_traits> #include <__functional_base> #include <utility> +#include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -1077,30 +1078,12 @@ namespace { _LIBCPP_INLINE_VAR constexpr __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>(); } -template <class _Tp> -struct __make_tuple_return_impl -{ - typedef _Tp type; -}; - -template <class _Tp> -struct __make_tuple_return_impl<reference_wrapper<_Tp> > -{ - typedef _Tp& type; -}; - -template <class _Tp> -struct __make_tuple_return -{ - typedef typename __make_tuple_return_impl<typename decay<_Tp>::type>::type type; -}; - template <class... _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -tuple<typename __make_tuple_return<_Tp>::type...> +tuple<typename __unwrap_ref_decay<_Tp>::type...> make_tuple(_Tp&&... __t) { - return tuple<typename __make_tuple_return<_Tp>::type...>(_VSTD::forward<_Tp>(__t)...); + return tuple<typename __unwrap_ref_decay<_Tp>::type...>(_VSTD::forward<_Tp>(__t)...); } template <class... _Tp> diff --git a/lib/libcxx/include/type_traits b/lib/libcxx/include/type_traits index 30bfb161c0d..8b30511a4ec 100644 --- a/lib/libcxx/include/type_traits +++ b/lib/libcxx/include/type_traits @@ -75,6 +75,10 @@ namespace std template <class T> struct remove_pointer; template <class T> struct add_pointer; + template<class T> struct type_identity; // C++20 + template<class T> + using type_identity_t = typename type_identity<T>::type; // C++20 + // Integral properties: template <class T> struct is_signed; template <class T> struct is_unsigned; @@ -400,6 +404,7 @@ namespace std */ #include <__config> #include <cstddef> +#include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -704,6 +709,9 @@ template <> struct __libcpp_is_integral<char> : public tr template <> struct __libcpp_is_integral<signed char> : public true_type {}; template <> struct __libcpp_is_integral<unsigned char> : public true_type {}; template <> struct __libcpp_is_integral<wchar_t> : public true_type {}; +#ifndef _LIBCPP_NO_HAS_CHAR8_T +template <> struct __libcpp_is_integral<char8_t> : public true_type {}; +#endif #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS template <> struct __libcpp_is_integral<char16_t> : public true_type {}; template <> struct __libcpp_is_integral<char32_t> : public true_type {}; @@ -733,12 +741,6 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_integral_v // is_floating_point template <class _Tp> struct __libcpp_is_floating_point : public false_type {}; -#ifdef __clang__ -template <> struct __libcpp_is_floating_point<__fp16> : public true_type {}; -#endif -#ifdef __FLT16_MANT_DIG__ -template <> struct __libcpp_is_floating_point<_Float16> : public true_type {}; -#endif template <> struct __libcpp_is_floating_point<float> : public true_type {}; template <> struct __libcpp_is_floating_point<double> : public true_type {}; template <> struct __libcpp_is_floating_point<long double> : public true_type {}; @@ -1226,6 +1228,12 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_pointer template <class _Tp> using add_pointer_t = typename add_pointer<_Tp>::type; #endif +// type_identity +#if _LIBCPP_STD_VER > 17 +template<class _Tp> struct type_identity { typedef _Tp type; }; +template<class _Tp> using type_identity_t = typename type_identity<_Tp>::type; +#endif + // is_signed template <class _Tp, bool = is_integral<_Tp>::value> @@ -1644,7 +1652,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool has_unique_object_representations_v // alignment_of template <class _Tp> struct _LIBCPP_TEMPLATE_VIS alignment_of - : public integral_constant<size_t, __alignof__(_Tp)> {}; + : public integral_constant<size_t, _LIBCPP_ALIGNOF(_Tp)> {}; #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template <class _Tp> @@ -1674,7 +1682,7 @@ struct __nat template <class _Tp> struct __align_type { - static const size_t value = alignment_of<_Tp>::value; + static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp); typedef _Tp type; }; @@ -1807,8 +1815,8 @@ struct __static_max<_I0, _I1, _In...> template <size_t _Len, class _Type0, class ..._Types> struct aligned_union { - static const size_t alignment_value = __static_max<__alignof__(_Type0), - __alignof__(_Types)...>::value; + static const size_t alignment_value = __static_max<_LIBCPP_PREFERRED_ALIGNOF(_Type0), + _LIBCPP_PREFERRED_ALIGNOF(_Types)...>::value; static const size_t __len = __static_max<_Len, sizeof(_Type0), sizeof(_Types)...>::value; typedef typename aligned_storage<__len, alignment_value>::type type; @@ -4748,7 +4756,6 @@ struct __has_operator_addressof #if _LIBCPP_STD_VER > 14 -#define __cpp_lib_void_t 201411 template <class...> using void_t = void; # ifndef _LIBCPP_HAS_NO_VARIADICS diff --git a/lib/libcxx/include/typeinfo b/lib/libcxx/include/typeinfo index f32ea6e76f1..8411532860b 100644 --- a/lib/libcxx/include/typeinfo +++ b/lib/libcxx/include/typeinfo @@ -73,12 +73,8 @@ public: #include <vcruntime_typeinfo.h> #else -#if !defined(_LIBCPP_ABI_MICROSOFT) -#if defined(_LIBCPP_NONUNIQUE_RTTI_BIT) -#define _LIBCPP_HAS_NONUNIQUE_TYPEINFO -#else -#define _LIBCPP_HAS_UNIQUE_TYPEINFO -#endif +#if defined(_LIBCPP_NONUNIQUE_RTTI_BIT) && !defined(_LIBCPP_ABI_MICROSOFT) +# define _LIBCPP_HAS_NONUNIQUE_TYPEINFO #endif namespace std // purposefully not using versioning namespace @@ -232,7 +228,7 @@ void __throw_bad_cast() #ifndef _LIBCPP_NO_EXCEPTIONS throw bad_cast(); #else - _VSTD::abort(); + _VSTD::abort(); #endif } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/unordered_map b/lib/libcxx/include/unordered_map index 348f57923b5..6035b05dc61 100644 --- a/lib/libcxx/include/unordered_map +++ b/lib/libcxx/include/unordered_map @@ -153,6 +153,15 @@ public: iterator erase(const_iterator first, const_iterator last); void clear() noexcept; + template<class H2, class P2> + void merge(unordered_map<Key, T, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_map<Key, T, H2, P2, Allocator>&& source); // C++17 + template<class H2, class P2> + void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source); // C++17 + void swap(unordered_map&) noexcept( (!allocator_type::propagate_on_container_swap::value || @@ -325,6 +334,15 @@ public: iterator erase(const_iterator first, const_iterator last); void clear() noexcept; + template<class H2, class P2> + void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source); // C++17 + template<class H2, class P2> + void merge(unordered_map<Key, T, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_map<Key, T, H2, P2, Allocator>&& source); // C++17 + void swap(unordered_multimap&) noexcept( (!allocator_type::propagate_on_container_swap::value || @@ -366,6 +384,12 @@ template <class Key, class T, class Hash, class Pred, class Alloc> unordered_multimap<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); +template <class K, class T, class H, class P, class A, class Predicate> + void erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred); // C++20 + +template <class K, class T, class H, class P, class A, class Predicate> + void erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred); // C++20 + template <class Key, class T, class Hash, class Pred, class Alloc> bool operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& x, @@ -386,6 +410,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc> #include <functional> #include <stdexcept> #include <tuple> +#include <version> #include <__debug> @@ -395,7 +420,8 @@ template <class Key, class T, class Hash, class Pred, class Alloc> _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Key, class _Cp, class _Hash, bool _IsEmpty> +template <class _Key, class _Cp, class _Hash, + bool = is_empty<_Hash>::value && !__libcpp_is_final<_Hash>::value> class __unordered_map_hasher : private _Hash { @@ -463,7 +489,8 @@ swap(__unordered_map_hasher<_Key, _Cp, _Hash, __b>& __x, __x.swap(__y); } -template <class _Key, class _Cp, class _Pred, bool _IsEmpty> +template <class _Key, class _Cp, class _Pred, + bool = is_empty<_Pred>::value && !__libcpp_is_final<_Pred>::value> class __unordered_map_equal : private _Pred { @@ -807,6 +834,9 @@ public: template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; }; +template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> +class unordered_multimap; + template <class _Key, class _Tp, class _Hash = hash<_Key>, class _Pred = equal_to<_Key>, class _Alloc = allocator<pair<const _Key, _Tp> > > class _LIBCPP_TEMPLATE_VIS unordered_map @@ -823,6 +853,7 @@ public: typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), "Invalid allocator::value_type"); + static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); private: typedef __hash_value_type<key_type, mapped_type> __value_type; @@ -864,6 +895,11 @@ public: typedef __insert_return_type<iterator, node_type> insert_return_type; #endif + template <class _Key2, class _Tp2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_map; + template <class _Key2, class _Tp2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; + _LIBCPP_INLINE_VISIBILITY unordered_map() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -1187,6 +1223,39 @@ public: return __table_.template __node_handle_extract<node_type>( __it.__i_); } + + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_unique(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_unique(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_unique(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_unique(__source.__table_); + } #endif _LIBCPP_INLINE_VISIBILITY @@ -1563,6 +1632,13 @@ swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate> +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> bool operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, @@ -1607,6 +1683,7 @@ public: typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), "Invalid allocator::value_type"); + static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); private: typedef __hash_value_type<key_type, mapped_type> __value_type; @@ -1645,6 +1722,11 @@ public: typedef __map_node_handle<__node, allocator_type> node_type; #endif + template <class _Key2, class _Tp2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_map; + template <class _Key2, class _Tp2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; + _LIBCPP_INLINE_VISIBILITY unordered_multimap() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -1846,6 +1928,39 @@ public: return __table_.template __node_handle_extract<node_type>( __it.__i_); } + + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } #endif _LIBCPP_INLINE_VISIBILITY @@ -2141,6 +2256,13 @@ swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate> +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> bool operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, diff --git a/lib/libcxx/include/unordered_set b/lib/libcxx/include/unordered_set index 9b8560da494..b4e61da89ee 100644 --- a/lib/libcxx/include/unordered_set +++ b/lib/libcxx/include/unordered_set @@ -127,6 +127,15 @@ public: iterator erase(const_iterator first, const_iterator last); void clear() noexcept; + template<class H2, class P2> + void merge(unordered_set<Key, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_set<Key, H2, P2, Allocator>&& source); // C++17 + template<class H2, class P2> + void merge(unordered_multiset<Key, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_multiset<Key, H2, P2, Allocator>&& source); // C++17 + void swap(unordered_set&) noexcept(allocator_traits<Allocator>::is_always_equal::value && noexcept(swap(declval<hasher&>(), declval<hasher&>())) && @@ -282,6 +291,15 @@ public: iterator erase(const_iterator first, const_iterator last); void clear() noexcept; + template<class H2, class P2> + void merge(unordered_multiset<Key, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_multiset<Key, H2, P2, Allocator>&& source); // C++17 + template<class H2, class P2> + void merge(unordered_set<Key, H2, P2, Allocator>& source); // C++17 + template<class H2, class P2> + void merge(unordered_set<Key, H2, P2, Allocator>&& source); // C++17 + void swap(unordered_multiset&) noexcept(allocator_traits<Allocator>::is_always_equal::value && noexcept(swap(declval<hasher&>(), declval<hasher&>())) && @@ -321,6 +339,13 @@ template <class Value, class Hash, class Pred, class Alloc> unordered_multiset<Value, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); +template <class K, class T, class H, class P, class A, class Predicate> + void erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred); // C++20 + +template <class K, class T, class H, class P, class A, class Predicate> + void erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred); // C++20 + + template <class Value, class Hash, class Pred, class Alloc> bool operator==(const unordered_multiset<Value, Hash, Pred, Alloc>& x, @@ -338,6 +363,7 @@ template <class Value, class Hash, class Pred, class Alloc> #include <__hash_table> #include <__node_handle> #include <functional> +#include <version> #include <__debug> @@ -347,6 +373,9 @@ template <class Value, class Hash, class Pred, class Alloc> _LIBCPP_BEGIN_NAMESPACE_STD +template <class _Value, class _Hash, class _Pred, class _Alloc> +class unordered_multiset; + template <class _Value, class _Hash = hash<_Value>, class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> > class _LIBCPP_TEMPLATE_VIS unordered_set @@ -362,6 +391,7 @@ public: typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), "Invalid allocator::value_type"); + static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); private: typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table; @@ -384,6 +414,11 @@ public: typedef __insert_return_type<iterator, node_type> insert_return_type; #endif + template <class _Value2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_set; + template <class _Value2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_multiset; + _LIBCPP_INLINE_VISIBILITY unordered_set() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -589,6 +624,39 @@ public: { return __table_.template __node_handle_extract<node_type>(__it); } + + template<class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_set<key_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + __table_.__node_handle_merge_unique(__source.__table_); + } + template<class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_set<key_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + __table_.__node_handle_merge_unique(__source.__table_); + } + template<class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + __table_.__node_handle_merge_unique(__source.__table_); + } + template<class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + __table_.__node_handle_merge_unique(__source.__table_); + } #endif _LIBCPP_INLINE_VISIBILITY @@ -873,6 +941,13 @@ swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate> +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template <class _Value, class _Hash, class _Pred, class _Alloc> bool operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, @@ -916,6 +991,7 @@ public: typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), "Invalid allocator::value_type"); + static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); private: typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table; @@ -937,6 +1013,11 @@ public: typedef __set_node_handle<typename __table::__node, allocator_type> node_type; #endif + template <class _Value2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_set; + template <class _Value2, class _Hash2, class _Pred2, class _Alloc2> + friend class _LIBCPP_TEMPLATE_VIS unordered_multiset; + _LIBCPP_INLINE_VISIBILITY unordered_multiset() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -1101,6 +1182,39 @@ public: { return __table_.template __node_handle_extract<node_type>(__key); } + + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_set<key_type, _H2, _P2, allocator_type>& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } + template <class _H2, class _P2> + _LIBCPP_INLINE_VISIBILITY + void merge(unordered_set<key_type, _H2, _P2, allocator_type>&& __source) + { + _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); + return __table_.__node_handle_merge_multi(__source.__table_); + } #endif _LIBCPP_INLINE_VISIBILITY @@ -1397,6 +1511,13 @@ swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate> +inline _LIBCPP_INLINE_VISIBILITY +void erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) +{ __libcpp_erase_if_container(__c, __pred); } +#endif + template <class _Value, class _Hash, class _Pred, class _Alloc> bool operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, diff --git a/lib/libcxx/include/utility b/lib/libcxx/include/utility index ed9bf030d49..74bbc5cf34f 100644 --- a/lib/libcxx/include/utility +++ b/lib/libcxx/include/utility @@ -103,7 +103,7 @@ swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); struct piecewise_construct_t { }; inline constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); -template <class T> class tuple_size; +template <class T> struct tuple_size; template <size_t I, class T> class tuple_element; template <class T1, class T2> struct tuple_size<pair<T1, T2> >; @@ -203,6 +203,7 @@ template <size_t I> #include <cstddef> #include <cstring> #include <cstdint> +#include <version> #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -296,12 +297,13 @@ template <class _Tp> void as_const(const _Tp&&) = delete; struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { }; #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) -extern const piecewise_construct_t piecewise_construct;// = piecewise_construct_t(); +extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;// = piecewise_construct_t(); #else /* _LIBCPP_INLINE_VAR */ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); #endif #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) +template <class, class> struct __non_trivially_copyable_base { _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY __non_trivially_copyable_base() _NOEXCEPT {} @@ -313,7 +315,7 @@ struct __non_trivially_copyable_base { template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS pair #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) -: private __non_trivially_copyable_base +: private __non_trivially_copyable_base<_T1, _T2> #endif { typedef _T1 first_type; @@ -408,13 +410,17 @@ struct _LIBCPP_TEMPLATE_VIS pair _CheckArgsDep<_Dummy>::template __enable_default<_T1, _T2>() > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - pair() : first(), second() {} + pair() _NOEXCEPT_(is_nothrow_default_constructible<first_type>::value && + is_nothrow_default_constructible<second_type>::value) + : first(), second() {} template <bool _Dummy = true, _EnableB< _CheckArgsDep<_Dummy>::template __enable_explicit<_T1 const&, _T2 const&>() > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit pair(_T1 const& __t1, _T2 const& __t2) + _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && + is_nothrow_copy_constructible<second_type>::value) : first(__t1), second(__t2) {} template<bool _Dummy = true, _EnableB< @@ -422,6 +428,8 @@ struct _LIBCPP_TEMPLATE_VIS pair > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 pair(_T1 const& __t1, _T2 const& __t2) + _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && + is_nothrow_copy_constructible<second_type>::value) : first(__t1), second(__t2) {} template<class _U1, class _U2, _EnableB< @@ -429,6 +437,8 @@ struct _LIBCPP_TEMPLATE_VIS pair > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit pair(_U1&& __u1, _U2&& __u2) + _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && + is_nothrow_constructible<second_type, _U2>::value)) : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} template<class _U1, class _U2, _EnableB< @@ -436,6 +446,8 @@ struct _LIBCPP_TEMPLATE_VIS pair > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 pair(_U1&& __u1, _U2&& __u2) + _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && + is_nothrow_constructible<second_type, _U2>::value)) : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} template<class _U1, class _U2, _EnableB< @@ -443,6 +455,8 @@ struct _LIBCPP_TEMPLATE_VIS pair > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit pair(pair<_U1, _U2> const& __p) + _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && + is_nothrow_constructible<second_type, _U2 const&>::value)) : first(__p.first), second(__p.second) {} template<class _U1, class _U2, _EnableB< @@ -450,6 +464,8 @@ struct _LIBCPP_TEMPLATE_VIS pair > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 pair(pair<_U1, _U2> const& __p) + _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && + is_nothrow_constructible<second_type, _U2 const&>::value)) : first(__p.first), second(__p.second) {} template<class _U1, class _U2, _EnableB< @@ -457,6 +473,8 @@ struct _LIBCPP_TEMPLATE_VIS pair > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit pair(pair<_U1, _U2>&&__p) + _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && + is_nothrow_constructible<second_type, _U2&&>::value)) : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} template<class _U1, class _U2, _EnableB< @@ -464,6 +482,8 @@ struct _LIBCPP_TEMPLATE_VIS pair > = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 pair(pair<_U1, _U2>&& __p) + _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && + is_nothrow_constructible<second_type, _U2&&>::value)) : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} template<class _Tuple, _EnableB< @@ -486,6 +506,8 @@ struct _LIBCPP_TEMPLATE_VIS pair _LIBCPP_INLINE_VISIBILITY pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) + _NOEXCEPT_((is_nothrow_constructible<first_type, _Args1...>::value && + is_nothrow_constructible<second_type, _Args2...>::value)) : pair(__pc, __first_args, __second_args, typename __make_tuple_indices<sizeof...(_Args1)>::type(), typename __make_tuple_indices<sizeof...(_Args2) >::type()) {} @@ -615,32 +637,37 @@ swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) __x.swap(__y); } -#ifndef _LIBCPP_CXX03_LANG +template <class _Tp> +struct __unwrap_reference { typedef _Tp type; }; template <class _Tp> -struct __make_pair_return_impl -{ - typedef _Tp type; -}; +struct __unwrap_reference<reference_wrapper<_Tp> > { typedef _Tp& type; }; +#if _LIBCPP_STD_VER > 17 template <class _Tp> -struct __make_pair_return_impl<reference_wrapper<_Tp>> -{ - typedef _Tp& type; -}; +struct unwrap_reference : __unwrap_reference<_Tp> { }; template <class _Tp> -struct __make_pair_return -{ - typedef typename __make_pair_return_impl<typename decay<_Tp>::type>::type type; -}; +struct unwrap_ref_decay : unwrap_reference<typename decay<_Tp>::type> { }; +#endif // > C++17 + +template <class _Tp> +struct __unwrap_ref_decay +#if _LIBCPP_STD_VER > 17 + : unwrap_ref_decay<_Tp> +#else + : __unwrap_reference<typename decay<_Tp>::type> +#endif +{ }; + +#ifndef _LIBCPP_CXX03_LANG template <class _T1, class _T2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 -pair<typename __make_pair_return<_T1>::type, typename __make_pair_return<_T2>::type> +pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> make_pair(_T1&& __t1, _T2&& __t2) { - return pair<typename __make_pair_return<_T1>::type, typename __make_pair_return<_T2>::type> + return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> (_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2)); } @@ -657,7 +684,7 @@ make_pair(_T1 __x, _T2 __y) #endif // _LIBCPP_CXX03_LANG template <class _T1, class _T2> - class _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > + struct _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > : public integral_constant<size_t, 2> {}; template <size_t _Ip, class _T1, class _T2> @@ -988,8 +1015,10 @@ __murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) { case 3: __h ^= __data[2] << 16; + _LIBCPP_FALLTHROUGH(); case 2: __h ^= __data[1] << 8; + _LIBCPP_FALLTHROUGH(); case 1: __h ^= __data[0]; __h *= __m; @@ -1453,7 +1482,7 @@ struct _LIBCPP_TEMPLATE_VIS hash<float> size_t operator()(float __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash - if (__v == 0) + if (__v == 0.0) return 0; return __scalar_hash<float>::operator()(__v); } @@ -1467,7 +1496,7 @@ struct _LIBCPP_TEMPLATE_VIS hash<double> size_t operator()(double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash - if (__v == 0) + if (__v == 0.0) return 0; return __scalar_hash<double>::operator()(__v); } @@ -1481,7 +1510,7 @@ struct _LIBCPP_TEMPLATE_VIS hash<long double> size_t operator()(long double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash - if (__v == 0) + if (__v == 0.0) return 0; #if defined(__i386__) // Zero out padding bits diff --git a/lib/libcxx/include/valarray b/lib/libcxx/include/valarray index 8d3892ad35d..07f38c81150 100644 --- a/lib/libcxx/include/valarray +++ b/lib/libcxx/include/valarray @@ -803,7 +803,7 @@ public: // construct/destroy: _LIBCPP_INLINE_VISIBILITY valarray() : __begin_(0), __end_(0) {} - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 explicit valarray(size_t __n); _LIBCPP_INLINE_VISIBILITY valarray(const value_type& __x, size_t __n); @@ -818,7 +818,7 @@ public: valarray(const gslice_array<value_type>& __ga); valarray(const mask_array<value_type>& __ma); valarray(const indirect_array<value_type>& __ia); - inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 ~valarray(); // assignment: @@ -1054,7 +1054,8 @@ private: const _Up* end(const valarray<_Up>& __v); - void __clear(); + _LIBCPP_INLINE_VISIBILITY + void __clear(size_t __capacity); valarray& __assign_range(const value_type* __f, const value_type* __l); }; @@ -2739,7 +2740,7 @@ __val_expr<_ValExpr>::operator valarray<__val_expr::result_type>() const __r.__begin_ = __r.__end_ = static_cast<result_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(result_type), __alignof(result_type))); + _VSTD::__libcpp_allocate(__n * sizeof(result_type), _LIBCPP_ALIGNOF(result_type))); for (size_t __i = 0; __i != __n; ++__r.__end_, ++__i) ::new (__r.__end_) result_type(__expr_[__i]); } @@ -2757,18 +2758,18 @@ valarray<_Tp>::valarray(size_t __n) if (__n) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS - for (; __n; --__n, ++__end_) + for (size_t __n_left = __n; __n_left; --__n_left, ++__end_) ::new (__end_) value_type(); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2792,18 +2793,18 @@ valarray<_Tp>::valarray(const value_type* __p, size_t __n) if (__n) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS - for (; __n; ++__end_, ++__p, --__n) + for (size_t __n_left = __n; __n_left; ++__end_, ++__p, --__n_left) ::new (__end_) value_type(*__p); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2818,7 +2819,7 @@ valarray<_Tp>::valarray(const valarray& __v) if (__v.size()) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__v.size() * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__v.size() * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2829,7 +2830,7 @@ valarray<_Tp>::valarray(const valarray& __v) } catch (...) { - __clear(); + __clear(__v.size()); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2852,22 +2853,23 @@ valarray<_Tp>::valarray(initializer_list<value_type> __il) : __begin_(0), __end_(0) { - size_t __n = __il.size(); + const size_t __n = __il.size(); if (__n) { __begin_ = __end_ = static_cast<value_type*>( -_VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); +_VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS - for (const value_type* __p = __il.begin(); __n; ++__end_, ++__p, --__n) + size_t __n_left = __n; + for (const value_type* __p = __il.begin(); __n_left; ++__end_, ++__p, --__n_left) ::new (__end_) value_type(*__p); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2881,22 +2883,23 @@ valarray<_Tp>::valarray(const slice_array<value_type>& __sa) : __begin_(0), __end_(0) { - size_t __n = __sa.__size_; + const size_t __n = __sa.__size_; if (__n) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS - for (const value_type* __p = __sa.__vp_; __n; ++__end_, __p += __sa.__stride_, --__n) + size_t __n_left = __n; + for (const value_type* __p = __sa.__vp_; __n_left; ++__end_, __p += __sa.__stride_, --__n_left) ::new (__end_) value_type(*__p); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2908,11 +2911,11 @@ valarray<_Tp>::valarray(const gslice_array<value_type>& __ga) : __begin_(0), __end_(0) { - size_t __n = __ga.__1d_.size(); + const size_t __n = __ga.__1d_.size(); if (__n) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2926,7 +2929,7 @@ valarray<_Tp>::valarray(const gslice_array<value_type>& __ga) } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2938,11 +2941,11 @@ valarray<_Tp>::valarray(const mask_array<value_type>& __ma) : __begin_(0), __end_(0) { - size_t __n = __ma.__1d_.size(); + const size_t __n = __ma.__1d_.size(); if (__n) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2956,7 +2959,7 @@ valarray<_Tp>::valarray(const mask_array<value_type>& __ma) } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2968,11 +2971,11 @@ valarray<_Tp>::valarray(const indirect_array<value_type>& __ia) : __begin_(0), __end_(0) { - size_t __n = __ia.__1d_.size(); + const size_t __n = __ia.__1d_.size(); if (__n) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2986,7 +2989,7 @@ valarray<_Tp>::valarray(const indirect_array<value_type>& __ia) } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS @@ -2997,7 +3000,7 @@ template <class _Tp> inline valarray<_Tp>::~valarray() { - __clear(); + __clear(size()); } template <class _Tp> @@ -3007,9 +3010,9 @@ valarray<_Tp>::__assign_range(const value_type* __f, const value_type* __l) size_t __n = __l - __f; if (size() != __n) { - __clear(); + __clear(size()); __begin_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); __end_ = __begin_ + __n; _VSTD::uninitialized_copy(__f, __l, __begin_); } else { @@ -3034,7 +3037,7 @@ inline valarray<_Tp>& valarray<_Tp>::operator=(valarray&& __v) _NOEXCEPT { - __clear(); + __clear(size()); __begin_ = __v.__begin_; __end_ = __v.__end_; __v.__begin_ = nullptr; @@ -3265,7 +3268,7 @@ valarray<_Tp>::operator+() const __r.__begin_ = __r.__end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(+*__p); } @@ -3283,7 +3286,7 @@ valarray<_Tp>::operator-() const __r.__begin_ = __r.__end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(-*__p); } @@ -3301,7 +3304,7 @@ valarray<_Tp>::operator~() const __r.__begin_ = __r.__end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(~*__p); } @@ -3318,7 +3321,7 @@ valarray<_Tp>::operator!() const { __r.__begin_ = __r.__end_ = - static_cast<bool*>(_VSTD::__libcpp_allocate(__n * sizeof(bool), __alignof(bool))); + static_cast<bool*>(_VSTD::__libcpp_allocate(__n * sizeof(bool), _LIBCPP_ALIGNOF(bool))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) bool(!*__p); } @@ -3639,7 +3642,7 @@ valarray<_Tp>::shift(int __i) const __r.__begin_ = __r.__end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); const value_type* __sb; value_type* __tb; value_type* __te; @@ -3678,7 +3681,7 @@ valarray<_Tp>::cshift(int __i) const __r.__begin_ = __r.__end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); __i %= static_cast<int>(__n); const value_type* __m = __i >= 0 ? __begin_ + __i : __end_ + __i; for (const value_type* __s = __m; __s != __end_; ++__r.__end_, ++__s) @@ -3700,7 +3703,7 @@ valarray<_Tp>::apply(value_type __f(value_type)) const __r.__begin_ = __r.__end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(__f(*__p)); } @@ -3718,7 +3721,7 @@ valarray<_Tp>::apply(value_type __f(const value_type&)) const __r.__begin_ = __r.__end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(__f(*__p)); } @@ -3726,38 +3729,38 @@ valarray<_Tp>::apply(value_type __f(const value_type&)) const } template <class _Tp> -void -valarray<_Tp>::__clear() +inline +void valarray<_Tp>::__clear(size_t __capacity) { - if (__begin_ != nullptr) - { - while (__end_ != __begin_) - (--__end_)->~value_type(); - _VSTD::__libcpp_deallocate(__begin_, __alignof(value_type)); - __begin_ = __end_ = nullptr; - } + if (__begin_ != nullptr) + { + while (__end_ != __begin_) + (--__end_)->~value_type(); + _VSTD::__libcpp_deallocate(__begin_, __capacity * sizeof(value_type), _LIBCPP_ALIGNOF(value_type)); + __begin_ = __end_ = nullptr; + } } template <class _Tp> void valarray<_Tp>::resize(size_t __n, value_type __x) { - __clear(); + __clear(size()); if (__n) { __begin_ = __end_ = static_cast<value_type*>( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS - for (; __n; --__n, ++__end_) + for (size_t __n_left = __n; __n_left; --__n_left, ++__end_) ::new (__end_) value_type(__x); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - __clear(); + __clear(__n); throw; } #endif // _LIBCPP_NO_EXCEPTIONS diff --git a/lib/libcxx/include/variant b/lib/libcxx/include/variant index f9098f42249..a4339de6cde 100644 --- a/lib/libcxx/include/variant +++ b/lib/libcxx/include/variant @@ -23,8 +23,8 @@ namespace std { // 20.7.2.1, constructors constexpr variant() noexcept(see below); - variant(const variant&); - variant(variant&&) noexcept(see below); + variant(const variant&); // constexpr in C++20 + variant(variant&&) noexcept(see below); // constexpr in C++20 template <class T> constexpr variant(T&&) noexcept(see below); @@ -46,8 +46,8 @@ namespace std { ~variant(); // 20.7.2.3, assignment - variant& operator=(const variant&); - variant& operator=(variant&&) noexcept(see below); + variant& operator=(const variant&); // constexpr in C++20 + variant& operator=(variant&&) noexcept(see below); // constexpr in C++20 template <class T> variant& operator=(T&&) noexcept(see below); @@ -208,6 +208,7 @@ namespace std { #include <type_traits> #include <utility> #include <limits> +#include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -218,7 +219,7 @@ _LIBCPP_PUSH_MACROS namespace std { // explicitly not using versioning namespace -class _LIBCPP_EXCEPTION_ABI bad_variant_access : public exception { +class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS bad_variant_access : public exception { public: virtual const char* what() const _NOEXCEPT; }; @@ -231,6 +232,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS void __throw_bad_variant_access() { #ifndef _LIBCPP_NO_EXCEPTIONS throw bad_variant_access(); @@ -1064,7 +1066,7 @@ public: #ifndef _LIBCPP_NO_EXCEPTIONS // EXTENSION: When the move construction of `__lhs` into `__rhs` throws // and `__tmp` is nothrow move constructible then we move `__tmp` back - // into `__rhs` and provide the strong exception safety guarentee. + // into `__rhs` and provide the strong exception safety guarantee. try { this->__generic_construct(*__rhs, _VSTD::move(*__lhs)); } catch (...) { @@ -1320,7 +1322,8 @@ constexpr bool holds_alternative(const variant<_Types...>& __v) noexcept { template <size_t _Ip, class _Vp> inline _LIBCPP_INLINE_VISIBILITY -static constexpr auto&& __generic_get(_Vp&& __v) { +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS +constexpr auto&& __generic_get(_Vp&& __v) { using __variant_detail::__access::__variant; if (!__holds_alternative<_Ip>(__v)) { __throw_bad_variant_access(); @@ -1330,6 +1333,7 @@ static constexpr auto&& __generic_get(_Vp&& __v) { template <size_t _Ip, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr variant_alternative_t<_Ip, variant<_Types...>>& get( variant<_Types...>& __v) { static_assert(_Ip < sizeof...(_Types)); @@ -1339,6 +1343,7 @@ constexpr variant_alternative_t<_Ip, variant<_Types...>>& get( template <size_t _Ip, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr variant_alternative_t<_Ip, variant<_Types...>>&& get( variant<_Types...>&& __v) { static_assert(_Ip < sizeof...(_Types)); @@ -1348,6 +1353,7 @@ constexpr variant_alternative_t<_Ip, variant<_Types...>>&& get( template <size_t _Ip, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const variant_alternative_t<_Ip, variant<_Types...>>& get( const variant<_Types...>& __v) { static_assert(_Ip < sizeof...(_Types)); @@ -1357,6 +1363,7 @@ constexpr const variant_alternative_t<_Ip, variant<_Types...>>& get( template <size_t _Ip, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const variant_alternative_t<_Ip, variant<_Types...>>&& get( const variant<_Types...>&& __v) { static_assert(_Ip < sizeof...(_Types)); @@ -1366,6 +1373,7 @@ constexpr const variant_alternative_t<_Ip, variant<_Types...>>&& get( template <class _Tp, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Tp& get(variant<_Types...>& __v) { static_assert(!is_void_v<_Tp>); return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); @@ -1373,6 +1381,7 @@ constexpr _Tp& get(variant<_Types...>& __v) { template <class _Tp, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr _Tp&& get(variant<_Types...>&& __v) { static_assert(!is_void_v<_Tp>); return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>( @@ -1381,6 +1390,7 @@ constexpr _Tp&& get(variant<_Types...>&& __v) { template <class _Tp, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const _Tp& get(const variant<_Types...>& __v) { static_assert(!is_void_v<_Tp>); return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); @@ -1388,6 +1398,7 @@ constexpr const _Tp& get(const variant<_Types...>& __v) { template <class _Tp, class... _Types> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr const _Tp&& get(const variant<_Types...>&& __v) { static_assert(!is_void_v<_Tp>); return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>( @@ -1437,6 +1448,16 @@ get_if(const variant<_Types...>* __v) noexcept { return _VSTD::get_if<__find_exactly_one_t<_Tp, _Types...>::value>(__v); } +template <class _Operator> +struct __convert_to_bool { + template <class _T1, class _T2> + _LIBCPP_INLINE_VISIBILITY constexpr bool operator()(_T1 && __t1, _T2&& __t2) const { + static_assert(std::is_convertible<decltype(_Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2))), bool>::value, + "the relational operator does not return a type which is implicitly convertible to bool"); + return _Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2)); + } +}; + template <class... _Types> inline _LIBCPP_INLINE_VISIBILITY constexpr bool operator==(const variant<_Types...>& __lhs, @@ -1444,7 +1465,7 @@ constexpr bool operator==(const variant<_Types...>& __lhs, using __variant_detail::__visitation::__variant; if (__lhs.index() != __rhs.index()) return false; if (__lhs.valueless_by_exception()) return true; - return __variant::__visit_value_at(__lhs.index(), equal_to<>{}, __lhs, __rhs); + return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<equal_to<>>{}, __lhs, __rhs); } template <class... _Types> @@ -1455,7 +1476,7 @@ constexpr bool operator!=(const variant<_Types...>& __lhs, if (__lhs.index() != __rhs.index()) return true; if (__lhs.valueless_by_exception()) return false; return __variant::__visit_value_at( - __lhs.index(), not_equal_to<>{}, __lhs, __rhs); + __lhs.index(), __convert_to_bool<not_equal_to<>>{}, __lhs, __rhs); } template <class... _Types> @@ -1467,7 +1488,7 @@ constexpr bool operator<(const variant<_Types...>& __lhs, if (__lhs.valueless_by_exception()) return true; if (__lhs.index() < __rhs.index()) return true; if (__lhs.index() > __rhs.index()) return false; - return __variant::__visit_value_at(__lhs.index(), less<>{}, __lhs, __rhs); + return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<less<>>{}, __lhs, __rhs); } template <class... _Types> @@ -1479,7 +1500,7 @@ constexpr bool operator>(const variant<_Types...>& __lhs, if (__rhs.valueless_by_exception()) return true; if (__lhs.index() > __rhs.index()) return true; if (__lhs.index() < __rhs.index()) return false; - return __variant::__visit_value_at(__lhs.index(), greater<>{}, __lhs, __rhs); + return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<greater<>>{}, __lhs, __rhs); } template <class... _Types> @@ -1492,7 +1513,7 @@ constexpr bool operator<=(const variant<_Types...>& __lhs, if (__lhs.index() < __rhs.index()) return true; if (__lhs.index() > __rhs.index()) return false; return __variant::__visit_value_at( - __lhs.index(), less_equal<>{}, __lhs, __rhs); + __lhs.index(), __convert_to_bool<less_equal<>>{}, __lhs, __rhs); } template <class... _Types> @@ -1505,11 +1526,12 @@ constexpr bool operator>=(const variant<_Types...>& __lhs, if (__lhs.index() > __rhs.index()) return true; if (__lhs.index() < __rhs.index()) return false; return __variant::__visit_value_at( - __lhs.index(), greater_equal<>{}, __lhs, __rhs); + __lhs.index(), __convert_to_bool<greater_equal<>>{}, __lhs, __rhs); } template <class _Visitor, class... _Vs> inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { using __variant_detail::__visitation::__variant; bool __results[] = {__vs.valueless_by_exception()...}; diff --git a/lib/libcxx/include/vector b/lib/libcxx/include/vector index 0f5006f3756..edb6d3e09f5 100644 --- a/lib/libcxx/include/vector +++ b/lib/libcxx/include/vector @@ -261,6 +261,11 @@ template <class T, class Allocator> void swap(vector<T,Allocator>& x, vector<T,Allocator>& y) noexcept(noexcept(x.swap(y))); +template <class T, class Allocator, class U> + void erase(vector<T, Allocator>& c, const U& value); // C++20 +template <class T, class Allocator, class Predicate> + void erase_if(vector<T, Allocator>& c, Predicate pred); // C++20 + } // std */ @@ -276,6 +281,7 @@ void swap(vector<T,Allocator>& x, vector<T,Allocator>& y) #include <stdexcept> #include <algorithm> #include <cstring> +#include <version> #include <__split_buffer> #include <__functional_base> @@ -540,13 +546,14 @@ public: value_type, typename iterator_traits<_ForwardIterator>::reference>::value>::type* = 0); -#if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY ~vector() { + __annotate_delete(); +#if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__erase_c(this); - } #endif + } vector(const vector& __x); vector(const vector& __x, const allocator_type& __a); @@ -2453,7 +2460,7 @@ private: void __vdeallocate() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY static size_type __align_it(size_type __new_size) _NOEXCEPT - {return __new_size + (__bits_per_word-1) & ~((size_type)__bits_per_word-1);}; + {return __new_size + (__bits_per_word-1) & ~((size_type)__bits_per_word-1);} _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; _LIBCPP_INLINE_VISIBILITY void __construct_at_end(size_type __n, bool __x); template <class _ForwardIterator> @@ -2604,6 +2611,13 @@ vector<bool, _Allocator>::__construct_at_end(size_type __n, bool __x) { size_type __old_size = this->__size_; this->__size_ += __n; + if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) + { + if (this->__size_ <= __bits_per_word) + this->__begin_[0] = __storage_type(0); + else + this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); + } _VSTD::fill_n(__make_iter(__old_size), __n, __x); } @@ -2618,6 +2632,13 @@ vector<bool, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardI { size_type __old_size = this->__size_; this->__size_ += _VSTD::distance(__first, __last); + if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) + { + if (this->__size_ <= __bits_per_word) + this->__begin_[0] = __storage_type(0); + else + this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); + } _VSTD::copy(__first, __last, __make_iter(__old_size)); } @@ -3392,6 +3413,18 @@ swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) __x.swap(__y); } +#if _LIBCPP_STD_VER > 17 +template <class _Tp, class _Allocator, class _Up> +inline _LIBCPP_INLINE_VISIBILITY +void erase(vector<_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(vector<_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 diff --git a/lib/libcxx/include/version b/lib/libcxx/include/version index 23a872ea85a..e37afc44860 100644 --- a/lib/libcxx/include/version +++ b/lib/libcxx/include/version @@ -12,7 +12,105 @@ #define _LIBCPP_VERSIONH /* - version synopsis + version synopsis + +Macro name Value Headers +__cpp_lib_addressof_constexpr 201603L <memory> +__cpp_lib_allocator_traits_is_always_equal 201411L <memory> <scoped_allocator> <string> + <deque> <forward_list> <list> + <vector> <map> <set> + <unordered_map> <unordered_set> +__cpp_lib_any 201606L <any> +__cpp_lib_apply 201603L <tuple> +__cpp_lib_array_constexpr 201603L <iterator> <array> +__cpp_lib_as_const 201510L <utility> +__cpp_lib_atomic_is_always_lock_free 201603L <atomic> +__cpp_lib_atomic_ref 201806L <atomic> +__cpp_lib_bind_front 201811L <functional> +__cpp_lib_bit_cast 201806L <bit> +__cpp_lib_bool_constant 201505L <type_traits> +__cpp_lib_boyer_moore_searcher 201603L <functional> +__cpp_lib_byte 201603L <cstddef> +__cpp_lib_char8_t 201811L <atomic> <filesystem> <istream> + <limits> <locale> <ostream> + <string> <string_view> +__cpp_lib_chrono 201611L <chrono> +__cpp_lib_chrono_udls 201304L <chrono> +__cpp_lib_clamp 201603L <algorithm> +__cpp_lib_complex_udls 201309L <complex> +__cpp_lib_concepts 201806L <concepts> +__cpp_lib_constexpr_misc 201811L <array> <functional> <iterator> + <string_view> <tuple> <utility> +__cpp_lib_constexpr_swap_algorithms 201806L <algorithm> +__cpp_lib_destroying_delete 201806L <new> +__cpp_lib_enable_shared_from_this 201603L <memory> +__cpp_lib_erase_if 201811L <string> <deque> <forward_list> + <list> <vector> <map> + <set> <unordered_map> <unordered_set> +__cpp_lib_exchange_function 201304L <utility> +__cpp_lib_execution 201603L <execution> +__cpp_lib_filesystem 201703L <filesystem> +__cpp_lib_gcd_lcm 201606L <numeric> +__cpp_lib_generic_associative_lookup 201304L <map> <set> +__cpp_lib_generic_unordered_lookup 201811L <unordered_map> <unordered_set> +__cpp_lib_hardware_interference_size 201703L <new> +__cpp_lib_has_unique_object_representations 201606L <type_traits> +__cpp_lib_hypot 201603L <cmath> +__cpp_lib_incomplete_container_elements 201505L <forward_list> <list> <vector> +__cpp_lib_integer_sequence 201304L <utility> +__cpp_lib_integral_constant_callable 201304L <type_traits> +__cpp_lib_invoke 201411L <functional> +__cpp_lib_is_aggregate 201703L <type_traits> +__cpp_lib_is_constant_evaluated 201811L <type_traits> +__cpp_lib_is_final 201402L <type_traits> +__cpp_lib_is_invocable 201703L <type_traits> +__cpp_lib_is_null_pointer 201309L <type_traits> +__cpp_lib_is_swappable 201603L <type_traits> +__cpp_lib_launder 201606L <new> +__cpp_lib_list_remove_return_type 201806L <forward_list> <list> +__cpp_lib_logical_traits 201510L <type_traits> +__cpp_lib_make_from_tuple 201606L <tuple> +__cpp_lib_make_reverse_iterator 201402L <iterator> +__cpp_lib_make_unique 201304L <memory> +__cpp_lib_map_try_emplace 201411L <map> +__cpp_lib_math_special_functions 201603L <cmath> +__cpp_lib_memory_resource 201603L <memory_resource> +__cpp_lib_node_extract 201606L <map> <set> <unordered_map> + <unordered_set> +__cpp_lib_nonmember_container_access 201411L <iterator> <array> <deque> + <forward_list> <list> <map> + <regex> <set> <string> + <unordered_map> <unordered_set> <vector> +__cpp_lib_not_fn 201603L <functional> +__cpp_lib_null_iterators 201304L <iterator> +__cpp_lib_optional 201606L <optional> +__cpp_lib_parallel_algorithm 201603L <algorithm> <numeric> +__cpp_lib_quoted_string_io 201304L <iomanip> +__cpp_lib_ranges 201811L <algorithm> <functional> <iterator> + <memory> <ranges> +__cpp_lib_raw_memory_algorithms 201606L <memory> +__cpp_lib_result_of_sfinae 201210L <functional> <type_traits> +__cpp_lib_robust_nonmodifying_seq_ops 201304L <algorithm> +__cpp_lib_sample 201603L <algorithm> +__cpp_lib_scoped_lock 201703L <mutex> +__cpp_lib_shared_mutex 201505L <shared_mutex> +__cpp_lib_shared_ptr_arrays 201611L <memory> +__cpp_lib_shared_ptr_weak_type 201606L <memory> +__cpp_lib_shared_timed_mutex 201402L <shared_mutex> +__cpp_lib_string_udls 201304L <string> +__cpp_lib_string_view 201606L <string> <string_view> +__cpp_lib_three_way_comparison 201711L <compare> +__cpp_lib_to_chars 201611L <utility> +__cpp_lib_transformation_trait_aliases 201304L <type_traits> +__cpp_lib_transparent_operators 201510L <functional> + 201210L // C++14 +__cpp_lib_tuple_element_t 201402L <tuple> +__cpp_lib_tuples_by_type 201304L <utility> <tuple> +__cpp_lib_type_trait_variable_templates 201510L <type_traits> +__cpp_lib_uncaught_exceptions 201411L <exception> +__cpp_lib_unordered_map_try_emplace 201411L <unordered_map> +__cpp_lib_variant 201606L <variant> +__cpp_lib_void_t 201411L <type_traits> */ @@ -22,4 +120,113 @@ #pragma GCC system_header #endif -#endif // _LIBCPP_VERSIONH +#if _LIBCPP_STD_VER > 11 +# define __cpp_lib_chrono_udls 201304L +# define __cpp_lib_complex_udls 201309L +# define __cpp_lib_exchange_function 201304L +# define __cpp_lib_generic_associative_lookup 201304L +# define __cpp_lib_integer_sequence 201304L +# define __cpp_lib_integral_constant_callable 201304L +# define __cpp_lib_is_final 201402L +# define __cpp_lib_is_null_pointer 201309L +# define __cpp_lib_make_reverse_iterator 201402L +# define __cpp_lib_make_unique 201304L +# define __cpp_lib_null_iterators 201304L +# define __cpp_lib_quoted_string_io 201304L +# define __cpp_lib_result_of_sfinae 201210L +# define __cpp_lib_robust_nonmodifying_seq_ops 201304L +# if !defined(_LIBCPP_HAS_NO_THREADS) +# define __cpp_lib_shared_timed_mutex 201402L +# endif +# define __cpp_lib_string_udls 201304L +# define __cpp_lib_transformation_trait_aliases 201304L +# define __cpp_lib_transparent_operators 201210L +# define __cpp_lib_tuple_element_t 201402L +# define __cpp_lib_tuples_by_type 201304L +#endif + +#if _LIBCPP_STD_VER > 14 +# if !defined(_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF) +# define __cpp_lib_addressof_constexpr 201603L +# endif +# define __cpp_lib_allocator_traits_is_always_equal 201411L +# define __cpp_lib_any 201606L +# define __cpp_lib_apply 201603L +# define __cpp_lib_array_constexpr 201603L +# define __cpp_lib_as_const 201510L +# if !defined(_LIBCPP_HAS_NO_THREADS) +# define __cpp_lib_atomic_is_always_lock_free 201603L +# endif +# define __cpp_lib_bool_constant 201505L +// # define __cpp_lib_boyer_moore_searcher 201603L +# define __cpp_lib_byte 201603L +# define __cpp_lib_chrono 201611L +# define __cpp_lib_clamp 201603L +# define __cpp_lib_enable_shared_from_this 201603L +// # define __cpp_lib_execution 201603L +# define __cpp_lib_filesystem 201703L +# define __cpp_lib_gcd_lcm 201606L +# define __cpp_lib_hardware_interference_size 201703L +# if defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS) +# define __cpp_lib_has_unique_object_representations 201606L +# endif +# define __cpp_lib_hypot 201603L +# define __cpp_lib_incomplete_container_elements 201505L +# define __cpp_lib_invoke 201411L +# if !defined(_LIBCPP_HAS_NO_IS_AGGREGATE) +# define __cpp_lib_is_aggregate 201703L +# endif +# define __cpp_lib_is_invocable 201703L +# define __cpp_lib_is_swappable 201603L +# define __cpp_lib_launder 201606L +# define __cpp_lib_logical_traits 201510L +# define __cpp_lib_make_from_tuple 201606L +# define __cpp_lib_map_try_emplace 201411L +// # define __cpp_lib_math_special_functions 201603L +// # define __cpp_lib_memory_resource 201603L +# define __cpp_lib_node_extract 201606L +# define __cpp_lib_nonmember_container_access 201411L +# define __cpp_lib_not_fn 201603L +# define __cpp_lib_optional 201606L +// # define __cpp_lib_parallel_algorithm 201603L +# define __cpp_lib_raw_memory_algorithms 201606L +# define __cpp_lib_sample 201603L +# define __cpp_lib_scoped_lock 201703L +# if !defined(_LIBCPP_HAS_NO_THREADS) +# define __cpp_lib_shared_mutex 201505L +# endif +// # define __cpp_lib_shared_ptr_arrays 201611L +# define __cpp_lib_shared_ptr_weak_type 201606L +# define __cpp_lib_string_view 201606L +// # define __cpp_lib_to_chars 201611L +# undef __cpp_lib_transparent_operators +# define __cpp_lib_transparent_operators 201510L +# define __cpp_lib_type_trait_variable_templates 201510L +# define __cpp_lib_uncaught_exceptions 201411L +# define __cpp_lib_unordered_map_try_emplace 201411L +# define __cpp_lib_variant 201606L +# define __cpp_lib_void_t 201411L +#endif + +#if _LIBCPP_STD_VER > 17 +# if !defined(_LIBCPP_HAS_NO_THREADS) +// # define __cpp_lib_atomic_ref 201806L +# endif +// # define __cpp_lib_bind_front 201811L +// # define __cpp_lib_bit_cast 201806L +# if !defined(_LIBCPP_NO_HAS_CHAR8_T) +# define __cpp_lib_char8_t 201811L +# endif +// # define __cpp_lib_concepts 201806L +// # define __cpp_lib_constexpr_misc 201811L +// # define __cpp_lib_constexpr_swap_algorithms 201806L +// # define __cpp_lib_destroying_delete 201806L +# define __cpp_lib_erase_if 201811L +// # define __cpp_lib_generic_unordered_lookup 201811L +// # define __cpp_lib_is_constant_evaluated 201811L +// # define __cpp_lib_list_remove_return_type 201806L +// # define __cpp_lib_ranges 201811L +// # define __cpp_lib_three_way_comparison 201711L +#endif + +#endif // _LIBCPP_VERSIONH diff --git a/lib/libcxx/lib/CMakeLists.txt b/lib/libcxx/lib/CMakeLists.txt index e068edc8a7a..24489e8fb5e 100644 --- a/lib/libcxx/lib/CMakeLists.txt +++ b/lib/libcxx/lib/CMakeLists.txt @@ -41,14 +41,14 @@ add_library_flags_if(LIBCXX_COVERAGE_LIBRARY "${LIBCXX_COVERAGE_LIBRARY}") if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR LIBCXX_CXX_ABI_LIBNAME STREQUAL "default")) - set(LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY ON) + set(LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS ON) endif() if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) add_library_flags("-Wl,--whole-archive" "-Wl,-Bstatic") add_library_flags("${LIBCXX_CXX_ABI_LIBRARY}") add_library_flags("-Wl,-Bdynamic" "-Wl,--no-whole-archive") -elseif (LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY) +elseif (LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS) add_library_flags("${LIBCXX_CXX_ABI_LIBRARY}") else () add_interface_library("${LIBCXX_CXX_ABI_LIBRARY}") @@ -129,7 +129,7 @@ if (LIBCXX_TARGETING_MSVC) add_library_flags(iso_stdio_wide_specifiers) endif() -if (LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY) +if (LIBCXX_OSX_REEXPORT_LIBCXXABI_SYMBOLS) if (NOT DEFINED LIBCXX_LIBCPPABI_VERSION) set(LIBCXX_LIBCPPABI_VERSION "2") # Default value execute_process( @@ -149,80 +149,95 @@ if (LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY) endif() if ( CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.6" ) - add_definitions(-D__STRICT_ANSI__) - add_link_flags( - "-compatibility_version 1" - "-current_version 1" - "-install_name /usr/lib/libc++.1.dylib" - "-Wl,-reexport_library,/usr/lib/libc++abi.dylib" - "-Wl,-unexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++unexp.exp" - "/usr/lib/libSystem.B.dylib") + message(FATAL_ERROR "Mac OSX 10.6 is not supported anymore as a deployment " + "target. If you need support for this, please contact " + "the libc++ maintainers.") else() - if (DEFINED CMAKE_OSX_SYSROOT AND NOT CMAKE_OSX_SYSROOT STREQUAL "") - list(FIND CMAKE_OSX_ARCHITECTURES "armv7" OSX_HAS_ARMV7) - if (NOT OSX_HAS_ARMV7 EQUAL -1) - set(OSX_RE_EXPORT_LINE - "${CMAKE_OSX_SYSROOT}/usr/lib/libc++abi.dylib" - "-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++sjlj-abi.exp") - else() - set(OSX_RE_EXPORT_LINE - "-Wl,-reexport_library,${CMAKE_OSX_SYSROOT}/usr/lib/libc++abi.dylib") - endif() + if ("armv7" IN_LIST CMAKE_OSX_ARCHITECTURES) + set(RE_EXPORT_LIST "${CMAKE_CURRENT_SOURCE_DIR}/libc++sjlj-abi.exp") else() - set(OSX_RE_EXPORT_LINE "/usr/lib/libc++abi.dylib -Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++abi${LIBCXX_LIBCPPABI_VERSION}.exp") - if (NOT LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) - add_link_flags("/usr/lib/libc++abi.dylib -Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++abi-new-delete.exp") - endif() + set(RE_EXPORT_LIST "${CMAKE_CURRENT_SOURCE_DIR}/libc++abi${LIBCXX_LIBCPPABI_VERSION}.exp") endif() add_link_flags( "-compatibility_version 1" "-install_name /usr/lib/libc++.1.dylib" - "-Wl,-unexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++unexp.exp" - "${OSX_RE_EXPORT_LINE}" - "-Wl,-force_symbols_not_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/notweak.exp" - "-Wl,-force_symbols_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/weak.exp") + "-Wl,-unexported_symbols_list,\"${CMAKE_CURRENT_SOURCE_DIR}/libc++unexp.exp\"" + "-Wl,-reexported_symbols_list,\"${RE_EXPORT_LIST}\"" + "-Wl,-force_symbols_not_weak_list,\"${CMAKE_CURRENT_SOURCE_DIR}/notweak.exp\"" + "-Wl,-force_symbols_weak_list,\"${CMAKE_CURRENT_SOURCE_DIR}/weak.exp\"") + + if (NOT LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) + add_link_flags("-Wl,-reexported_symbols_list,\"${CMAKE_CURRENT_SOURCE_DIR}/libc++abi-new-delete.exp\"") + endif() endif() endif() split_list(LIBCXX_COMPILE_FLAGS) split_list(LIBCXX_LINK_FLAGS) -# Add an object library that contains the compiled source files. -add_library(cxx_objects OBJECT ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) -if(LIBCXX_CXX_ABI_HEADER_TARGET) - add_dependencies(cxx_objects ${LIBCXX_CXX_ABI_HEADER_TARGET}) -endif() -if(WIN32 AND NOT MINGW) - target_compile_definitions(cxx_objects - PRIVATE - # Ignore the -MSC_VER mismatch, as we may build - # with a different compatibility version. - _ALLOW_MSC_VER_MISMATCH - # Don't check the msvcprt iterator debug levels - # as we will define the iterator types; libc++ - # uses a different macro to identify the debug - # level. - _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH - # We are building the c++ runtime, don't pull in - # msvcprt. - _CRTBLD - # Don't warn on the use of "deprecated" - # "insecure" functions which are standards - # specified. - _CRT_SECURE_NO_WARNINGS - # Use the ISO conforming behaviour for conversion - # in printf, scanf. - _CRT_STDIO_ISO_WIDE_SPECIFIERS) -endif() +macro(cxx_object_library name) + cmake_parse_arguments(ARGS "" "" "DEFINES;FLAGS" ${ARGN}) -set_target_properties(cxx_objects - PROPERTIES - COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" -) + # Add an object library that contains the compiled source files. + add_library(${name} OBJECT ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) + if(LIBCXX_CXX_ABI_HEADER_TARGET) + add_dependencies(${name} ${LIBCXX_CXX_ABI_HEADER_TARGET}) + endif() + if(WIN32 AND NOT MINGW) + target_compile_definitions(${name} + PRIVATE + # Ignore the -MSC_VER mismatch, as we may build + # with a different compatibility version. + _ALLOW_MSC_VER_MISMATCH + # Don't check the msvcprt iterator debug levels + # as we will define the iterator types; libc++ + # uses a different macro to identify the debug + # level. + _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH + # We are building the c++ runtime, don't pull in + # msvcprt. + _CRTBLD + # Don't warn on the use of "deprecated" + # "insecure" functions which are standards + # specified. + _CRT_SECURE_NO_WARNINGS + # Use the ISO conforming behaviour for conversion + # in printf, scanf. + _CRT_STDIO_ISO_WIDE_SPECIFIERS) + endif() + + if(ARGS_DEFINES) + target_compile_definitions(${name} PRIVATE ${ARGS_DEFINES}) + endif() + + set_target_properties(${name} + PROPERTIES + COMPILE_FLAGS ${LIBCXX_COMPILE_FLAGS} + ) + + if(ARGS_FLAGS) + target_compile_options(${name} PRIVATE ${ARGS_FLAGS}) + endif() +endmacro() + +if(LIBCXX_HERMETIC_STATIC_LIBRARY) + append_flags_if_supported(CXX_STATIC_OBJECTS_FLAGS -fvisibility=hidden) + append_flags_if_supported(CXX_STATIC_OBJECTS_FLAGS -fvisibility-global-new-delete-hidden) + cxx_object_library(cxx_static_objects + DEFINES _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS + FLAGS ${CXX_STATIC_OBJECTS_FLAGS}) + cxx_object_library(cxx_shared_objects) + set(cxx_static_sources $<TARGET_OBJECTS:cxx_static_objects>) + set(cxx_shared_sources $<TARGET_OBJECTS:cxx_shared_objects>) +else() + cxx_object_library(cxx_objects) + set(cxx_static_sources $<TARGET_OBJECTS:cxx_objects>) + set(cxx_shared_sources $<TARGET_OBJECTS:cxx_objects>) +endif() # Build the shared library. if (LIBCXX_ENABLE_SHARED) - add_library(cxx_shared SHARED $<TARGET_OBJECTS:cxx_objects>) + add_library(cxx_shared SHARED ${cxx_shared_sources}) if(COMMAND llvm_setup_rpath) llvm_setup_rpath(cxx_shared) endif() @@ -249,7 +264,7 @@ endif() # Build the static library. if (LIBCXX_ENABLE_STATIC) - add_library(cxx_static STATIC $<TARGET_OBJECTS:cxx_objects>) + add_library(cxx_static STATIC ${cxx_static_sources}) target_link_libraries(cxx_static ${LIBCXX_LIBRARIES}) set(CMAKE_STATIC_LIBRARY_PREFIX "lib") set_target_properties(cxx_static diff --git a/lib/libcxx/lib/abi/CHANGELOG.TXT b/lib/libcxx/lib/abi/CHANGELOG.TXT index c1237338fbb..38dffd2908b 100644 --- a/lib/libcxx/lib/abi/CHANGELOG.TXT +++ b/lib/libcxx/lib/abi/CHANGELOG.TXT @@ -13,9 +13,121 @@ Afterwards the ABI list should be updated to include the new changes. New entries should be added directly below the "Version" header. ----------- +Version 8.0 +----------- + +* rXXXXX - Remove std::bad_array_length + + The change removes the definition of std::bad_array_length (which never made + it into the standard) from the headers and the dylib. This is technically an + ABI break because the symbols are shipped starting with mac OSX 10.13, however + users couldn't be relying on the functionality because it is marked as being + unavailable using Clang's availability attribute. + + x86_64-apple-darwin16.0 + ----------------------- + Symbol removed: __ZNKSt16bad_array_length4whatEv + Symbol removed: __ZNKSt16bad_array_length4whatEv + Symbol removed: __ZNSt16bad_array_lengthC1Ev + Symbol removed: __ZNSt16bad_array_lengthC1Ev + Symbol removed: __ZNSt16bad_array_lengthC2Ev + Symbol removed: __ZNSt16bad_array_lengthC2Ev + Symbol removed: __ZNSt16bad_array_lengthD0Ev + Symbol removed: __ZNSt16bad_array_lengthD0Ev + Symbol removed: __ZNSt16bad_array_lengthD1Ev + Symbol removed: __ZNSt16bad_array_lengthD1Ev + Symbol removed: __ZNSt16bad_array_lengthD2Ev + Symbol removed: __ZNSt16bad_array_lengthD2Ev + Symbol removed: __ZTISt16bad_array_length + Symbol removed: __ZTISt16bad_array_length + Symbol removed: __ZTSSt16bad_array_length + Symbol removed: __ZTSSt16bad_array_length + Symbol removed: __ZTVSt16bad_array_length + Symbol removed: __ZTVSt16bad_array_length + +* r347395 - Making libc++ build under -fvisibility=hidden on Linux + + The change marks several function templates as hidden. This removes symbols + from the shared library, but this is not an ABI break because it's impossible + for programs linking against libc++.so to actually depend on that symbol. + The reason is that the symbol is exported from the shared library through + an implicit instantiation present in the shared object itself only. Furthermore, + if a user's shared object was implicitly instantiating one of these functions, + marking that symbol as hidden would not be an ABI break for them because none + of their users could actually be using the symbol in their dylib (because + it's an implicit instantiation). + + x86_64-linux-gnu + ---------------- + Symbol removed: _ZNSt3__125__num_get_signed_integralIlEET_PKcS3_Rji + Symbol removed: _ZNSt3__125__num_get_signed_integralIxEET_PKcS3_Rji + Symbol removed: _ZNSt3__127__num_get_unsigned_integralIjEET_PKcS3_Rji + Symbol removed: _ZNSt3__127__num_get_unsigned_integralImEET_PKcS3_Rji + Symbol removed: _ZNSt3__127__num_get_unsigned_integralItEET_PKcS3_Rji + Symbol removed: _ZNSt3__127__num_get_unsigned_integralIyEET_PKcS3_Rji + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIaaEEPaEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIccEEPcEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIddEEPdEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIffEEPfEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIhhEEPhEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIiiEEPiEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIjjEEPjEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIllEEPlEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessImmEEPmEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIssEEPsEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIttEEPtEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIwwEEPwEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIxxEEPxEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__17__sort5IRNS_6__lessIyyEEPyEEjT0_S5_S5_S5_S5_T_ + Symbol removed: _ZNSt3__1plIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_12basic_stringIT_T0_T1_EERKS9_PKS6_ + Symbol removed: _ZSt18make_exception_ptrINSt3__112future_errorEESt13exception_ptrT_ + +* r345260 - Making libc++ build under -fvisibility=hidden on Mac OS + + The change marks __thread_specific_ptr<__thread_struct>::__at_thread_exit(void*) + with hidden visibility. This removes a symbol from the shared libraries, + however this is not an ABI break because it's impossible for programs linking + against libc++.dylib to actually depend on that symbol. The reason is that + the symbol is exported from the shared library through an implicit + instantiation present in the dylib itself only. Furthermore, if a user's + dylib was implicitly instantiating __thread_specific_ptr<T>::__at_thread_exit + (because it's defined in the headers), marking that symbol as hidden would + not be an ABI break for them because none of their users could actually be + using the symbol in their dylib (because it's an implicit instantiation). + + This change also marks __start_std_streams as hidden -- this variable is + only required to initialize the streams, and nobody should depend on it + from outside the dylib. + + x86_64-linux-gnu + ---------------- + Symbol removed: _ZNSt3__121__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv + Symbol removed: _ZNSt3__119__start_std_streamsE + + x86_64-apple-darwin16.0 + ----------------------- + Symbol removed: __ZNSt3__221__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv + Symbol removed: __ZNSt3__119__start_std_streamsE + +----------- Version 7.0 ----------- +* r338479 - Elementary string conversions for integral types + + The change emits __u64toa and __u32toa under std::__1::__itoa. + + x86_64-linux-gnu + ---------------- + Symbol added: _ZNSt3__16__itoa8__u64toaEmPc + Symbol added: _ZNSt3__16__itoa8__u32toaEjPc + + x86_64-apple-darwin16.0 + ----------------------- + Symbol added: __ZNSt3__16__itoa8__u64toaEyPc + Symbol added: __ZNSt3__16__itoa8__u32toaEjPc + + * r333467 - Fix embarrasing typo in uncaught_exceptions. This bug caused __uncaught_exception to be ODR used instead of diff --git a/lib/libcxx/lib/abi/CMakeLists.txt b/lib/libcxx/lib/abi/CMakeLists.txt index e42e96173f5..bb9217f8847 100644 --- a/lib/libcxx/lib/abi/CMakeLists.txt +++ b/lib/libcxx/lib/abi/CMakeLists.txt @@ -1,9 +1,16 @@ if (DEFINED TARGET_TRIPLE) - # Ignore the major, minor, and patchlevel versions of the darwin - # target. - string(REGEX REPLACE "darwin([0-9]+)\\.([0-9]+)\\.([0-9]+)" "darwin" - GENERIC_TARGET_TRIPLE "${TARGET_TRIPLE}") + if (TARGET_TRIPLE MATCHES "darwin") + # Ignore the major, minor, and patchlevel versions of darwin targets. + string(REGEX REPLACE "darwin[0-9]+\\.[0-9]+\\.[0-9]+" "darwin" + GENERIC_TARGET_TRIPLE "${TARGET_TRIPLE}") + elseif(TARGET_TRIPLE MATCHES "freebsd") + # Ignore the major and minor versions of freebsd targets. + string(REGEX REPLACE "freebsd[0-9]+\\.[0-9]+" "freebsd" + GENERIC_TARGET_TRIPLE "${TARGET_TRIPLE}") + else() + set(GENERIC_TARGET_TRIPLE "${TARGET_TRIPLE}") + endif() endif() # Detect if we are building in the same configuration used to generate diff --git a/lib/libcxx/lib/abi/x86_64-apple-darwin.v1.abilist b/lib/libcxx/lib/abi/x86_64-apple-darwin.v1.abilist index 1be950f2e54..65a03496134 100644 --- a/lib/libcxx/lib/abi/x86_64-apple-darwin.v1.abilist +++ b/lib/libcxx/lib/abi/x86_64-apple-darwin.v1.abilist @@ -8,8 +8,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZNKSt13bad_exception4whatEv'} {'type': 'U', 'is_defined': False, 'name': '__ZNKSt13runtime_error4whatEv'} {'type': 'I', 'is_defined': True, 'name': '__ZNKSt13runtime_error4whatEv'} -{'type': 'U', 'is_defined': False, 'name': '__ZNKSt16bad_array_length4whatEv'} -{'type': 'I', 'is_defined': True, 'name': '__ZNKSt16bad_array_length4whatEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt16nested_exception14rethrow_nestedEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt18bad_variant_access4whatEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt19bad_optional_access4whatEv'} @@ -527,16 +525,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZNSt15underflow_errorD1Ev'} {'type': 'U', 'is_defined': False, 'name': '__ZNSt15underflow_errorD2Ev'} {'type': 'I', 'is_defined': True, 'name': '__ZNSt15underflow_errorD2Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthC1Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthC1Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthC2Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthC2Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthD0Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthD0Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthD1Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthD1Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthD2Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthD2Ev'} {'type': 'U', 'is_defined': False, 'name': '__ZNSt16invalid_argumentD0Ev'} {'type': 'I', 'is_defined': True, 'name': '__ZNSt16invalid_argumentD0Ev'} {'type': 'U', 'is_defined': False, 'name': '__ZNSt16invalid_argumentD1Ev'} @@ -1197,13 +1185,11 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD2Ev'} -{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__119__start_std_streamsE', 'size': 0} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__thread_local_dataEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119declare_no_pointersEPcm'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__119piecewise_constructE', 'size': 0} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__120__get_collation_nameEPKc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__120__throw_system_errorEiPKc'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121__throw_runtime_errorEPKc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121__undeclare_reachableEPv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutex4lockEv'} @@ -1282,6 +1268,8 @@ {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__15wcerrE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__15wclogE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_'} @@ -1804,8 +1792,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZTISt14overflow_error'} {'type': 'U', 'is_defined': False, 'name': '__ZTISt15underflow_error'} {'type': 'I', 'is_defined': True, 'name': '__ZTISt15underflow_error'} -{'type': 'U', 'is_defined': False, 'name': '__ZTISt16bad_array_length'} -{'type': 'I', 'is_defined': True, 'name': '__ZTISt16bad_array_length'} {'type': 'U', 'is_defined': False, 'name': '__ZTISt16invalid_argument'} {'type': 'I', 'is_defined': True, 'name': '__ZTISt16invalid_argument'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTISt16nested_exception', 'size': 0} @@ -2059,8 +2045,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZTSSt14overflow_error'} {'type': 'U', 'is_defined': False, 'name': '__ZTSSt15underflow_error'} {'type': 'I', 'is_defined': True, 'name': '__ZTSSt15underflow_error'} -{'type': 'U', 'is_defined': False, 'name': '__ZTSSt16bad_array_length'} -{'type': 'I', 'is_defined': True, 'name': '__ZTSSt16bad_array_length'} {'type': 'U', 'is_defined': False, 'name': '__ZTSSt16invalid_argument'} {'type': 'I', 'is_defined': True, 'name': '__ZTSSt16invalid_argument'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSSt16nested_exception', 'size': 0} @@ -2251,8 +2235,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZTVSt14overflow_error'} {'type': 'U', 'is_defined': False, 'name': '__ZTVSt15underflow_error'} {'type': 'I', 'is_defined': True, 'name': '__ZTVSt15underflow_error'} -{'type': 'U', 'is_defined': False, 'name': '__ZTVSt16bad_array_length'} -{'type': 'I', 'is_defined': True, 'name': '__ZTVSt16bad_array_length'} {'type': 'U', 'is_defined': False, 'name': '__ZTVSt16invalid_argument'} {'type': 'I', 'is_defined': True, 'name': '__ZTVSt16invalid_argument'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVSt16nested_exception', 'size': 0} diff --git a/lib/libcxx/lib/abi/x86_64-apple-darwin.v2.abilist b/lib/libcxx/lib/abi/x86_64-apple-darwin.v2.abilist index 05255a65705..5880a3bfd4f 100644 --- a/lib/libcxx/lib/abi/x86_64-apple-darwin.v2.abilist +++ b/lib/libcxx/lib/abi/x86_64-apple-darwin.v2.abilist @@ -8,8 +8,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZNKSt13bad_exception4whatEv'} {'type': 'U', 'is_defined': False, 'name': '__ZNKSt13runtime_error4whatEv'} {'type': 'I', 'is_defined': True, 'name': '__ZNKSt13runtime_error4whatEv'} -{'type': 'U', 'is_defined': False, 'name': '__ZNKSt16bad_array_length4whatEv'} -{'type': 'I', 'is_defined': True, 'name': '__ZNKSt16bad_array_length4whatEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt16nested_exception14rethrow_nestedEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt18bad_variant_access4whatEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt19bad_optional_access4whatEv'} @@ -180,8 +178,6 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb1EE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb1EE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb1EE9do_lengthER11__mbstate_tPKcS5_m'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215basic_streambufIcNS_11char_traitsIcEEE6getlocEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215basic_streambufIwNS_11char_traitsIwEEE6getlocEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215error_condition7messageEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217bad_function_call4whatEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE11do_groupingEv'} @@ -532,16 +528,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZNSt15underflow_errorD1Ev'} {'type': 'U', 'is_defined': False, 'name': '__ZNSt15underflow_errorD2Ev'} {'type': 'I', 'is_defined': True, 'name': '__ZNSt15underflow_errorD2Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthC1Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthC1Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthC2Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthC2Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthD0Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthD0Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthD1Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthD1Ev'} -{'type': 'U', 'is_defined': False, 'name': '__ZNSt16bad_array_lengthD2Ev'} -{'type': 'I', 'is_defined': True, 'name': '__ZNSt16bad_array_lengthD2Ev'} {'type': 'U', 'is_defined': False, 'name': '__ZNSt16invalid_argumentD0Ev'} {'type': 'I', 'is_defined': True, 'name': '__ZNSt16invalid_argumentD0Ev'} {'type': 'U', 'is_defined': False, 'name': '__ZNSt16invalid_argumentD1Ev'} @@ -812,15 +798,11 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorD2Ev'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__213allocator_argE', 'size': 0} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE3getEPcl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE3getEPclc'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EEc'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE3getERc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE3getEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE4peekEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE4readEPcl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE4swapERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE4syncEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE5seekgENS_4fposI11__mbstate_tEE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE5seekgExNS_8ios_base7seekdirE'} @@ -829,18 +811,12 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE6ignoreEli'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE6sentryC1ERS3_b'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE6sentryC2ERS3_b'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE7getlineEPcl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE7getlineEPclc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE7putbackEc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE8readsomeEPcl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEED0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEED1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEED2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_8ios_baseES5_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_9basic_iosIcS2_EES6_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsEPFRS3_S4_E'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsEPNS_15basic_streambufIcS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERPv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERb'} @@ -855,15 +831,11 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERt'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERx'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERy'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE3getEPwl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE3getEPwlw'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE3getERNS_15basic_streambufIwS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE3getERNS_15basic_streambufIwS2_EEw'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE3getERw'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE3getEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE4peekEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE4readEPwl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE4swapERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE4syncEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE5seekgENS_4fposI11__mbstate_tEE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE5seekgExNS_8ios_base7seekdirE'} @@ -872,18 +844,12 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE6ignoreEli'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE6sentryC1ERS3_b'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE6sentryC2ERS3_b'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE7getlineEPwl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE7getlineEPwlw'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE7putbackEw'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE8readsomeEPwl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEED0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEED1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEED2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_8ios_baseES5_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_9basic_iosIwS2_EES6_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsEPFRS3_S4_E'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsEPNS_15basic_streambufIwS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERPv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERb'} @@ -899,24 +865,15 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERx'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERy'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE4swapERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE5flushEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE5seekpENS_4fposI11__mbstate_tEE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE5seekpExNS_8ios_base7seekdirE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE5tellpEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE5writeEPKcl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE6sentryC1ERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE6sentryC2ERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE6sentryD2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEED0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEED1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEED2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_8ios_baseES5_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_9basic_iosIcS2_EES6_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEPFRS3_S4_E'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEPKv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEPNS_15basic_streambufIcS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEb'} @@ -932,24 +889,15 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEx'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEy'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE3putEw'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE4swapERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE5flushEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE5seekpENS_4fposI11__mbstate_tEE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE5seekpExNS_8ios_base7seekdirE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE5tellpEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE5writeEPKwl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE6sentryC1ERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE6sentryC2ERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE6sentryD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEE6sentryD2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEED0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEED1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEED2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_8ios_baseES5_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_9basic_iosIwS2_EES6_E'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEPFRS3_S4_E'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEPKv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEPNS_15basic_streambufIwS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEb'} @@ -981,9 +929,6 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__shared_countD0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__shared_countD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__shared_countD2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214basic_iostreamIcNS_11char_traitsIcEEE4swapERS3_'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214basic_iostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214basic_iostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214basic_iostreamIcNS_11char_traitsIcEEED0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214basic_iostreamIcNS_11char_traitsIcEEED1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214basic_iostreamIcNS_11char_traitsIcEEED2Ev'} @@ -1023,36 +968,18 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215__thread_structC2Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215__thread_structD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215__thread_structD2Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE10pubseekoffExNS_8ios_base7seekdirEj'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE10pubseekposENS_4fposI11__mbstate_tEEj'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE4setgEPcS4_S4_'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE4setpEPcS4_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE4swapERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE4syncEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5gbumpEi'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5imbueERKNS_6localeE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5pbumpEi'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5sgetcEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5sgetnEPcl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5sputcEc'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5sputnEPKcl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE5uflowEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE6sbumpcEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE6setbufEPcl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE6snextcEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE6xsgetnEPcl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE6xsputnEPKcl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE7pubsyncEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE7seekoffExNS_8ios_base7seekdirEj'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE7seekposENS_4fposI11__mbstate_tEEj'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE7sungetcEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE8in_availEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE8overflowEi'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE8pubimbueERKNS_6localeE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE9pbackfailEi'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE9pubsetbufEPcl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE9showmanycEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE9sputbackcEc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEE9underflowEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEEC1ERKS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEEC1Ev'} @@ -1062,36 +989,18 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEED1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEED2Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEEaSERKS3_'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE10pubseekoffExNS_8ios_base7seekdirEj'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE10pubseekposENS_4fposI11__mbstate_tEEj'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE4setgEPwS4_S4_'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE4setpEPwS4_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE4swapERS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE4syncEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5gbumpEi'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5imbueERKNS_6localeE'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5pbumpEi'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5sgetcEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5sgetnEPwl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5sputcEw'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5sputnEPKwl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE5uflowEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE6sbumpcEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE6setbufEPwl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE6snextcEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE6xsgetnEPwl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE6xsputnEPKwl'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE7pubsyncEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE7seekoffExNS_8ios_base7seekdirEj'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE7seekposENS_4fposI11__mbstate_tEEj'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE7sungetcEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE8in_availEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE8overflowEi'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE8pubimbueERKNS_6localeE'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE9pbackfailEi'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE9pubsetbufEPwl'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE9showmanycEv'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE9sputbackcEw'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEE9underflowEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEEC1ERKS3_'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEEC1Ev'} @@ -1198,13 +1107,11 @@ {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_countD0Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_countD1Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_countD2Ev'} -{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__219__start_std_streamsE', 'size': 0} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__thread_local_dataEv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219declare_no_pointersEPcm'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__219piecewise_constructE', 'size': 0} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__220__get_collation_nameEPKc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__220__throw_system_errorEiPKc'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221__throw_runtime_errorEPKc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221__undeclare_reachableEPv'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutex4lockEv'} @@ -1481,10 +1388,6 @@ {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28valarrayImE6resizeEmm'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28valarrayImEC1Em'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28valarrayImEC2Em'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28valarrayImED1Ev'} -{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28valarrayImED2Ev'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIcE17__stage2_int_loopEciPcRS2_RjcRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSD_PKc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIcE17__stage2_int_prepERNS_8ios_baseERc'} {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIcE19__stage2_float_loopEcRbRcPcRS4_ccRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSE_RjS4_'} @@ -1806,8 +1709,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZTISt14overflow_error'} {'type': 'U', 'is_defined': False, 'name': '__ZTISt15underflow_error'} {'type': 'I', 'is_defined': True, 'name': '__ZTISt15underflow_error'} -{'type': 'U', 'is_defined': False, 'name': '__ZTISt16bad_array_length'} -{'type': 'I', 'is_defined': True, 'name': '__ZTISt16bad_array_length'} {'type': 'U', 'is_defined': False, 'name': '__ZTISt16invalid_argument'} {'type': 'I', 'is_defined': True, 'name': '__ZTISt16invalid_argument'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTISt16nested_exception', 'size': 0} @@ -2098,8 +1999,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZTSSt14overflow_error'} {'type': 'U', 'is_defined': False, 'name': '__ZTSSt15underflow_error'} {'type': 'I', 'is_defined': True, 'name': '__ZTSSt15underflow_error'} -{'type': 'U', 'is_defined': False, 'name': '__ZTSSt16bad_array_length'} -{'type': 'I', 'is_defined': True, 'name': '__ZTSSt16bad_array_length'} {'type': 'U', 'is_defined': False, 'name': '__ZTSSt16invalid_argument'} {'type': 'I', 'is_defined': True, 'name': '__ZTSSt16invalid_argument'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSSt16nested_exception', 'size': 0} @@ -2291,8 +2190,6 @@ {'type': 'I', 'is_defined': True, 'name': '__ZTVSt14overflow_error'} {'type': 'U', 'is_defined': False, 'name': '__ZTVSt15underflow_error'} {'type': 'I', 'is_defined': True, 'name': '__ZTVSt15underflow_error'} -{'type': 'U', 'is_defined': False, 'name': '__ZTVSt16bad_array_length'} -{'type': 'I', 'is_defined': True, 'name': '__ZTVSt16bad_array_length'} {'type': 'U', 'is_defined': False, 'name': '__ZTVSt16invalid_argument'} {'type': 'I', 'is_defined': True, 'name': '__ZTVSt16invalid_argument'} {'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVSt16nested_exception', 'size': 0} diff --git a/lib/libcxx/lib/abi/x86_64-unknown-linux-gnu.v1.abilist b/lib/libcxx/lib/abi/x86_64-unknown-linux-gnu.v1.abilist index 833342ca899..0be9eb2fcb3 100644 --- a/lib/libcxx/lib/abi/x86_64-unknown-linux-gnu.v1.abilist +++ b/lib/libcxx/lib/abi/x86_64-unknown-linux-gnu.v1.abilist @@ -1098,13 +1098,11 @@ {'name': '_ZNSt3__119__shared_weak_countD0Ev', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__119__shared_weak_countD1Ev', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__119__shared_weak_countD2Ev', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__119__start_std_streamsE', 'is_defined': True, 'type': 'OBJECT', 'size': 1} {'name': '_ZNSt3__119__thread_local_dataEv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__119declare_no_pointersEPcm', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__119piecewise_constructE', 'is_defined': True, 'type': 'OBJECT', 'size': 1} {'name': '_ZNSt3__120__get_collation_nameEPKc', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__120__throw_system_errorEiPKc', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__121__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__121__throw_runtime_errorEPKc', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__121__undeclare_reachableEPv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__121recursive_timed_mutex4lockEv', 'is_defined': True, 'type': 'FUNC'} @@ -1125,8 +1123,6 @@ {'name': '_ZNSt3__124__libcpp_debug_exceptionD0Ev', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__124__libcpp_debug_exceptionD1Ev', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__124__libcpp_debug_exceptionD2Ev', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__125__num_get_signed_integralIlEET_PKcS3_Rji', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__125__num_get_signed_integralIxEET_PKcS3_Rji', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'is_defined': True, 'type': 'FUNC'} @@ -1144,10 +1140,6 @@ {'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIxxEEPxEEbT0_S5_T_', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIyyEEPyEEbT0_S5_T_', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__127__libcpp_set_debug_functionEPFvRKNS_19__libcpp_debug_infoEE', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__127__num_get_unsigned_integralIjEET_PKcS3_Rji', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__127__num_get_unsigned_integralImEET_PKcS3_Rji', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__127__num_get_unsigned_integralItEET_PKcS3_Rji', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__127__num_get_unsigned_integralIyEET_PKcS3_Rji', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__129__libcpp_abort_debug_functionERKNS_19__libcpp_debug_infoE', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__129__libcpp_throw_debug_functionERKNS_19__libcpp_debug_infoE', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__13cinE', 'is_defined': True, 'type': 'OBJECT', 'size': 168} @@ -1264,21 +1256,7 @@ {'name': '_ZNSt3__16thread6detachEv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__16threadD1Ev', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__16threadD2Ev', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIaaEEPaEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIccEEPcEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIddEEPdEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__17__sort5IRNS_6__lessIeeEEPeEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIffEEPfEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIhhEEPhEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIiiEEPiEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIjjEEPjEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIllEEPlEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessImmEEPmEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIssEEPsEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIttEEPtEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIwwEEPwEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIxxEEPxEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__17__sort5IRNS_6__lessIyyEEPyEEjT0_S5_S5_S5_S5_T_', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__17codecvtIDic11__mbstate_tE2idE', 'is_defined': True, 'type': 'OBJECT', 'size': 16} {'name': '_ZNSt3__17codecvtIDic11__mbstate_tED0Ev', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__17codecvtIDic11__mbstate_tED1Ev', 'is_defined': True, 'type': 'FUNC'} @@ -1449,7 +1427,6 @@ {'name': '_ZNSt3__19to_stringEx', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__19to_stringEy', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt3__1plIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_12basic_stringIT_T0_T1_EEPKS6_RKS9_', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZNSt3__1plIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_12basic_stringIT_T0_T1_EERKS9_PKS6_', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZNSt8bad_castC1Ev', 'is_defined': False, 'type': 'FUNC'} {'name': '_ZNSt8bad_castD1Ev', 'is_defined': False, 'type': 'FUNC'} {'name': '_ZNSt8bad_castD2Ev', 'is_defined': False, 'type': 'FUNC'} @@ -1460,7 +1437,6 @@ {'name': '_ZSt17__throw_bad_allocv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZSt17current_exceptionv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZSt17rethrow_exceptionSt13exception_ptr', 'is_defined': True, 'type': 'FUNC'} -{'name': '_ZSt18make_exception_ptrINSt3__112future_errorEESt13exception_ptrT_', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZSt18uncaught_exceptionv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZSt19uncaught_exceptionsv', 'is_defined': True, 'type': 'FUNC'} {'name': '_ZSt7nothrow', 'is_defined': True, 'type': 'OBJECT', 'size': 1} diff --git a/lib/libcxx/lib/libc++abi2.exp b/lib/libcxx/lib/libc++abi2.exp index 0059eb49e24..40c055dae97 100644 --- a/lib/libcxx/lib/libc++abi2.exp +++ b/lib/libcxx/lib/libc++abi2.exp @@ -283,16 +283,6 @@ __ZTISt16invalid_argument __ZTSSt16invalid_argument __ZTVSt16invalid_argument -__ZNKSt16bad_array_length4whatEv -__ZNSt16bad_array_lengthC1Ev -__ZNSt16bad_array_lengthC2Ev -__ZNSt16bad_array_lengthD0Ev -__ZNSt16bad_array_lengthD1Ev -__ZNSt16bad_array_lengthD2Ev -__ZTISt16bad_array_length -__ZTSSt16bad_array_length -__ZTVSt16bad_array_length - __ZTSDi __ZTSDn __ZTSDs diff --git a/lib/libcxx/src/experimental/memory_resource.cpp b/lib/libcxx/src/experimental/memory_resource.cpp index a3b64cc8b49..7f0052f2b50 100644 --- a/lib/libcxx/src/experimental/memory_resource.cpp +++ b/lib/libcxx/src/experimental/memory_resource.cpp @@ -33,8 +33,9 @@ protected: virtual void* do_allocate(size_t __size, size_t __align) { return _VSTD::__libcpp_allocate(__size, __align); /* FIXME */} - virtual void do_deallocate(void * __p, size_t, size_t __align) - { _VSTD::__libcpp_deallocate(__p, __align); /* FIXME */ } + virtual void do_deallocate(void* __p, size_t __n, size_t __align) { + _VSTD::__libcpp_deallocate(__p, __n, __align); /* FIXME */ + } virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT { return &__other == this; } diff --git a/lib/libcxx/src/filesystem/filesystem_common.h b/lib/libcxx/src/filesystem/filesystem_common.h index ed92877c425..40419ee35e6 100644 --- a/lib/libcxx/src/filesystem/filesystem_common.h +++ b/lib/libcxx/src/filesystem/filesystem_common.h @@ -67,24 +67,31 @@ static string format_string_imp(const char* msg, ...) { va_copy(args_cp, args); GuardVAList args_copy_guard(args_cp); + std::string result; + array<char, 256> local_buff; - size_t size = local_buff.size(); - auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp); + size_t size_with_null = local_buff.size(); + auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp); args_copy_guard.clear(); // handle empty expansion if (ret == 0) - return string{}; - if (static_cast<size_t>(ret) < size) - return string(local_buff.data()); - - // we did not provide a long enough buffer on our first attempt. - // add 1 to size to account for null-byte in size cast to prevent overflow - size = static_cast<size_t>(ret) + 1; - auto buff_ptr = unique_ptr<char[]>(new char[size]); - ret = ::vsnprintf(buff_ptr.get(), size, msg, args); - return string(buff_ptr.get()); + return result; + if (static_cast<size_t>(ret) < size_with_null) { + result.assign(local_buff.data(), static_cast<size_t>(ret)); + return result; + } + + // we did not provide a long enough buffer on our first attempt. The + // return value is the number of bytes (excluding the null byte) that are + // needed for formatting. + size_with_null = static_cast<size_t>(ret) + 1; + result.__resize_default_init(size_with_null - 1); + ret = ::vsnprintf(&result[0], size_with_null, msg, args); + _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); + + return result; } const char* unwrap(string const& s) { return s.c_str(); } diff --git a/lib/libcxx/src/filesystem/operations.cpp b/lib/libcxx/src/filesystem/operations.cpp index c9396b59cae..b4106188872 100644 --- a/lib/libcxx/src/filesystem/operations.cpp +++ b/lib/libcxx/src/filesystem/operations.cpp @@ -206,8 +206,20 @@ public: return *this; } + bool atEnd() const noexcept { + return State == PS_AtEnd; + } + + bool inRootDir() const noexcept { + return State == PS_InRootDir; + } + + bool inRootName() const noexcept { + return State == PS_InRootName; + } + bool inRootPath() const noexcept { - return State == PS_InRootDir || State == PS_InRootName; + return inRootName() || inRootDir(); } private: @@ -427,7 +439,8 @@ file_status posix_lstat(path const& p, error_code* ec) { return posix_lstat(p, path_stat, ec); } -bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) { +// http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html +bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { if (::ftruncate(fd.fd, to_size) == -1) { ec = capture_errno(); return true; @@ -1294,7 +1307,19 @@ string_view_t path::__root_path_raw() const { return {}; } +static bool ConsumeRootName(PathParser *PP) { + static_assert(PathParser::PS_BeforeBegin == 1 && + PathParser::PS_InRootName == 2, + "Values for enums are incorrect"); + while (PP->State <= PathParser::PS_InRootName) + ++(*PP); + return PP->State == PathParser::PS_AtEnd; +} + static bool ConsumeRootDir(PathParser* PP) { + static_assert(PathParser::PS_BeforeBegin == 1 && + PathParser::PS_InRootName == 2 && + PathParser::PS_InRootDir == 3, "Values for enums are incorrect"); while (PP->State <= PathParser::PS_InRootDir) ++(*PP); return PP->State == PathParser::PS_AtEnd; @@ -1454,7 +1479,7 @@ static int DetermineLexicalElementCount(PathParser PP) { auto Elem = *PP; if (Elem == "..") --Count; - else if (Elem != ".") + else if (Elem != "." && Elem != "") ++Count; } return Count; @@ -1468,8 +1493,7 @@ path path::lexically_relative(const path& base) const { return PP.State != PPBase.State && (PP.inRootPath() || PPBase.inRootPath()); }; - if (PP.State == PathParser::PS_InRootName && - PPBase.State == PathParser::PS_InRootName) { + if (PP.inRootName() && PPBase.inRootName()) { if (*PP != *PPBase) return {}; } else if (CheckIterMismatchAtBase()) @@ -1501,6 +1525,10 @@ path path::lexically_relative(const path& base) const { if (ElemCount < 0) return {}; + // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise + if (ElemCount == 0 && (PP.atEnd() || *PP == "")) + return "."; + // return a path constructed with 'n' dot-dot elements, followed by the the // elements of '*this' after the mismatch. path Result; @@ -1514,21 +1542,68 @@ path path::lexically_relative(const path& base) const { //////////////////////////////////////////////////////////////////////////// // path.comparisons -int path::__compare(string_view_t __s) const { - auto PP = PathParser::CreateBegin(__pn_); - auto PP2 = PathParser::CreateBegin(__s); - while (PP && PP2) { - int res = (*PP).compare(*PP2); - if (res != 0) +static int CompareRootName(PathParser *LHS, PathParser *RHS) { + if (!LHS->inRootName() && !RHS->inRootName()) + return 0; + + auto GetRootName = [](PathParser *Parser) -> string_view_t { + return Parser->inRootName() ? **Parser : ""; + }; + int res = GetRootName(LHS).compare(GetRootName(RHS)); + ConsumeRootName(LHS); + ConsumeRootName(RHS); + return res; +} + +static int CompareRootDir(PathParser *LHS, PathParser *RHS) { + if (!LHS->inRootDir() && RHS->inRootDir()) + return -1; + else if (LHS->inRootDir() && !RHS->inRootDir()) + return 1; + else { + ConsumeRootDir(LHS); + ConsumeRootDir(RHS); + return 0; + } +} + +static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) { + auto &LHS = *LHSPtr; + auto &RHS = *RHSPtr; + + int res; + while (LHS && RHS) { + if ((res = (*LHS).compare(*RHS)) != 0) return res; - ++PP; - ++PP2; + ++LHS; + ++RHS; } - if (PP.State == PP2.State && !PP) - return 0; - if (!PP) + return 0; +} + +static int CompareEndState(PathParser *LHS, PathParser *RHS) { + if (LHS->atEnd() && !RHS->atEnd()) return -1; - return 1; + else if (!LHS->atEnd() && RHS->atEnd()) + return 1; + return 0; +} + +int path::__compare(string_view_t __s) const { + auto LHS = PathParser::CreateBegin(__pn_); + auto RHS = PathParser::CreateBegin(__s); + int res; + + if ((res = CompareRootName(&LHS, &RHS)) != 0) + return res; + + if ((res = CompareRootDir(&LHS, &RHS)) != 0) + return res; + + if ((res = CompareRelative(&LHS, &RHS)) != 0) + return res; + + return CompareEndState(&LHS, &RHS); } //////////////////////////////////////////////////////////////////////////// diff --git a/lib/libcxx/src/future.cpp b/lib/libcxx/src/future.cpp index 07e4602f567..cbcd2e7b728 100644 --- a/lib/libcxx/src/future.cpp +++ b/lib/libcxx/src/future.cpp @@ -179,10 +179,7 @@ __assoc_sub_state::__execute() future<void>::future(__assoc_sub_state* __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(); } future<void>::~future() diff --git a/lib/libcxx/src/iostream.cpp b/lib/libcxx/src/iostream.cpp index 2b47cf25b64..11bfb486208 100644 --- a/lib/libcxx/src/iostream.cpp +++ b/lib/libcxx/src/iostream.cpp @@ -13,21 +13,21 @@ #define _str(s) #s #define str(s) _str(s) -#define _LIBCPP_NAMESPACE_STR str(_LIBCPP_NAMESPACE) +#define _LIBCPP_ABI_NAMESPACE_STR str(_LIBCPP_ABI_NAMESPACE) _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_STDIN _ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin[sizeof(istream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?cin@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_istream@DU?$char_traits@D@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?cin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; _ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin[sizeof(__stdinbuf <char>)]; static mbstate_t mb_cin; _ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin[sizeof(wistream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?wcin@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_istream@_WU?$char_traits@_W@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?wcin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; _ALIGNAS_TYPE (__stdinbuf<wchar_t> ) static char __wcin[sizeof(__stdinbuf <wchar_t>)]; @@ -37,14 +37,14 @@ static mbstate_t mb_wcin; #ifndef _LIBCPP_HAS_NO_STDOUT _ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cout[sizeof(ostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?cout@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?cout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; _ALIGNAS_TYPE (__stdoutbuf<char>) static char __cout[sizeof(__stdoutbuf<char>)]; static mbstate_t mb_cout; _ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcout[sizeof(wostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?wcout@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?wcout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; _ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcout[sizeof(__stdoutbuf<wchar_t>)]; @@ -53,14 +53,14 @@ static mbstate_t mb_wcout; _ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?cerr@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?cerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; _ALIGNAS_TYPE (__stdoutbuf<char>) static char __cerr[sizeof(__stdoutbuf<char>)]; static mbstate_t mb_cerr; _ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcerr[sizeof(wostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?wcerr@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?wcerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; _ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcerr[sizeof(__stdoutbuf<wchar_t>)]; @@ -68,16 +68,16 @@ static mbstate_t mb_wcerr; _ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?clog@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?clog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; _ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wclog[sizeof(wostream)] #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) -__asm__("?wclog@" _LIBCPP_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_NAMESPACE_STR "@std@@@12@A") +__asm__("?wclog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") #endif ; -ios_base::Init __start_std_streams; +_LIBCPP_HIDDEN ios_base::Init __start_std_streams; ios_base::Init::Init() { diff --git a/lib/libcxx/src/new.cpp b/lib/libcxx/src/new.cpp index 8013d89ae3c..cc8383d4f14 100644 --- a/lib/libcxx/src/new.cpp +++ b/lib/libcxx/src/new.cpp @@ -55,7 +55,7 @@ __throw_bad_alloc() } // std #if !defined(__GLIBCXX__) && \ - (!defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME)) && \ + !defined(_LIBCPP_DEFER_NEW_TO_VCRUNTIME) && \ !defined(_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS) // Implement all new and delete operators as weak definitions @@ -135,8 +135,7 @@ _LIBCPP_WEAK void operator delete(void* ptr) _NOEXCEPT { - if (ptr) - ::free(ptr); + ::free(ptr); } _LIBCPP_WEAK @@ -174,7 +173,7 @@ operator delete[] (void* ptr, size_t) _NOEXCEPT ::operator delete[](ptr); } -#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) +#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) _LIBCPP_WEAK void * @@ -257,11 +256,10 @@ _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) _NOEXCEPT { - if (ptr) #if defined(_LIBCPP_MSVCRT_LIKE) - ::_aligned_free(ptr); + ::_aligned_free(ptr); #else - ::free(ptr); + ::free(ptr); #endif } @@ -300,5 +298,5 @@ operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT ::operator delete[](ptr, alignment); } -#endif // !_LIBCPP_HAS_NO_ALIGNED_ALLOCATION +#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION #endif // !__GLIBCXX__ && (!_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME) && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS diff --git a/lib/libcxx/src/support/runtime/exception_fallback.ipp b/lib/libcxx/src/support/runtime/exception_fallback.ipp index 664e7f48c09..16d387b99e8 100644 --- a/lib/libcxx/src/support/runtime/exception_fallback.ipp +++ b/lib/libcxx/src/support/runtime/exception_fallback.ipp @@ -134,22 +134,6 @@ bad_array_new_length::what() const _NOEXCEPT return "bad_array_new_length"; } - -bad_array_length::bad_array_length() _NOEXCEPT -{ -} - -bad_array_length::~bad_array_length() _NOEXCEPT -{ -} - -const char* -bad_array_length::what() const _NOEXCEPT -{ - return "bad_array_length"; -} - - bad_cast::bad_cast() _NOEXCEPT { } diff --git a/lib/libcxx/src/support/runtime/exception_glibcxx.ipp b/lib/libcxx/src/support/runtime/exception_glibcxx.ipp index 0f78932f6f9..dda4432b508 100644 --- a/lib/libcxx/src/support/runtime/exception_glibcxx.ipp +++ b/lib/libcxx/src/support/runtime/exception_glibcxx.ipp @@ -22,11 +22,6 @@ bad_array_new_length::bad_array_new_length() _NOEXCEPT { } -bad_array_length::bad_array_length() _NOEXCEPT -{ -} - - bad_cast::bad_cast() _NOEXCEPT { } diff --git a/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp b/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp index 6d9e0cff58d..52fe8635db7 100644 --- a/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp +++ b/lib/libcxx/src/support/runtime/exception_libcxxrt.ipp @@ -23,19 +23,4 @@ const char* bad_exception::what() const _NOEXCEPT return "std::bad_exception"; } - -bad_array_length::bad_array_length() _NOEXCEPT -{ -} - -bad_array_length::~bad_array_length() _NOEXCEPT -{ -} - -const char* -bad_array_length::what() const _NOEXCEPT -{ - return "bad_array_length"; -} - } // namespace std diff --git a/lib/libcxx/src/support/runtime/exception_msvc.ipp b/lib/libcxx/src/support/runtime/exception_msvc.ipp index 87d5a66fc8f..042d3add6c7 100644 --- a/lib/libcxx/src/support/runtime/exception_msvc.ipp +++ b/lib/libcxx/src/support/runtime/exception_msvc.ipp @@ -83,20 +83,6 @@ int uncaught_exceptions() _NOEXCEPT { return __uncaught_exceptions(); } -bad_array_length::bad_array_length() _NOEXCEPT -{ -} - -bad_array_length::~bad_array_length() _NOEXCEPT -{ -} - -const char* -bad_array_length::what() const _NOEXCEPT -{ - return "bad_array_length"; -} - #if defined(_LIBCPP_NO_VCRUNTIME) bad_cast::bad_cast() _NOEXCEPT { diff --git a/lib/libcxx/utils/ci/macos-backdeployment.sh b/lib/libcxx/utils/ci/macos-backdeployment.sh new file mode 100755 index 00000000000..1f01fa397c9 --- /dev/null +++ b/lib/libcxx/utils/ci/macos-backdeployment.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash + +set -ue + +function usage() { + cat <<EOM +$(basename ${0}) [-h|--help] --libcxx-root <LIBCXX-ROOT> --libcxxabi-root <LIBCXXABI-ROOT> --std <STD> --arch <ARCHITECTURE> --deployment-target <TARGET> --sdk-version <SDK-VERSION> [--lit-args <ARGS...>] + +This script is used to continually test the back-deployment use case of libc++ and libc++abi on MacOS. + + --libcxx-root Full path to the root of the libc++ repository to test. + --libcxxabi-root Full path to the root of the libc++abi repository to test. + --std Version of the C++ Standard to run the tests under (c++03, c++11, etc..). + --arch Architecture to build the tests for (32, 64). + --deployment-target The deployment target to run the tests for. This should be a version number of MacOS (e.g. 10.12). All MacOS versions until and including 10.7 are supported. + --sdk-version The version of the SDK to test with. This should be a version number of MacOS (e.g. 10.12). We'll link against the libc++ dylib in that SDK, but we'll run against the one on the given deployment target. + [--lit-args] Additional arguments to pass to lit (optional). If there are multiple arguments, quote them to pass them as a single argument to this script. + [--no-cleanup] Do not cleanup the temporary directory that was used for testing at the end. This can be useful to debug failures. Make sure to clean up manually after. + [-h, --help] Print this help. +EOM +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --libcxx-root) + LIBCXX_ROOT="${2}" + if [[ ! -d "${LIBCXX_ROOT}" ]]; then + echo "--libcxx-root '${LIBCXX_ROOT}' is not a valid directory" + usage + exit 1 + fi + shift; shift + ;; + --libcxxabi-root) + LIBCXXABI_ROOT="${2}" + if [[ ! -d "${LIBCXXABI_ROOT}" ]]; then + echo "--libcxxabi-root '${LIBCXXABI_ROOT}' is not a valid directory" + usage + exit 1 + fi + shift; shift + ;; + --std) + STD="${2}" + shift; shift + ;; + --arch) + ARCH="${2}" + shift; shift + ;; + --deployment-target) + DEPLOYMENT_TARGET="${2}" + shift; shift + ;; + --sdk-version) + MACOS_SDK_VERSION="${2}" + shift; shift + ;; + --lit-args) + ADDITIONAL_LIT_ARGS="${2}" + shift; shift + ;; + --no-cleanup) + NO_CLEANUP="" + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "${1} is not a supported argument" + usage + exit 1 + ;; + esac +done + +if [[ -z ${LIBCXX_ROOT+x} ]]; then echo "--libcxx-root is a required parameter"; usage; exit 1; fi +if [[ -z ${LIBCXXABI_ROOT+x} ]]; then echo "--libcxxabi-root is a required parameter"; usage; exit 1; fi +if [[ -z ${STD+x} ]]; then echo "--std is a required parameter"; usage; exit 1; fi +if [[ -z ${ARCH+x} ]]; then echo "--arch is a required parameter"; usage; exit 1; fi +if [[ -z ${DEPLOYMENT_TARGET+x} ]]; then echo "--deployment-target is a required parameter"; usage; exit 1; fi +if [[ -z ${MACOS_SDK_VERSION+x} ]]; then echo "--sdk-version is a required parameter"; usage; exit 1; fi +if [[ -z ${ADDITIONAL_LIT_ARGS+x} ]]; then ADDITIONAL_LIT_ARGS=""; fi + + +TEMP_DIR="$(mktemp -d)" +echo "Created temporary directory ${TEMP_DIR}" +function cleanup { + if [[ -z ${NO_CLEANUP+x} ]]; then + echo "Removing temporary directory ${TEMP_DIR}" + rm -rf "${TEMP_DIR}" + else + echo "Temporary directory is at '${TEMP_DIR}', make sure to clean it up yourself" + fi +} +trap cleanup EXIT + + +LLVM_ROOT="${TEMP_DIR}/llvm" +LIBCXX_BUILD_DIR="${TEMP_DIR}/libcxx-build" +LIBCXX_INSTALL_DIR="${TEMP_DIR}/libcxx-install" +LIBCXXABI_BUILD_DIR="${TEMP_DIR}/libcxxabi-build" +LIBCXXABI_INSTALL_DIR="${TEMP_DIR}/libcxxabi-install" + +PREVIOUS_DYLIBS_URL="http://lab.llvm.org:8080/roots/libcxx-roots.tar.gz" +LLVM_TARBALL_URL="https://github.com/llvm-mirror/llvm/archive/master.tar.gz" +export CC="$(xcrun --find clang)" +export CXX="$(xcrun --find clang++)" + + +echo "@@@ Downloading LLVM tarball of master (only used for CMake configuration) @@@" +mkdir "${LLVM_ROOT}" +curl -L "${LLVM_TARBALL_URL}" | tar -xz --strip-components=1 -C "${LLVM_ROOT}" +echo "@@@@@@" + + +echo "@@@ Configuring architecture-related stuff @@@" +if [[ "${ARCH}" == "64" ]]; then CMAKE_ARCH_STRING="x86_64"; else CMAKE_ARCH_STRING="i386"; fi +if [[ "${ARCH}" == "64" ]]; then LIT_ARCH_STRING=""; else LIT_ARCH_STRING="--param=enable_32bit=true"; fi +echo "@@@@@@" + + +echo "@@@ Configuring CMake for libc++ @@@" +mkdir -p "${LIBCXX_BUILD_DIR}" +(cd "${LIBCXX_BUILD_DIR}" && + xcrun cmake "${LIBCXX_ROOT}" -GNinja \ + -DLLVM_PATH="${LLVM_ROOT}" \ + -DCMAKE_INSTALL_PREFIX="${LIBCXX_INSTALL_DIR}" \ + -DCMAKE_OSX_ARCHITECTURES="${CMAKE_ARCH_STRING}" +) +echo "@@@@@@" + + +echo "@@@ Configuring CMake for libc++abi @@@" +mkdir -p "${LIBCXXABI_BUILD_DIR}" +(cd "${LIBCXXABI_BUILD_DIR}" && + xcrun cmake "${LIBCXXABI_ROOT}" -GNinja \ + -DLIBCXXABI_LIBCXX_PATH="${LIBCXX_ROOT}" \ + -DLLVM_PATH="${LLVM_ROOT}" \ + -DCMAKE_INSTALL_PREFIX="${LIBCXXABI_INSTALL_DIR}" \ + -DCMAKE_OSX_ARCHITECTURES="${CMAKE_ARCH_STRING}" +) +echo "@@@@@@" + + +echo "@@@ Installing the latest libc++ headers @@@" +ninja -C "${LIBCXX_BUILD_DIR}" install-cxx-headers +echo "@@@@@@" + + +echo "@@@ Downloading dylibs for older deployment targets @@@" +# TODO: The tarball should contain libc++abi.dylib too, we shouldn't be relying on the system's +# TODO: We should also link against the libc++abi.dylib that was shipped in the SDK +PREVIOUS_DYLIBS_DIR="${TEMP_DIR}/libcxx-dylibs" +mkdir "${PREVIOUS_DYLIBS_DIR}" +curl "${PREVIOUS_DYLIBS_URL}" | tar -xz --strip-components=1 -C "${PREVIOUS_DYLIBS_DIR}" +LIBCXX_ON_DEPLOYMENT_TARGET="${PREVIOUS_DYLIBS_DIR}/macOS/${DEPLOYMENT_TARGET}/libc++.dylib" +LIBCXXABI_ON_DEPLOYMENT_TARGET="/usr/lib/libc++abi.dylib" +LIBCXX_IN_SDK="${PREVIOUS_DYLIBS_DIR}/macOS/${MACOS_SDK_VERSION}/libc++.dylib" +echo "@@@@@@" + + +# TODO: We need to also run the tests for libc++abi. +# TODO: Make sure lit will actually run against the libc++abi we specified +echo "@@@ Running tests for libc++ @@@" +"${LIBCXX_BUILD_DIR}/bin/llvm-lit" -sv "${LIBCXX_ROOT}/test" \ + --param=enable_experimental=false \ + --param=enable_filesystem=false \ + ${LIT_ARCH_STRING} \ + --param=cxx_under_test="${CXX}" \ + --param=cxx_headers="${LIBCXX_INSTALL_DIR}/include/c++/v1" \ + --param=std="${STD}" \ + --param=platform="macosx${DEPLOYMENT_TARGET}" \ + --param=cxx_runtime_root="$(dirname "${LIBCXX_ON_DEPLOYMENT_TARGET}")" \ + --param=abi_library_path="$(dirname "${LIBCXXABI_ON_DEPLOYMENT_TARGET}")" \ + --param=use_system_cxx_lib="$(dirname "${LIBCXX_IN_SDK}")" \ + ${ADDITIONAL_LIT_ARGS} +echo "@@@@@@" diff --git a/lib/libcxx/utils/ci/macos-trunk.sh b/lib/libcxx/utils/ci/macos-trunk.sh new file mode 100755 index 00000000000..b365cc6d8e3 --- /dev/null +++ b/lib/libcxx/utils/ci/macos-trunk.sh @@ -0,0 +1,153 @@ +#!/usr/bin/env bash + +set -ue + +function usage() { + cat <<EOM +$(basename ${0}) [-h|--help] --libcxx-root <LIBCXX-ROOT> --libcxxabi-root <LIBCXXABI-ROOT> --std <STD> --arch <ARCHITECTURE> [--lit-args <ARGS...>] + +This script is used to continually test libc++ and libc++abi trunk on MacOS. + + --libcxx-root Full path to the root of the libc++ repository to test. + --libcxxabi-root Full path to the root of the libc++abi repository to test. + --std Version of the C++ Standard to run the tests under (c++03, c++11, etc..). + --arch Architecture to build the tests for (32, 64). + [--lit-args] Additional arguments to pass to lit (optional). If there are multiple arguments, quote them to pass them as a single argument to this script. + [--no-cleanup] Do not cleanup the temporary directory that was used for testing at the end. This can be useful to debug failures. Make sure to clean up manually after. + [-h, --help] Print this help. +EOM +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --libcxx-root) + LIBCXX_ROOT="${2}" + if [[ ! -e "${LIBCXX_ROOT}" ]]; then + echo "--libcxx-root '${LIBCXX_ROOT}' is not a valid directory" + usage + exit 1 + fi + shift; shift + ;; + --libcxxabi-root) + LIBCXXABI_ROOT="${2}" + if [[ ! -e "${LIBCXXABI_ROOT}" ]]; then + echo "--libcxxabi-root '${LIBCXXABI_ROOT}' is not a valid directory" + usage + exit 1 + fi + shift; shift + ;; + --std) + STD="${2}" + shift; shift + ;; + --arch) + ARCH="${2}" + shift; shift + ;; + --lit-args) + ADDITIONAL_LIT_ARGS="${2}" + shift; shift + ;; + --no-cleanup) + NO_CLEANUP="" + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "${1} is not a supported argument" + usage + exit 1 + ;; + esac +done + +if [[ -z ${LIBCXX_ROOT+x} ]]; then echo "--libcxx-root is a required parameter"; usage; exit 1; fi +if [[ -z ${LIBCXXABI_ROOT+x} ]]; then echo "--libcxxabi-root is a required parameter"; usage; exit 1; fi +if [[ -z ${STD+x} ]]; then echo "--std is a required parameter"; usage; exit 1; fi +if [[ -z ${ARCH+x} ]]; then echo "--arch is a required parameter"; usage; exit 1; fi +if [[ -z ${ADDITIONAL_LIT_ARGS+x} ]]; then ADDITIONAL_LIT_ARGS=""; fi + + +TEMP_DIR="$(mktemp -d)" +echo "Created temporary directory ${TEMP_DIR}" +function cleanup { + if [[ -z ${NO_CLEANUP+x} ]]; then + echo "Removing temporary directory ${TEMP_DIR}" + rm -rf "${TEMP_DIR}" + else + echo "Temporary directory is at '${TEMP_DIR}', make sure to clean it up yourself" + fi +} +trap cleanup EXIT + + +LLVM_ROOT="${TEMP_DIR}/llvm" +LIBCXX_BUILD_DIR="${TEMP_DIR}/libcxx-build" +LIBCXX_INSTALL_DIR="${TEMP_DIR}/libcxx-install" +LIBCXXABI_BUILD_DIR="${TEMP_DIR}/libcxxabi-build" +LIBCXXABI_INSTALL_DIR="${TEMP_DIR}/libcxxabi-install" + +LLVM_TARBALL_URL="https://github.com/llvm-mirror/llvm/archive/master.tar.gz" +export CC="$(xcrun --find clang)" +export CXX="$(xcrun --find clang++)" + + +echo "@@@ Downloading LLVM tarball of master (only used for CMake configuration) @@@" +mkdir "${LLVM_ROOT}" +curl -L "${LLVM_TARBALL_URL}" | tar -xz --strip-components=1 -C "${LLVM_ROOT}" +echo "@@@@@@" + + +echo "@@@ Setting up LIT flags @@@" +LIT_FLAGS="-sv --param=std=${STD} ${ADDITIONAL_LIT_ARGS}" +if [[ "${ARCH}" == "32" ]]; then + LIT_FLAGS+=" --param=enable_32bit=true" +fi +echo "@@@@@@" + + +echo "@@@ Configuring CMake for libc++ @@@" +mkdir -p "${LIBCXX_BUILD_DIR}" +(cd "${LIBCXX_BUILD_DIR}" && + xcrun cmake "${LIBCXX_ROOT}" -GNinja \ + -DLLVM_PATH="${LLVM_ROOT}" \ + -DCMAKE_INSTALL_PREFIX="${LIBCXX_INSTALL_DIR}" \ + -DLLVM_LIT_ARGS="${LIT_FLAGS}" \ + -DCMAKE_OSX_ARCHITECTURES="i386;x86_64" # Build a universal dylib +) +echo "@@@@@@" + + +echo "@@@ Configuring CMake for libc++abi @@@" +mkdir -p "${LIBCXXABI_BUILD_DIR}" +(cd "${LIBCXXABI_BUILD_DIR}" && + xcrun cmake "${LIBCXXABI_ROOT}" -GNinja \ + -DLIBCXXABI_LIBCXX_PATH="${LIBCXX_ROOT}" \ + -DLLVM_PATH="${LLVM_ROOT}" \ + -DCMAKE_INSTALL_PREFIX="${LIBCXXABI_INSTALL_DIR}" \ + -DLLVM_LIT_ARGS="${LIT_FLAGS}" \ + -DCMAKE_OSX_ARCHITECTURES="i386;x86_64" # Build a universal dylib +) +echo "@@@@@@" + + +echo "@@@ Building libc++.dylib and libc++abi.dylib from sources (just to make sure it works) @@@" +ninja -C "${LIBCXX_BUILD_DIR}" install-cxx +ninja -C "${LIBCXXABI_BUILD_DIR}" install-cxxabi +echo "@@@@@@" + + +echo "@@@ Running tests for libc++ @@@" +# TODO: We should run check-cxx-abilist too +ninja -C "${LIBCXX_BUILD_DIR}" check-cxx +echo "@@@@@@" + + +echo "@@@ Running tests for libc++abi @@@" +ninja -C "${LIBCXXABI_BUILD_DIR}" check-cxxabi +echo "@@@@@@" diff --git a/lib/libcxx/utils/docker/build_docker_image.sh b/lib/libcxx/utils/docker/build_docker_image.sh new file mode 100755 index 00000000000..0d2d6d313c7 --- /dev/null +++ b/lib/libcxx/utils/docker/build_docker_image.sh @@ -0,0 +1,109 @@ +#!/bin/bash +#===- libcxx/utils/docker/build_docker_image.sh ----------------------------===// +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===----------------------------------------------------------------------===// +set -e + +IMAGE_SOURCE="" +DOCKER_REPOSITORY="" +DOCKER_TAG="" + +function show_usage() { + cat << EOF +Usage: build_docker_image.sh [options] [-- [cmake_args]...] + +Available options: + General: + -h|--help show this help message + Docker-specific: + -s|--source image source dir (i.e. debian8, nvidia-cuda, etc) + -d|--docker-repository docker repository for the image + -t|--docker-tag docker tag for the image + +Required options: --source and --docker-repository. + +For example, running: +$ build_docker_image.sh -s debian9 -d mydocker/debian9-clang -t latest +will produce two docker images: + mydocker/debian9-clang-build:latest - an intermediate image used to compile + clang. + mydocker/clang-debian9:latest - a small image with preinstalled clang. +Please note that this example produces a not very useful installation, since it +doesn't override CMake defaults, which produces a Debug and non-boostrapped +version of clang. +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + show_usage + exit 0 + ;; + -s|--source) + shift + IMAGE_SOURCE="$1" + shift + ;; + -d|--docker-repository) + shift + DOCKER_REPOSITORY="$1" + shift + ;; + -t|--docker-tag) + shift + DOCKER_TAG="$1" + shift + ;; + *) + echo "Unknown argument $1" + exit 1 + ;; + esac +done + + +command -v docker >/dev/null || + { + echo "Docker binary cannot be found. Please install Docker to use this script." + exit 1 + } + +if [ "$IMAGE_SOURCE" == "" ]; then + echo "Required argument missing: --source" + exit 1 +fi + +if [ "$DOCKER_REPOSITORY" == "" ]; then + echo "Required argument missing: --docker-repository" + exit 1 +fi + +SOURCE_DIR=$(dirname $0) +if [ ! -d "$SOURCE_DIR/$IMAGE_SOURCE" ]; then + echo "No sources for '$IMAGE_SOURCE' were found in $SOURCE_DIR" + exit 1 +fi + +BUILD_DIR=$(mktemp -d) +trap "rm -rf $BUILD_DIR" EXIT +echo "Using a temporary directory for the build: $BUILD_DIR" + +cp -r "$SOURCE_DIR/$IMAGE_SOURCE" "$BUILD_DIR/$IMAGE_SOURCE" +cp -r "$SOURCE_DIR/scripts" "$BUILD_DIR/scripts" + + +if [ "$DOCKER_TAG" != "" ]; then + DOCKER_TAG=":$DOCKER_TAG" +fi + +echo "Building ${DOCKER_REPOSITORY}${DOCKER_TAG} from $IMAGE_SOURCE" +docker build -t "${DOCKER_REPOSITORY}${DOCKER_TAG}" \ + -f "$BUILD_DIR/$IMAGE_SOURCE/Dockerfile" \ + "$BUILD_DIR" +echo "Done" diff --git a/lib/libcxx/utils/docker/debian9/Dockerfile b/lib/libcxx/utils/docker/debian9/Dockerfile new file mode 100644 index 00000000000..8dc43f40105 --- /dev/null +++ b/lib/libcxx/utils/docker/debian9/Dockerfile @@ -0,0 +1,115 @@ +#===- libcxx/utils/docker/debian9/Dockerfile -------------------------===// +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===----------------------------------------------------------------------===// + +# Setup the base builder image with the packages we'll need to build GCC and Clang from source. +FROM launcher.gcr.io/google/debian9:latest as builder-base +LABEL maintainer "libc++ Developers" + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + gnupg \ + build-essential \ + wget \ + subversion \ + unzip \ + automake \ + python \ + cmake \ + ninja-build \ + curl \ + git \ + gcc-multilib \ + g++-multilib \ + libc6-dev \ + bison \ + flex \ + libtool \ + autoconf \ + binutils-dev \ + binutils-gold \ + software-properties-common && \ + update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20 && \ + update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.bfd" 10 + +# Build GCC 4.9 for testing our C++11 against +FROM builder-base as gcc-49-builder +LABEL maintainer "libc++ Developers" + +ADD scripts/build_gcc.sh /tmp/build_gcc.sh + +RUN git clone --depth=1 --branch gcc-4_9_4-release git://gcc.gnu.org/git/gcc.git /tmp/gcc-4.9.4 +RUN cd /tmp/gcc-4.9.4/ && ./contrib/download_prerequisites +RUN /tmp/build_gcc.sh --source /tmp/gcc-4.9.4 --to /opt/gcc-4.9.4 + +# Build GCC ToT for testing in all dialects. +FROM builder-base as gcc-tot-builder +LABEL maintainer "libc++ Developers" + +ADD scripts/build_gcc.sh /tmp/build_gcc.sh + +RUN git clone --depth=1 git://gcc.gnu.org/git/gcc.git /tmp/gcc-tot +RUN cd /tmp/gcc-tot && ./contrib/download_prerequisites +RUN /tmp/build_gcc.sh --source /tmp/gcc-tot --to /opt/gcc-tot + +# Build LLVM 4.0 which is used to test against a "legacy" compiler. +FROM builder-base as llvm-4-builder +LABEL maintainer "libc++ Developers" + +ADD scripts/checkout_git.sh /tmp/checkout_git.sh +ADD scripts/build_install_llvm.sh /tmp/build_install_llvm.sh + +RUN /tmp/checkout_git.sh --to /tmp/llvm-4.0 -p clang -p compiler-rt --branch release_40 +RUN /tmp/build_install_llvm.sh \ + --install /opt/llvm-4.0 \ + --source /tmp/llvm-4.0 \ + --build /tmp/build-llvm-4.0 \ + -i install-clang -i install-clang-headers \ + -i install-compiler-rt \ + -- \ + -DCMAKE_BUILD_TYPE=RELEASE \ + -DLLVM_ENABLE_ASSERTIONS=ON + +# Stage 2. Produce a minimal release image with build results. +FROM launcher.gcr.io/google/debian9:latest +LABEL maintainer "libc++ Developers" + +# Copy over the GCC and Clang installations +COPY --from=gcc-49-builder /opt/gcc-4.9.4 /opt/gcc-4.9.4 +COPY --from=gcc-tot-builder /opt/gcc-tot /opt/gcc-tot +COPY --from=llvm-4-builder /opt/llvm-4.0 /opt/llvm-4.0 + +RUN ln -s /opt/gcc-4.9.4/bin/gcc /usr/local/bin/gcc-4.9 && \ + ln -s /opt/gcc-4.9.4/bin/g++ /usr/local/bin/g++-4.9 + +RUN apt-get update && \ + apt-get install -y \ + ca-certificates \ + gnupg \ + build-essential \ + apt-transport-https \ + curl \ + software-properties-common + +RUN apt-get install -y --no-install-recommends \ + systemd \ + sysvinit-utils \ + cmake \ + subversion \ + git \ + ninja-build \ + gcc-multilib \ + g++-multilib \ + python \ + buildbot-slave + +ADD scripts/install_clang_packages.sh /tmp/install_clang_packages.sh +RUN /tmp/install_clang_packages.sh && rm /tmp/install_clang_packages.sh + +RUN git clone https://git.llvm.org/git/libcxx.git /libcxx diff --git a/lib/libcxx/utils/docker/scripts/build_gcc.sh b/lib/libcxx/utils/docker/scripts/build_gcc.sh new file mode 100755 index 00000000000..85feb16acd6 --- /dev/null +++ b/lib/libcxx/utils/docker/scripts/build_gcc.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +#===- libcxx/utils/docker/scripts/build-gcc.sh ----------------------------===// +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===-----------------------------------------------------------------------===// + +set -e + + +function show_usage() { + cat << EOF +Usage: build-gcc.sh [options] + +Run autoconf with the specified arguments. Used inside docker container. + +Available options: + -h|--help show this help message + --source the source path from which to run the configuration. + --to destination directory where to install the targets. +Required options: --to, at least one --install-target. + +All options after '--' are passed to CMake invocation. +EOF +} + +GCC_INSTALL_DIR="" +GCC_SOURCE_DIR="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --to) + shift + GCC_INSTALL_DIR="$1" + shift + ;; + --source) + shift + GCC_SOURCE_DIR="$1" + shift + ;; + -h|--help) + show_usage + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 1 + esac +done + +if [ "$GCC_INSTALL_DIR" == "" ]; then + echo "No install directory. Please specify the --to argument." + exit 1 +fi + +if [ "$GCC_SOURCE_DIR" == "" ]; then + echo "No source directory. Please specify the --source argument." + exit 1 +fi + +GCC_NAME=`basename $GCC_SOURCE_DIR` +GCC_BUILD_DIR="/tmp/gcc-build-root/build-$GCC_NAME" + +mkdir -p "$GCC_INSTALL_DIR" +mkdir -p "$GCC_BUILD_DIR" +pushd "$GCC_BUILD_DIR" + +# Run the build as specified in the build arguments. +echo "Running configuration" +$GCC_SOURCE_DIR/configure --prefix=$GCC_INSTALL_DIR \ + --disable-bootstrap --disable-libgomp --disable-libitm \ + --disable-libvtv --disable-libcilkrts --disable-libmpx \ + --disable-liboffloadmic --disable-libcc1 --enable-languages=c,c++ + +NPROC=`nproc` +echo "Running build with $NPROC threads" +make -j$NPROC + +echo "Installing to $GCC_INSTALL_DIR" +make install -j$NPROC + +popd + +# Cleanup. +rm -rf "$GCC_BUILD_DIR" + +echo "Done"
\ No newline at end of file diff --git a/lib/libcxx/utils/docker/scripts/build_install_llvm.sh b/lib/libcxx/utils/docker/scripts/build_install_llvm.sh new file mode 100755 index 00000000000..6f19a96a1b7 --- /dev/null +++ b/lib/libcxx/utils/docker/scripts/build_install_llvm.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +#===- llvm/utils/docker/scripts/build_install_llvm.sh ---------------------===// +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===-----------------------------------------------------------------------===// + +set -e + +function show_usage() { + cat << EOF +Usage: build_install_llvm.sh [options] -- [cmake-args] + +Run cmake with the specified arguments. Used inside docker container. +Passes additional -DCMAKE_INSTALL_PREFIX and puts the build results into +the directory specified by --to option. + +Available options: + -h|--help show this help message + -i|--install-target name of a cmake install target to build and include in + the resulting archive. Can be specified multiple times. + --install destination directory where to install the targets. + --source location of the source tree. + --build location to use as the build directory. +Required options: --to, --source, --build, and at least one --install-target. + +All options after '--' are passed to CMake invocation. +EOF +} + +CMAKE_ARGS="" +CMAKE_INSTALL_TARGETS="" +CLANG_INSTALL_DIR="" +CLANG_SOURCE_DIR="" +CLANG_BUILD_DIR="" + +while [[ $# -gt 0 ]]; do + case "$1" in + -i|--install-target) + shift + CMAKE_INSTALL_TARGETS="$CMAKE_INSTALL_TARGETS $1" + shift + ;; + --source) + shift + CLANG_SOURCE_DIR="$1" + shift + ;; + --build) + shift + CLANG_BUILD_DIR="$1" + shift + ;; + --install) + shift + CLANG_INSTALL_DIR="$1" + shift + ;; + --) + shift + CMAKE_ARGS="$*" + shift $# + ;; + -h|--help) + show_usage + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 1 + esac +done + +if [ "$CLANG_SOURCE_DIR" == "" ]; then + echo "No source directory. Please pass --source." + exit 1 +fi + +if [ "$CLANG_BUILD_DIR" == "" ]; then + echo "No build directory. Please pass --build" + exit 1 +fi + +if [ "$CMAKE_INSTALL_TARGETS" == "" ]; then + echo "No install targets. Please pass one or more --install-target." + exit 1 +fi + +if [ "$CLANG_INSTALL_DIR" == "" ]; then + echo "No install directory. Please specify the --to argument." + exit 1 +fi + +echo "Building in $CLANG_BUILD_DIR" +mkdir -p "$CLANG_BUILD_DIR" +pushd "$CLANG_BUILD_DIR" + +# Run the build as specified in the build arguments. +echo "Running build" +cmake -GNinja \ + -DCMAKE_INSTALL_PREFIX="$CLANG_INSTALL_DIR" \ + $CMAKE_ARGS \ + "$CLANG_SOURCE_DIR" +ninja $CMAKE_INSTALL_TARGETS + +popd + +# Cleanup. +rm -rf "$CLANG_BUILD_DIR" + +echo "Done" diff --git a/lib/libcxx/utils/docker/scripts/checkout_git.sh b/lib/libcxx/utils/docker/scripts/checkout_git.sh new file mode 100755 index 00000000000..222700229c5 --- /dev/null +++ b/lib/libcxx/utils/docker/scripts/checkout_git.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash +#===- llvm/utils/docker/scripts/checkout.sh ---------------------===// +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===-----------------------------------------------------------------------===// + +set -e + +function show_usage() { + cat << EOF +Usage: checkout.sh [options] + +Checkout svn sources into /tmp/clang-build/src. Used inside a docker container. + +Available options: + -h|--help show this help message + -b|--branch svn branch to checkout, i.e. 'trunk', + 'branches/release_40' + (default: 'trunk') + -p|--llvm-project name of an svn project to checkout. + For clang, please use 'clang', not 'cfe'. + Project 'llvm' is always included and ignored, if + specified. + Can be specified multiple times. +EOF +} + +LLVM_BRANCH="" +# We always checkout llvm +LLVM_PROJECTS="llvm" +SOURCE_DIR="" + +function contains_project() { + local TARGET_PROJ="$1" + local PROJ + for PROJ in $LLVM_PROJECTS; do + if [ "$PROJ" == "$TARGET_PROJ" ]; then + return 0 + fi + done + return 1 +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --to) + shift + SOURCE_DIR="$1" + shift + ;; + -b|--branch) + shift + LLVM_BRANCH="$1" + shift + ;; + -p|--llvm-project) + shift + PROJ="$1" + shift + + if [ "$PROJ" == "cfe" ]; then + PROJ="clang" + fi + + if ! contains_project "$PROJ" ; then + if [ "$PROJ" == "clang-tools-extra" ] && [ ! contains_project "clang" ]; then + echo "Project 'clang-tools-extra' specified before 'clang'. Adding 'clang' to a list of projects first." + LLVM_PROJECTS="$LLVM_PROJECTS clang" + fi + LLVM_PROJECTS="$LLVM_PROJECTS $PROJ" + else + echo "Project '$PROJ' is already enabled, ignoring extra occurrences." + fi + ;; + -h|--help) + show_usage + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 1 + esac +done + +if [ "$SOURCE_DIR" == "" ]; then + echo "Must specify checkout directory using --to" + exit 1 +fi + +if [ "$LLVM_BRANCH" == "" ]; then + GIT_BRANCH_ARG="" +else + GIT_BRANCH_ARG="--branch $LLVM_BRANCH" +fi + +if [ "$LLVM_SVN_REV" != "" ]; then + SVN_REV_ARG="-r$LLVM_SVN_REV" + echo "Checking out svn revision r$LLVM_SVN_REV." +else + SVN_REV_ARG="" + echo "Checking out latest svn revision." +fi + +# Get the sources from svn. +echo "Checking out sources from git" + +for LLVM_PROJECT in $LLVM_PROJECTS; do + if [ "$LLVM_PROJECT" == "llvm" ]; then + CHECKOUT_DIR="$SOURCE_DIR" + elif [ "$LLVM_PROJECT" == "libcxx" ] || [ "$LLVM_PROJECT" == "libcxxabi" ] || [ "$LLVM_PROJECT" == "compiler-rt" ]; then + CHECKOUT_DIR="$SOURCE_DIR/projects/$LLVM_PROJECT" + elif [ "$LLVM_PROJECT" == "clang" ]; then + CHECKOUT_DIR="$SOURCE_DIR/tools/clang" + elif [ "$LLVM_PROJECT" == "clang-tools-extra" ]; then + CHECKOUT_DIR="$SOURCE_DIR/tools/clang/tools/extra" + else + CHECKOUT_DIR="$SOURCE_DIR/$LLVM_PROJECT" + fi + + echo "Checking out https://git.llvm.org/git/$LLVM_PROJECT to $CHECKOUT_DIR" + git clone --depth=1 $GIT_BRANCH_ARG \ + "https://git.llvm.org/git/$LLVM_PROJECT.git" \ + "$CHECKOUT_DIR" +done + +echo "Done" diff --git a/lib/libcxx/utils/docker/scripts/docker_start_buildbots.sh b/lib/libcxx/utils/docker/scripts/docker_start_buildbots.sh new file mode 100755 index 00000000000..f47ddcd2481 --- /dev/null +++ b/lib/libcxx/utils/docker/scripts/docker_start_buildbots.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -x + +# Update the libc++ sources in the image in order to use the most recent version of +# run_buildbots.sh +cd /libcxx +git pull +/libcxx/utils/docker/scripts/run_buildbot.sh "$@" diff --git a/lib/libcxx/utils/docker/scripts/install_clang_packages.sh b/lib/libcxx/utils/docker/scripts/install_clang_packages.sh new file mode 100755 index 00000000000..fabee0e8147 --- /dev/null +++ b/lib/libcxx/utils/docker/scripts/install_clang_packages.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +#===- libcxx/utils/docker/scripts/install_clang_package.sh -----------------===// +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===-----------------------------------------------------------------------===// + +set -e + +function show_usage() { + cat << EOF +Usage: install_clang_package.sh [options] + +Install +Available options: + -h|--help show this help message + --version the numeric version of the package to use. +EOF +} + +VERSION="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --version) + shift + VERSION="$1" + shift + ;; + -h|--help) + show_usage + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 1 + esac +done + + + +curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - +add-apt-repository -s "deb http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs) main" +apt-get update +apt-get install -y --no-install-recommends clang + +echo "Testing clang version..." +clang --version + +echo "Testing clang++ version..." +clang++ --version + +# Figure out the libc++ and libc++abi package versions that we want. +if [ "$VERSION" == "" ]; then + VERSION="$(apt-cache search 'libc\+\+-[0-9]-dev' | awk '{print $1}' | awk -F- '{print $2}')" + echo "Installing version '$VERSION'" +fi + +apt-get install -y --no-install-recommends "libc++-$VERSION-dev" "libc++abi-$VERSION-dev" + +echo "Done" diff --git a/lib/libcxx/utils/docker/scripts/run_buildbot.sh b/lib/libcxx/utils/docker/scripts/run_buildbot.sh new file mode 100755 index 00000000000..45f5a1cf6bf --- /dev/null +++ b/lib/libcxx/utils/docker/scripts/run_buildbot.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +set -x + +BOT_DIR=/b +BOT_NAME=$1 +BOT_PASS=$2 + +mkdir -p $BOT_DIR + +#curl "https://repo.stackdriver.com/stack-install.sh" | bash -s -- --write-gcm + +apt-get update -y +apt-get upgrade -y + +# FIXME(EricWF): Remove this hack. It's only in place to temporarily fix linking libclang_rt from the +# debian packages. +# WARNING: If you're not a buildbot, DO NOT RUN! +apt-get install lld-8 +rm /usr/bin/ld +ln -s /usr/bin/lld-8 /usr/bin/ld + +systemctl set-property buildslave.service TasksMax=100000 + +buildslave stop $BOT_DIR + +chown buildbot:buildbot $BOT_DIR + +echo "Connecting as $BOT_NAME" +buildslave create-slave --allow-shutdown=signal $BOT_DIR lab.llvm.org:9990 $BOT_NAME $BOT_PASS + +echo "Eric Fiselier <ericwf@google.com>" > $BOT_DIR/info/admin + +{ + uname -a | head -n1 + cmake --version | head -n1 + g++ --version | head -n1 + ld --version | head -n1 + date + lscpu +} > $BOT_DIR/info/host + +echo "SLAVE_RUNNER=/usr/bin/buildslave +SLAVE_ENABLED[1]=\"1\" +SLAVE_NAME[1]=\"buildslave1\" +SLAVE_USER[1]=\"buildbot\" +SLAVE_BASEDIR[1]=\"$BOT_DIR\" +SLAVE_OPTIONS[1]=\"\" +SLAVE_PREFIXCMD[1]=\"\"" > /etc/default/buildslave + +chown -R buildbot:buildbot $BOT_DIR +systemctl daemon-reload +service buildslave restart + +sleep 30 +cat $BOT_DIR/twistd.log +grep "slave is ready" $BOT_DIR/twistd.log || shutdown now + +# GCE can restart instance after 24h in the middle of the build. +# Gracefully restart before that happen. +sleep 72000 +while pkill -SIGHUP buildslave; do sleep 5; done; +shutdown now
\ No newline at end of file diff --git a/lib/libcxx/utils/google-benchmark/.clang-format b/lib/libcxx/utils/google-benchmark/.clang-format new file mode 100644 index 00000000000..4b3f13fa55e --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/.clang-format @@ -0,0 +1,5 @@ +--- +Language: Cpp +BasedOnStyle: Google +... + diff --git a/lib/libcxx/utils/google-benchmark/.gitignore b/lib/libcxx/utils/google-benchmark/.gitignore index 3c1b4f2183e..8c30e28f53a 100644 --- a/lib/libcxx/utils/google-benchmark/.gitignore +++ b/lib/libcxx/utils/google-benchmark/.gitignore @@ -6,6 +6,7 @@ *.dylib *.cmake !/cmake/*.cmake +!/test/AssemblyTests.cmake *~ *.pyc __pycache__ @@ -41,6 +42,17 @@ build.ninja install_manifest.txt rules.ninja +# bazel output symlinks. +bazel-* + # out-of-source build top-level folders. build/ _build/ +build*/ + +# in-source dependencies +/googletest/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +CMakeSettings.json diff --git a/lib/libcxx/utils/google-benchmark/.travis-libcxx-setup.sh b/lib/libcxx/utils/google-benchmark/.travis-libcxx-setup.sh new file mode 100644 index 00000000000..a591743c6a6 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/.travis-libcxx-setup.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# Install a newer CMake version +curl -sSL https://cmake.org/files/v3.6/cmake-3.6.1-Linux-x86_64.sh -o install-cmake.sh +chmod +x install-cmake.sh +sudo ./install-cmake.sh --prefix=/usr/local --skip-license + +# Checkout LLVM sources +git clone --depth=1 https://github.com/llvm-mirror/llvm.git llvm-source +git clone --depth=1 https://github.com/llvm-mirror/libcxx.git llvm-source/projects/libcxx +git clone --depth=1 https://github.com/llvm-mirror/libcxxabi.git llvm-source/projects/libcxxabi + +# Setup libc++ options +if [ -z "$BUILD_32_BITS" ]; then + export BUILD_32_BITS=OFF && echo disabling 32 bit build +fi + +# Build and install libc++ (Use unstable ABI for better sanitizer coverage) +mkdir llvm-build && cd llvm-build +cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr \ + -DLIBCXX_ABI_UNSTABLE=ON \ + -DLLVM_USE_SANITIZER=${LIBCXX_SANITIZER} \ + -DLLVM_BUILD_32_BITS=${BUILD_32_BITS} \ + ../llvm-source +make cxx -j2 +sudo make install-cxxabi install-cxx +cd ../ diff --git a/lib/libcxx/utils/google-benchmark/.travis.yml b/lib/libcxx/utils/google-benchmark/.travis.yml new file mode 100644 index 00000000000..4625dfb0878 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/.travis.yml @@ -0,0 +1,199 @@ +sudo: required +dist: trusty +language: cpp + +env: + global: + - /usr/local/bin:$PATH + +matrix: + include: + - compiler: gcc + addons: + apt: + packages: + - lcov + env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Coverage + - compiler: gcc + env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Debug + - compiler: gcc + env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Release + - compiler: gcc + addons: + apt: + packages: + - g++-multilib + env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Debug BUILD_32_BITS=ON + - compiler: gcc + addons: + apt: + packages: + - g++-multilib + env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Release BUILD_32_BITS=ON + - compiler: gcc + env: + - INSTALL_GCC6_FROM_PPA=1 + - COMPILER=g++-6 C_COMPILER=gcc-6 BUILD_TYPE=Debug + - ENABLE_SANITIZER=1 + - EXTRA_FLAGS="-fno-omit-frame-pointer -g -O2 -fsanitize=undefined,address -fuse-ld=gold" + - compiler: clang + env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Debug + - compiler: clang + env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Release + # Clang w/ libc++ + - compiler: clang + addons: + apt: + packages: + clang-3.8 + env: + - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug + - LIBCXX_BUILD=1 + - EXTRA_FLAGS="-stdlib=libc++" + - compiler: clang + addons: + apt: + packages: + clang-3.8 + env: + - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release + - LIBCXX_BUILD=1 + - EXTRA_FLAGS="-stdlib=libc++" + # Clang w/ 32bit libc++ + - compiler: clang + addons: + apt: + packages: + - clang-3.8 + - g++-multilib + env: + - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug + - LIBCXX_BUILD=1 + - BUILD_32_BITS=ON + - EXTRA_FLAGS="-stdlib=libc++ -m32" + # Clang w/ 32bit libc++ + - compiler: clang + addons: + apt: + packages: + - clang-3.8 + - g++-multilib + env: + - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release + - LIBCXX_BUILD=1 + - BUILD_32_BITS=ON + - EXTRA_FLAGS="-stdlib=libc++ -m32" + # Clang w/ libc++, ASAN, UBSAN + - compiler: clang + addons: + apt: + packages: + clang-3.8 + env: + - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug + - LIBCXX_BUILD=1 LIBCXX_SANITIZER="Undefined;Address" + - ENABLE_SANITIZER=1 + - EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=undefined,address -fno-sanitize-recover=all" + - UBSAN_OPTIONS=print_stacktrace=1 + # Clang w/ libc++ and MSAN + - compiler: clang + addons: + apt: + packages: + clang-3.8 + env: + - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug + - LIBCXX_BUILD=1 LIBCXX_SANITIZER=MemoryWithOrigins + - ENABLE_SANITIZER=1 + - EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins" + # Clang w/ libc++ and MSAN + - compiler: clang + addons: + apt: + packages: + clang-3.8 + env: + - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=RelWithDebInfo + - LIBCXX_BUILD=1 LIBCXX_SANITIZER=Thread + - ENABLE_SANITIZER=1 + - EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all" + - os: osx + osx_image: xcode8.3 + compiler: clang + env: + - COMPILER=clang++ BUILD_TYPE=Debug + - os: osx + osx_image: xcode8.3 + compiler: clang + env: + - COMPILER=clang++ BUILD_TYPE=Release + - os: osx + osx_image: xcode8.3 + compiler: clang + env: + - COMPILER=clang++ BUILD_TYPE=Release BUILD_32_BITS=ON + - os: osx + osx_image: xcode8.3 + compiler: gcc + env: + - COMPILER=g++-7 C_COMPILER=gcc-7 BUILD_TYPE=Debug + +before_script: + - if [ -n "${LIBCXX_BUILD}" ]; then + source .travis-libcxx-setup.sh; + fi + - if [ -n "${ENABLE_SANITIZER}" ]; then + export EXTRA_OPTIONS="-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF"; + else + export EXTRA_OPTIONS=""; + fi + - mkdir -p build && cd build + +before_install: + - if [ -z "$BUILD_32_BITS" ]; then + export BUILD_32_BITS=OFF && echo disabling 32 bit build; + fi + - if [ -n "${INSTALL_GCC6_FROM_PPA}" ]; then + sudo add-apt-repository -y "ppa:ubuntu-toolchain-r/test"; + sudo apt-get update --option Acquire::Retries=100 --option Acquire::http::Timeout="60"; + fi + +install: + - if [ -n "${INSTALL_GCC6_FROM_PPA}" ]; then + travis_wait sudo -E apt-get -yq --no-install-suggests --no-install-recommends install g++-6; + fi + - if [ "${TRAVIS_OS_NAME}" == "linux" -a "${BUILD_32_BITS}" == "OFF" ]; then + travis_wait sudo -E apt-get -y --no-install-suggests --no-install-recommends install llvm-3.9-tools; + sudo cp /usr/lib/llvm-3.9/bin/FileCheck /usr/local/bin/; + fi + - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then + PATH=~/.local/bin:${PATH}; + pip install --user --upgrade pip; + travis_wait pip install --user cpp-coveralls; + fi + - if [ "${C_COMPILER}" == "gcc-7" -a "${TRAVIS_OS_NAME}" == "osx" ]; then + rm -f /usr/local/include/c++; + brew update; + travis_wait brew install gcc@7; + fi + - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then + sudo apt-get update -qq; + sudo apt-get install -qq unzip; + wget https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-linux-x86_64.sh --output-document bazel-installer.sh; + travis_wait sudo bash bazel-installer.sh; + fi + - if [ "${TRAVIS_OS_NAME}" == "osx" ]; then + curl -L -o bazel-installer.sh https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-darwin-x86_64.sh; + travis_wait sudo bash bazel-installer.sh; + fi + +script: + - cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_CXX_FLAGS="${EXTRA_FLAGS}" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON -DBENCHMARK_BUILD_32_BITS=${BUILD_32_BITS} ${EXTRA_OPTIONS} .. + - make + - ctest -C ${BUILD_TYPE} --output-on-failure + - bazel test -c dbg --define google_benchmark.have_regex=posix --announce_rc --verbose_failures --test_output=errors --keep_going //test/... + +after_success: + - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then + coveralls --include src --include include --gcov-options '\-lp' --root .. --build-root .; + fi diff --git a/lib/libcxx/utils/google-benchmark/.ycm_extra_conf.py b/lib/libcxx/utils/google-benchmark/.ycm_extra_conf.py new file mode 100644 index 00000000000..5649ddcc749 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/.ycm_extra_conf.py @@ -0,0 +1,115 @@ +import os +import ycm_core + +# These are the compilation flags that will be used in case there's no +# compilation database set (by default, one is not set). +# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR. +flags = [ +'-Wall', +'-Werror', +'-pedantic-errors', +'-std=c++0x', +'-fno-strict-aliasing', +'-O3', +'-DNDEBUG', +# ...and the same thing goes for the magic -x option which specifies the +# language that the files to be compiled are written in. This is mostly +# relevant for c++ headers. +# For a C project, you would set this to 'c' instead of 'c++'. +'-x', 'c++', +'-I', 'include', +'-isystem', '/usr/include', +'-isystem', '/usr/local/include', +] + + +# Set this to the absolute path to the folder (NOT the file!) containing the +# compile_commands.json file to use that instead of 'flags'. See here for +# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html +# +# Most projects will NOT need to set this to anything; you can just change the +# 'flags' list of compilation flags. Notice that YCM itself uses that approach. +compilation_database_folder = '' + +if os.path.exists( compilation_database_folder ): + database = ycm_core.CompilationDatabase( compilation_database_folder ) +else: + database = None + +SOURCE_EXTENSIONS = [ '.cc' ] + +def DirectoryOfThisScript(): + return os.path.dirname( os.path.abspath( __file__ ) ) + + +def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): + if not working_directory: + return list( flags ) + new_flags = [] + make_next_absolute = False + path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith( '/' ): + new_flag = os.path.join( working_directory, flag ) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith( path_flag ): + path = flag[ len( path_flag ): ] + new_flag = path_flag + os.path.join( working_directory, path ) + break + + if new_flag: + new_flags.append( new_flag ) + return new_flags + + +def IsHeaderFile( filename ): + extension = os.path.splitext( filename )[ 1 ] + return extension in [ '.h', '.hxx', '.hpp', '.hh' ] + + +def GetCompilationInfoForFile( filename ): + # The compilation_commands.json file generated by CMake does not have entries + # for header files. So we do our best by asking the db for flags for a + # corresponding source file, if any. If one exists, the flags for that file + # should be good enough. + if IsHeaderFile( filename ): + basename = os.path.splitext( filename )[ 0 ] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists( replacement_file ): + compilation_info = database.GetCompilationInfoForFile( + replacement_file ) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile( filename ) + + +def FlagsForFile( filename, **kwargs ): + if database: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile( filename ) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_ ) + else: + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) + + return { + 'flags': final_flags, + 'do_cache': True + } diff --git a/lib/libcxx/utils/google-benchmark/AUTHORS b/lib/libcxx/utils/google-benchmark/AUTHORS index daea1f66f07..09e2e0551ad 100644 --- a/lib/libcxx/utils/google-benchmark/AUTHORS +++ b/lib/libcxx/utils/google-benchmark/AUTHORS @@ -36,6 +36,7 @@ Maxim Vafin <maxvafin@gmail.com> MongoDB Inc. Nick Hutchinson <nshutchinson@gmail.com> Oleksandr Sochka <sasha.sochka@gmail.com> +Ori Livneh <ori.livneh@gmail.com> Paul Redmond <paul.redmond@gmail.com> Radoslav Yovchev <radoslav.tm@gmail.com> Roman Lebedev <lebedev.ri@gmail.com> diff --git a/lib/libcxx/utils/google-benchmark/CMakeLists.txt b/lib/libcxx/utils/google-benchmark/CMakeLists.txt index 8ddacabb6e0..310c7ee9f6b 100644 --- a/lib/libcxx/utils/google-benchmark/CMakeLists.txt +++ b/lib/libcxx/utils/google-benchmark/CMakeLists.txt @@ -16,7 +16,11 @@ option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON) option(BENCHMARK_ENABLE_EXCEPTIONS "Enable the use of exceptions in the benchmark library." ON) option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF) option(BENCHMARK_USE_LIBCXX "Build and test using libc++ as the standard library." OFF) -option(BENCHMARK_BUILD_32_BITS "Build a 32 bit version of the library." OFF) +if(NOT MSVC) + option(BENCHMARK_BUILD_32_BITS "Build a 32 bit version of the library." OFF) +else() + set(BENCHMARK_BUILD_32_BITS OFF CACHE BOOL "Build a 32 bit version of the library - unsupported when using MSVC)" FORCE) +endif() option(BENCHMARK_ENABLE_INSTALL "Enable installation of benchmark. (Projects embedding benchmark may want to turn this OFF.)" ON) # Allow unmet dependencies to be met using CMake's ExternalProject mechanics, which @@ -75,7 +79,7 @@ get_git_version(GIT_VERSION) # Tell the user what versions we are using string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" VERSION ${GIT_VERSION}) -message("-- Version: ${VERSION}") +message(STATUS "Version: ${VERSION}") # The version of the libraries set(GENERIC_LIB_VERSION ${VERSION}) @@ -90,7 +94,7 @@ if (BENCHMARK_BUILD_32_BITS) add_required_cxx_compiler_flag(-m32) endif() -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") +if (MSVC) # Turn compiler warnings up to 11 string(REGEX REPLACE "[-/]W[1-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") @@ -99,6 +103,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if (NOT BENCHMARK_ENABLE_EXCEPTIONS) add_cxx_compiler_flag(-EHs-) add_cxx_compiler_flag(-EHa-) + add_definitions(-D_HAS_EXCEPTIONS=0) endif() # Link time optimisation if (BENCHMARK_ENABLE_LTO) @@ -163,7 +168,7 @@ else() endif() # ICC17u2: overloaded virtual function "benchmark::Fixture::SetUp" is only partially overridden # (because of deprecated overload) - add_cxx_compiler_flag(-wd654) + add_cxx_compiler_flag(-wd654) add_cxx_compiler_flag(-Wthread-safety) if (HAVE_CXX_FLAG_WTHREAD_SAFETY) cxx_feature_check(THREAD_SAFETY_ATTRIBUTES) @@ -189,7 +194,7 @@ else() if (GCC_RANLIB) set(CMAKE_RANLIB ${GCC_RANLIB}) endif() - elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") + elseif("${CMAKE_C_COMPILER_ID}" MATCHES "Clang") include(llvm-toolchain) endif() endif() @@ -214,12 +219,12 @@ else() endif() if (BENCHMARK_USE_LIBCXX) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") add_cxx_compiler_flag(-stdlib=libc++) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") add_cxx_compiler_flag(-nostdinc++) - message("libc++ header path must be manually specified using CMAKE_CXX_FLAGS") + message(WARNING "libc++ header path must be manually specified using CMAKE_CXX_FLAGS") # Adding -nodefaultlibs directly to CMAKE_<TYPE>_LINKER_FLAGS will break # configuration checks such as 'find_package(Threads)' list(APPEND BENCHMARK_CXX_LINKER_FLAGS -nodefaultlibs) diff --git a/lib/libcxx/utils/google-benchmark/CONTRIBUTORS b/lib/libcxx/utils/google-benchmark/CONTRIBUTORS index 2ff2f2a8fa0..ee74ff886c0 100644 --- a/lib/libcxx/utils/google-benchmark/CONTRIBUTORS +++ b/lib/libcxx/utils/google-benchmark/CONTRIBUTORS @@ -27,6 +27,7 @@ Arne Beer <arne@twobeer.de> Billy Robert O'Neal III <billy.oneal@gmail.com> <bion@microsoft.com> Chris Kennelly <ckennelly@google.com> <ckennelly@ckennelly.com> Christopher Seymour <chris.j.seymour@hotmail.com> +Cyrille Faucheux <cyrille.faucheux@gmail.com> David Coeurjolly <david.coeurjolly@liris.cnrs.fr> Deniz Evrenci <denizevrenci@gmail.com> Dominic Hamon <dma@stripysock.com> <dominic@google.com> @@ -50,6 +51,7 @@ Matt Clarkson <mattyclarkson@gmail.com> Maxim Vafin <maxvafin@gmail.com> Nick Hutchinson <nshutchinson@gmail.com> Oleksandr Sochka <sasha.sochka@gmail.com> +Ori Livneh <ori.livneh@gmail.com> Pascal Leroy <phl@google.com> Paul Redmond <paul.redmond@gmail.com> Pierre Phaneuf <pphaneuf@google.com> diff --git a/lib/libcxx/utils/google-benchmark/README.md b/lib/libcxx/utils/google-benchmark/README.md index 80e69f6e10d..858ea2334ef 100644 --- a/lib/libcxx/utils/google-benchmark/README.md +++ b/lib/libcxx/utils/google-benchmark/README.md @@ -6,11 +6,9 @@ A library to support the benchmarking of functions, similar to unit-tests. -Discussion group: https://groups.google.com/d/forum/benchmark-discuss +[Discussion group](https://groups.google.com/d/forum/benchmark-discuss) -IRC channel: https://freenode.net #googlebenchmark - -[Known issues and common problems](#known-issues) +IRC channel: [freenode](https://freenode.net) #googlebenchmark [Additional Tooling Documentation](docs/tools.md) @@ -47,11 +45,10 @@ to `CMAKE_ARGS`. For Ubuntu and Debian Based System -First make sure you have git and cmake installed (If not please install it) +First make sure you have git and cmake installed (If not please install them) ``` -sudo apt-get install git -sudo apt-get install cmake +sudo apt-get install git cmake ``` Now, let's clone the repository and build it @@ -59,22 +56,20 @@ Now, let's clone the repository and build it ``` git clone https://github.com/google/benchmark.git cd benchmark -git clone https://github.com/google/googletest.git +# If you want to build tests and don't use BENCHMARK_DOWNLOAD_DEPENDENCIES, then +# git clone https://github.com/google/googletest.git mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=RELEASE make ``` -We need to install the library globally now +If you need to install the library globally ``` sudo make install ``` -Now you have google/benchmark installed in your machine -Note: Don't forget to link to pthread library while building - ## Stable and Experimental Library Versions The main branch contains the latest stable version of the benchmarking library; @@ -87,15 +82,16 @@ to use, test, and provide feedback on the new features are encouraged to try this branch. However, this branch provides no stability guarantees and reserves the right to change and break the API at any time. -## Prerequisite knowledge - -Before attempting to understand this framework one should ideally have some familiarity with the structure and format of the Google Test framework, upon which it is based. Documentation for Google Test, including a "Getting Started" (primer) guide, is available here: -https://github.com/google/googletest/blob/master/googletest/docs/primer.md +## Further knowledge +It may help to read the [Google Test documentation](https://github.com/google/googletest/blob/master/googletest/docs/primer.md) +as some of the structural aspects of the APIs are similar. ## Example usage ### Basic usage -Define a function that executes the code to be measured. +Define a function that executes the code to be measured, register it as a +benchmark function using the `BENCHMARK` macro, and ensure an appropriate `main` +function is available: ```c++ #include <benchmark/benchmark.h> @@ -123,7 +119,23 @@ Don't forget to inform your linker to add benchmark library e.g. through `BENCHMARK_MAIN();` at the end of the source file and link against `-lbenchmark_main` to get the same default behavior. -The benchmark library will reporting the timing for the code within the `for(...)` loop. +The benchmark library will measure and report the timing for code within the +`for(...)` loop. + +#### Platform-specific libraries +When the library is built using GCC it is necessary to link with the pthread +library due to how GCC implements `std::thread`. Failing to link to pthread will +lead to runtime exceptions (unless you're using libc++), not linker errors. See +[issue #67](https://github.com/google/benchmark/issues/67) for more details. You +can link to pthread by adding `-pthread` to your linker command. Note, you can +also use `-lpthread`, but there are potential issues with ordering of command +line parameters if you use that. + +If you're running benchmarks on Windows, the shlwapi library (`-lshlwapi`) is +also required. + +If you're running benchmarks on solaris, you'll want the kstat library linked in +too (`-lkstat`). ### Passing arguments Sometimes a family of benchmarks can be implemented with just one routine that @@ -243,7 +255,7 @@ that might be used to customize high-order term calculation. ```c++ BENCHMARK(BM_StringCompare)->RangeMultiplier(2) - ->Range(1<<10, 1<<18)->Complexity([](int n)->double{return n; }); + ->Range(1<<10, 1<<18)->Complexity([](int64_t n)->double{return n; }); ``` ### Templated benchmarks @@ -252,7 +264,7 @@ messages of size `sizeof(v)` `range_x` times. It also outputs throughput in the absence of multiprogramming. ```c++ -template <class Q> int BM_Sequential(benchmark::State& state) { +template <class Q> void BM_Sequential(benchmark::State& state) { Q q; typename Q::value_type v; for (auto _ : state) { @@ -416,6 +428,26 @@ BENCHMARK(BM_test)->Range(8, 8<<10)->UseRealTime(); Without `UseRealTime`, CPU time is used by default. +## Controlling timers +Normally, the entire duration of the work loop (`for (auto _ : state) {}`) +is measured. But sometimes, it is nessesary to do some work inside of +that loop, every iteration, but without counting that time to the benchmark time. +That is possible, althought it is not recommended, since it has high overhead. + +```c++ +static void BM_SetInsert_With_Timer_Control(benchmark::State& state) { + std::set<int> data; + for (auto _ : state) { + state.PauseTiming(); // Stop timers. They will not count until they are resumed. + data = ConstructRandomSet(state.range(0)); // Do something that should not be measured + state.ResumeTiming(); // And resume timers. They are now counting again. + // The rest will be measured. + for (int j = 0; j < state.range(1); ++j) + data.insert(RandomNumber()); + } +} +BENCHMARK(BM_SetInsert_With_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}}); +``` ## Manual timing For benchmarking something for which neither CPU time nor real-time are @@ -522,15 +554,7 @@ order to manually set the time unit, you can specify it manually: BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); ``` -## Controlling number of iterations -In all cases, the number of iterations for which the benchmark is run is -governed by the amount of time the benchmark takes. Concretely, the number of -iterations is at least one, not more than 1e9, until CPU time is greater than -the minimum time, or the wallclock time is 5x minimum time. The minimum time is -set as a flag `--benchmark_min_time` or per benchmark by calling `MinTime` on -the registered benchmark object. - -## Reporting the mean, median and standard deviation by repeated benchmarks +### Reporting the mean, median and standard deviation by repeated benchmarks By default each benchmark is run once and that single result is reported. However benchmarks are often noisy and a single result may not be representative of the overall behavior. For this reason it's possible to repeatedly rerun the @@ -541,12 +565,20 @@ The number of runs of each benchmark is specified globally by the `Repetitions` on the registered benchmark object. When a benchmark is run more than once the mean, median and standard deviation of the runs will be reported. -Additionally the `--benchmark_report_aggregates_only={true|false}` flag or -`ReportAggregatesOnly(bool)` function can be used to change how repeated tests -are reported. By default the result of each repeated run is reported. When this -option is `true` only the mean, median and standard deviation of the runs is reported. -Calling `ReportAggregatesOnly(bool)` on a registered benchmark object overrides -the value of the flag for that benchmark. +Additionally the `--benchmark_report_aggregates_only={true|false}`, +`--benchmark_display_aggregates_only={true|false}` flags or +`ReportAggregatesOnly(bool)`, `DisplayAggregatesOnly(bool)` functions can be +used to change how repeated tests are reported. By default the result of each +repeated run is reported. When `report aggregates only` option is `true`, +only the aggregates (i.e. mean, median and standard deviation, maybe complexity +measurements if they were requested) of the runs is reported, to both the +reporters - standard output (console), and the file. +However when only the `display aggregates only` option is `true`, +only the aggregates are displayed in the standard output, while the file +output still contains everything. +Calling `ReportAggregatesOnly(bool)` / `DisplayAggregatesOnly(bool)` on a +registered benchmark object overrides the value of the appropriate flag for that +benchmark. ## User-defined statistics for repeated benchmarks While having mean, median and standard deviation is nice, this may not be @@ -653,9 +685,12 @@ In multithreaded benchmarks, each counter is set on the calling thread only. When the benchmark finishes, the counters from each thread will be summed; the resulting sum is the value which will be shown for the benchmark. -The `Counter` constructor accepts two parameters: the value as a `double` -and a bit flag which allows you to show counters as rates and/or as -per-thread averages: +The `Counter` constructor accepts three parameters: the value as a `double` +; a bit flag which allows you to show counters as rates, and/or as per-thread +iteration, and/or as per-thread averages, and/or iteration invariants; +and a flag specifying the 'unit' - i.e. is 1k a 1000 (default, +`benchmark::Counter::OneK::kIs1000`), or 1024 +(`benchmark::Counter::OneK::kIs1024`)? ```c++ // sets a simple counter @@ -671,6 +706,9 @@ per-thread averages: // There's also a combined flag: state.counters["FooAvgRate"] = Counter(numFoos,benchmark::Counter::kAvgThreadsRate); + + // This says that we process with the rate of state.range(0) bytes every iteration: + state.counters["BytesProcessed"] = Counter(state.range(0), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::OneK::kIs1024); ``` When you're compiling in C++11 mode or later you can use `insert()` with @@ -810,8 +848,29 @@ BM_memcpy/32 12 ns 12 ns 54687500 BM_memcpy/32k 1834 ns 1837 ns 357143 ``` +## Runtime and reporting considerations +When the benchmark binary is executed, each benchmark function is run serially. +The number of iterations to run is determined dynamically by running the +benchmark a few times and measuring the time taken and ensuring that the +ultimate result will be statistically stable. As such, faster benchmark +functions will be run for more iterations than slower benchmark functions, and +the number of iterations is thus reported. + +In all cases, the number of iterations for which the benchmark is run is +governed by the amount of time the benchmark takes. Concretely, the number of +iterations is at least one, not more than 1e9, until CPU time is greater than +the minimum time, or the wallclock time is 5x minimum time. The minimum time is +set per benchmark by calling `MinTime` on the registered benchmark object. + +Average timings are then reported over the iterations run. If multiple +repetitions are requested using the `--benchmark_repetitions` command-line +option, or at registration time, the benchmark function will be run several +times and statistical results across these repetitions will also be reported. + +As well as the per-benchmark entries, a preamble in the report will include +information about the machine on which the benchmarks are run. -## Output Formats +### Output Formats The library supports multiple output formats. Use the `--benchmark_format=<console|json|csv>` flag to set the format type. `console` is the default format. @@ -879,14 +938,19 @@ name,iterations,real_time,cpu_time,bytes_per_second,items_per_second,label "BM_SetInsert/1024/10",106365,17238.4,8421.53,4.74973e+06,1.18743e+06, ``` -## Output Files +### Output Files The library supports writing the output of the benchmark to a file specified by `--benchmark_out=<filename>`. The format of the output can be specified using `--benchmark_out_format={json|console|csv}`. Specifying `--benchmark_out` does not suppress the console output. +## Result comparison + +It is possible to compare the benchmarking results. See [Additional Tooling Documentation](docs/tools.md) + ## Debug vs Release -By default, benchmark builds as a debug library. You will see a warning in the output when this is the case. To build it as a release library instead, use: +By default, benchmark builds as a debug library. You will see a warning in the +output when this is the case. To build it as a release library instead, use: ``` cmake -DCMAKE_BUILD_TYPE=Release @@ -898,16 +962,11 @@ To enable link-time optimisation, use cmake -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_LTO=true ``` -If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake cache variables, if autodetection fails. -If you are using clang, you may need to set `LLVMAR_EXECUTABLE`, `LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables. - -## Linking against the library +If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake +cache variables, if autodetection fails. -When the library is built using GCC it is necessary to link with `-pthread`, -due to how GCC implements `std::thread`. - -For GCC 4.x failing to link to pthreads will lead to runtime exceptions, not linker errors. -See [issue #67](https://github.com/google/benchmark/issues/67) for more details. +If you are using clang, you may need to set `LLVMAR_EXECUTABLE`, +`LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables. ## Compiler Support @@ -937,14 +996,3 @@ sudo cpupower frequency-set --governor performance ./mybench sudo cpupower frequency-set --governor powersave ``` - -# Known Issues - -### Windows with CMake - -* Users must manually link `shlwapi.lib`. Failure to do so may result -in unresolved symbols. - -### Solaris - -* Users must explicitly link with kstat library (-lkstat compilation flag). diff --git a/lib/libcxx/utils/google-benchmark/WORKSPACE b/lib/libcxx/utils/google-benchmark/WORKSPACE new file mode 100644 index 00000000000..54734f1ea55 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/WORKSPACE @@ -0,0 +1,7 @@ +workspace(name = "com_github_google_benchmark") + +http_archive( + name = "com_google_googletest", + urls = ["https://github.com/google/googletest/archive/3f0cf6b62ad1eb50d8736538363d3580dd640c3e.zip"], + strip_prefix = "googletest-3f0cf6b62ad1eb50d8736538363d3580dd640c3e", +) diff --git a/lib/libcxx/utils/google-benchmark/appveyor.yml b/lib/libcxx/utils/google-benchmark/appveyor.yml new file mode 100644 index 00000000000..cf240190bea --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/appveyor.yml @@ -0,0 +1,50 @@ +version: '{build}' + +image: Visual Studio 2017 + +configuration: + - Debug + - Release + +environment: + matrix: + - compiler: msvc-15-seh + generator: "Visual Studio 15 2017" + + - compiler: msvc-15-seh + generator: "Visual Studio 15 2017 Win64" + + - compiler: msvc-14-seh + generator: "Visual Studio 14 2015" + + - compiler: msvc-14-seh + generator: "Visual Studio 14 2015 Win64" + + - compiler: gcc-5.3.0-posix + generator: "MinGW Makefiles" + cxx_path: 'C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin' + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + +matrix: + fast_finish: true + +install: + # git bash conflicts with MinGW makefiles + - if "%generator%"=="MinGW Makefiles" (set "PATH=%PATH:C:\Program Files\Git\usr\bin;=%") + - if not "%cxx_path%"=="" (set "PATH=%PATH%;%cxx_path%") + +build_script: + - md _build -Force + - cd _build + - echo %configuration% + - cmake -G "%generator%" "-DCMAKE_BUILD_TYPE=%configuration%" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON .. + - cmake --build . --config %configuration% + +test_script: + - ctest -c %configuration% --timeout 300 --output-on-failure + +artifacts: + - path: '_build/CMakeFiles/*.log' + name: logs + - path: '_build/Testing/**/*.xml' + name: test_results diff --git a/lib/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake b/lib/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake index c4c4d660f1e..99b56dd6239 100644 --- a/lib/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake +++ b/lib/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake @@ -28,7 +28,7 @@ function(cxx_feature_check FILE) endif() if (NOT DEFINED COMPILE_${FEATURE}) - message("-- Performing Test ${FEATURE}") + message(STATUS "Performing Test ${FEATURE}") if(CMAKE_CROSSCOMPILING) try_compile(COMPILE_${FEATURE} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp @@ -42,7 +42,7 @@ function(cxx_feature_check FILE) set(RUN_${FEATURE} 1) endif() else() - message("-- Performing Test ${FEATURE}") + message(STATUS "Performing Test ${FEATURE}") try_run(RUN_${FEATURE} COMPILE_${FEATURE} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS} @@ -51,14 +51,14 @@ function(cxx_feature_check FILE) endif() if(RUN_${FEATURE} EQUAL 0) - message("-- Performing Test ${FEATURE} -- success") + message(STATUS "Performing Test ${FEATURE} -- success") set(HAVE_${VAR} 1 PARENT_SCOPE) add_definitions(-DHAVE_${VAR}) else() if(NOT COMPILE_${FEATURE}) - message("-- Performing Test ${FEATURE} -- failed to compile") + message(STATUS "Performing Test ${FEATURE} -- failed to compile") else() - message("-- Performing Test ${FEATURE} -- compiled but failed to run") + message(STATUS "Performing Test ${FEATURE} -- compiled but failed to run") endif() endif() endfunction() diff --git a/lib/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake b/lib/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake index 88cebe3a1ca..4f10f226d7a 100644 --- a/lib/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake +++ b/lib/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake @@ -49,6 +49,6 @@ function(get_git_version var) set(GIT_VERSION "v0.0.0") endif() - message("-- git Version: ${GIT_VERSION}") + message(STATUS "git Version: ${GIT_VERSION}") set(${var} ${GIT_VERSION} PARENT_SCOPE) endfunction() diff --git a/lib/libcxx/utils/google-benchmark/cmake/HandleGTest.cmake b/lib/libcxx/utils/google-benchmark/cmake/HandleGTest.cmake index 7ce1a633d65..b9c14436dbf 100644 --- a/lib/libcxx/utils/google-benchmark/cmake/HandleGTest.cmake +++ b/lib/libcxx/utils/google-benchmark/cmake/HandleGTest.cmake @@ -5,7 +5,7 @@ macro(build_external_gtest) include(ExternalProject) set(GTEST_FLAGS "") if (BENCHMARK_USE_LIBCXX) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") list(APPEND GTEST_FLAGS -stdlib=libc++) else() message(WARNING "Unsupported compiler (${CMAKE_CXX_COMPILER}) when using libc++") @@ -76,11 +76,11 @@ macro(build_external_gtest) endmacro(build_external_gtest) if (BENCHMARK_ENABLE_GTEST_TESTS) - if (IS_DIRECTORY ${CMAKE_SOURCE_DIR}/googletest) - set(GTEST_ROOT "${CMAKE_SOURCE_DIR}/googletest") + if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest) + set(GTEST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/googletest") set(INSTALL_GTEST OFF CACHE INTERNAL "") set(INSTALL_GMOCK OFF CACHE INTERNAL "") - add_subdirectory(${CMAKE_SOURCE_DIR}/googletest) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/googletest) set(GTEST_BOTH_LIBRARIES gtest gmock gmock_main) foreach(HEADER test mock) # CMake 2.8 and older don't respect INTERFACE_INCLUDE_DIRECTORIES, so we diff --git a/lib/libcxx/utils/google-benchmark/docs/tools.md b/lib/libcxx/utils/google-benchmark/docs/tools.md index 70500bd3223..4a3b2e9bd2c 100644 --- a/lib/libcxx/utils/google-benchmark/docs/tools.md +++ b/lib/libcxx/utils/google-benchmark/docs/tools.md @@ -1,84 +1,25 @@ # Benchmark Tools -## compare_bench.py - -The `compare_bench.py` utility which can be used to compare the result of benchmarks. -The program is invoked like: - -``` bash -$ compare_bench.py <old-benchmark> <new-benchmark> [benchmark options]... -``` - -Where `<old-benchmark>` and `<new-benchmark>` either specify a benchmark executable file, or a JSON output file. The type of the input file is automatically detected. If a benchmark executable is specified then the benchmark is run to obtain the results. Otherwise the results are simply loaded from the output file. - -`[benchmark options]` will be passed to the benchmarks invocations. They can be anything that binary accepts, be it either normal `--benchmark_*` parameters, or some custom parameters your binary takes. - -The sample output using the JSON test files under `Inputs/` gives: - -``` bash -$ ./compare_bench.py ./gbench/Inputs/test1_run1.json ./gbench/Inputs/test1_run2.json -Comparing ./gbench/Inputs/test1_run1.json to ./gbench/Inputs/test1_run2.json -Benchmark Time CPU Time Old Time New CPU Old CPU New -------------------------------------------------------------------------------------------------------------- -BM_SameTimes +0.0000 +0.0000 10 10 10 10 -BM_2xFaster -0.5000 -0.5000 50 25 50 25 -BM_2xSlower +1.0000 +1.0000 50 100 50 100 -BM_1PercentFaster -0.0100 -0.0100 100 99 100 99 -BM_1PercentSlower +0.0100 +0.0100 100 101 100 101 -BM_10PercentFaster -0.1000 -0.1000 100 90 100 90 -BM_10PercentSlower +0.1000 +0.1000 100 110 100 110 -BM_100xSlower +99.0000 +99.0000 100 10000 100 10000 -BM_100xFaster -0.9900 -0.9900 10000 100 10000 100 -BM_10PercentCPUToTime +0.1000 -0.1000 100 110 100 90 -BM_ThirdFaster -0.3333 -0.3334 100 67 100 67 -BM_BadTimeUnit -0.9000 +0.2000 0 0 0 1 -``` - -As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`. +## compare.py -When a benchmark executable is run, the raw output from the benchmark is printed in real time to stdout. The sample output using `benchmark/basic_test` for both arguments looks like: +The `compare.py` can be used to compare the result of benchmarks. -``` -./compare_bench.py test/basic_test test/basic_test --benchmark_filter=BM_empty.* -RUNNING: test/basic_test --benchmark_filter=BM_empty.* --benchmark_out=/tmp/tmpN7LF3a -Run on (8 X 4000 MHz CPU s) -2017-11-07 23:28:36 ---------------------------------------------------------------------- -Benchmark Time CPU Iterations ---------------------------------------------------------------------- -BM_empty 4 ns 4 ns 170178757 -BM_empty/threads:8 1 ns 7 ns 103868920 -BM_empty_stop_start 0 ns 0 ns 1000000000 -BM_empty_stop_start/threads:8 0 ns 0 ns 1403031720 -RUNNING: /test/basic_test --benchmark_filter=BM_empty.* --benchmark_out=/tmp/tmplvrIp8 -Run on (8 X 4000 MHz CPU s) -2017-11-07 23:28:38 ---------------------------------------------------------------------- -Benchmark Time CPU Iterations ---------------------------------------------------------------------- -BM_empty 4 ns 4 ns 169534855 -BM_empty/threads:8 1 ns 7 ns 104188776 -BM_empty_stop_start 0 ns 0 ns 1000000000 -BM_empty_stop_start/threads:8 0 ns 0 ns 1404159424 -Comparing ../build/test/basic_test to ../build/test/basic_test -Benchmark Time CPU Time Old Time New CPU Old CPU New ---------------------------------------------------------------------------------------------------------------------- -BM_empty -0.0048 -0.0049 4 4 4 4 -BM_empty/threads:8 -0.0123 -0.0054 1 1 7 7 -BM_empty_stop_start -0.0000 -0.0000 0 0 0 0 -BM_empty_stop_start/threads:8 -0.0029 +0.0001 0 0 0 0 +**NOTE**: the utility relies on the scipy package which can be installed using [these instructions](https://www.scipy.org/install.html). -``` +### Displaying aggregates only -As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`. -Obviously this example doesn't give any useful output, but it's intended to show the output format when 'compare_bench.py' needs to run benchmarks. +The switch `-a` / `--display_aggregates_only` can be used to control the +displayment of the normal iterations vs the aggregates. When passed, it will +be passthrough to the benchmark binaries to be run, and will be accounted for +in the tool itself; only the aggregates will be displayed, but not normal runs. +It only affects the display, the separate runs will still be used to calculate +the U test. -## compare.py +### Modes of operation -The `compare.py` can be used to compare the result of benchmarks. There are three modes of operation: -1. Just compare two benchmarks, what `compare_bench.py` did. +1. Just compare two benchmarks The program is invoked like: ``` bash @@ -240,3 +181,19 @@ Benchmark Time CPU Time Old ``` This is a mix of the previous two modes, two (potentially different) benchmark binaries are run, and a different filter is applied to each one. As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`. + +### U test + +If there is a sufficient repetition count of the benchmarks, the tool can do +a [U Test](https://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_test), of the +null hypothesis that it is equally likely that a randomly selected value from +one sample will be less than or greater than a randomly selected value from a +second sample. + +If the calculated p-value is below this value is lower than the significance +level alpha, then the result is said to be statistically significant and the +null hypothesis is rejected. Which in other words means that the two benchmarks +aren't identical. + +**WARNING**: requires **LARGE** (no less than 9) number of repetitions to be +meaningful! diff --git a/lib/libcxx/utils/google-benchmark/include/benchmark/benchmark.h b/lib/libcxx/utils/google-benchmark/include/benchmark/benchmark.h index 193fffc4bea..a0fd7c6e1ca 100644 --- a/lib/libcxx/utils/google-benchmark/include/benchmark/benchmark.h +++ b/lib/libcxx/utils/google-benchmark/include/benchmark/benchmark.h @@ -241,8 +241,21 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) #endif +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#if defined(__GNUC__) || __has_builtin(__builtin_unreachable) + #define BENCHMARK_UNREACHABLE() __builtin_unreachable() +#elif defined(_MSC_VER) + #define BENCHMARK_UNREACHABLE() __assume(false) +#else + #define BENCHMARK_UNREACHABLE() ((void)0) +#endif + namespace benchmark { class BenchmarkReporter; +class MemoryManager; void Initialize(int* argc, char** argv); @@ -255,7 +268,7 @@ bool ReportUnrecognizedArguments(int argc, char** argv); // of each matching benchmark. Otherwise run each matching benchmark and // report the results. // -// The second and third overload use the specified 'console_reporter' and +// The second and third overload use the specified 'display_reporter' and // 'file_reporter' respectively. 'file_reporter' will write to the file // specified // by '--benchmark_output'. If '--benchmark_output' is not given the @@ -263,16 +276,13 @@ bool ReportUnrecognizedArguments(int argc, char** argv); // // RETURNS: The number of matching benchmarks. size_t RunSpecifiedBenchmarks(); -size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter); -size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter, +size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter); +size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter); -// If this routine is called, peak memory allocation past this point in the -// benchmark is reported at the end of the benchmark report line. (It is -// computed by running the benchmark once with a single iteration and a memory -// tracer.) -// TODO(dominic) -// void MemoryUsage(); +// Register a MemoryManager instance that will be used to collect and report +// allocation measurements for benchmark runs. +void RegisterMemoryManager(MemoryManager* memory_manager); namespace internal { class Benchmark; @@ -363,11 +373,20 @@ class Counter { kAvgIterationsRate = kIsRate | kAvgIterations }; + enum OneK { + // 1'000 items per 1k + kIs1000 = 1000, + // 1'024 items per 1k + kIs1024 = 1024 + }; + double value; Flags flags; + OneK oneK; BENCHMARK_ALWAYS_INLINE - Counter(double v = 0., Flags f = kDefaults) : value(v), flags(f) {} + Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000) + : value(v), flags(f), oneK(k) {} BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; } BENCHMARK_ALWAYS_INLINE operator double&() { return value; } @@ -406,22 +425,35 @@ struct Statistics { std::string name_; StatisticsFunc* compute_; - Statistics(std::string name, StatisticsFunc* compute) + Statistics(const std::string& name, StatisticsFunc* compute) : name_(name), compute_(compute) {} }; namespace internal { +struct BenchmarkInstance; class ThreadTimer; class ThreadManager; -enum ReportMode +enum AggregationReportMode #if defined(BENCHMARK_HAS_CXX11) : unsigned #else #endif -{ RM_Unspecified, // The mode has not been manually specified - RM_Default, // The mode is user-specified as default. - RM_ReportAggregatesOnly }; +{ + // The mode has not been manually specified + ARM_Unspecified = 0, + // The mode is user-specified. + // This may or may not be set when the following bit-flags are set. + ARM_Default = 1U << 0U, + // File reporter should only output aggregates. + ARM_FileReportAggregatesOnly = 1U << 1U, + // Display reporter should only output aggregates + ARM_DisplayReportAggregatesOnly = 1U << 2U, + // Both reporters should only display aggregates. + ARM_ReportAggregatesOnly = + ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly +}; + } // namespace internal // State is passed to a running Benchmark and contains state for the @@ -517,16 +549,21 @@ class State { // Set the number of bytes processed by the current benchmark // execution. This routine is typically called once at the end of a - // throughput oriented benchmark. If this routine is called with a - // value > 0, the report is printed in MB/sec instead of nanoseconds - // per iteration. + // throughput oriented benchmark. // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetBytesProcessed(int64_t bytes) { bytes_processed_ = bytes; } + void SetBytesProcessed(int64_t bytes) { + counters["bytes_per_second"] = + Counter(static_cast<double>(bytes), Counter::kIsRate, Counter::kIs1024); + } BENCHMARK_ALWAYS_INLINE - int64_t bytes_processed() const { return bytes_processed_; } + int64_t bytes_processed() const { + if (counters.find("bytes_per_second") != counters.end()) + return static_cast<int64_t>(counters.at("bytes_per_second")); + return 0; + } // If this routine is called with complexity_n > 0 and complexity report is // requested for the @@ -546,10 +583,17 @@ class State { // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetItemsProcessed(int64_t items) { items_processed_ = items; } + void SetItemsProcessed(int64_t items) { + counters["items_per_second"] = + Counter(static_cast<double>(items), benchmark::Counter::kIsRate); + } BENCHMARK_ALWAYS_INLINE - int64_t items_processed() const { return items_processed_; } + int64_t items_processed() const { + if (counters.find("items_per_second") != counters.end()) + return static_cast<int64_t>(counters.at("items_per_second")); + return 0; + } // If this routine is called, the specified label is printed at the // end of the benchmark report line for the currently executing @@ -612,9 +656,6 @@ class State { private: // items we don't need on the first cache line std::vector<int64_t> range_; - int64_t bytes_processed_; - int64_t items_processed_; - int64_t complexity_n_; public: @@ -625,12 +666,11 @@ class State { // Number of threads concurrently executing the benchmark. const int threads; - // TODO(EricWF) make me private + private: State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i, int n_threads, internal::ThreadTimer* timer, internal::ThreadManager* manager); - private: void StartKeepRunning(); // Implementation of KeepRunning() and KeepRunningBatch(). // is_batch must be true unless n is 1. @@ -638,7 +678,8 @@ class State { void FinishKeepRunning(); internal::ThreadTimer* timer_; internal::ThreadManager* manager_; - BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State); + + friend struct internal::BenchmarkInstance; }; inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() { @@ -827,8 +868,12 @@ class Benchmark { // Specify if each repetition of the benchmark should be reported separately // or if only the final statistics should be reported. If the benchmark // is not repeated then the single result is always reported. + // Applies to *ALL* reporters (display and file). Benchmark* ReportAggregatesOnly(bool value = true); + // Same as ReportAggregatesOnly(), but applies to display reporter only. + Benchmark* DisplayAggregatesOnly(bool value = true); + // If a particular benchmark is I/O bound, runs multiple threads internally or // if for some reason CPU timings are not representative, call this method. If // called, the elapsed time will be used to control how many iterations are @@ -888,9 +933,6 @@ class Benchmark { virtual void Run(State& state) = 0; - // Used inside the benchmark implementation - struct Instance; - protected: explicit Benchmark(const char* name); Benchmark(Benchmark const&); @@ -902,7 +944,7 @@ class Benchmark { friend class BenchmarkFamilies; std::string name_; - ReportMode report_mode_; + AggregationReportMode aggregation_report_mode_; std::vector<std::string> arg_names_; // Args for all benchmark runs std::vector<std::vector<int64_t> > args_; // Args for all benchmark runs TimeUnit time_unit_; @@ -1242,6 +1284,7 @@ struct CPUInfo { double cycles_per_second; std::vector<CacheInfo> caches; bool scaling_enabled; + std::vector<double> load_avg; static const CPUInfo& Get(); @@ -1250,6 +1293,15 @@ struct CPUInfo { BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo); }; +//Adding Struct for System Information +struct SystemInfo { + std::string name; + static const SystemInfo& Get(); + private: + SystemInfo(); + BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo); +}; + // Interface for custom benchmark result printers. // By default, benchmark reports are printed to stdout. However an application // can control the destination of the reports by calling @@ -1259,6 +1311,7 @@ class BenchmarkReporter { public: struct Context { CPUInfo const& cpu_info; + SystemInfo const& sys_info; // The number of chars in the longest benchmark name. size_t name_field_width; static const char* executable_name; @@ -1266,23 +1319,30 @@ class BenchmarkReporter { }; struct Run { + enum RunType { RT_Iteration, RT_Aggregate }; + Run() - : error_occurred(false), + : run_type(RT_Iteration), + error_occurred(false), iterations(1), time_unit(kNanosecond), real_accumulated_time(0), cpu_accumulated_time(0), - bytes_per_second(0), - items_per_second(0), max_heapbytes_used(0), complexity(oNone), complexity_lambda(), complexity_n(0), report_big_o(false), report_rms(false), - counters() {} - - std::string benchmark_name; + counters(), + has_memory_result(false), + allocs_per_iter(0.0), + max_bytes_used(0) {} + + std::string benchmark_name() const; + std::string run_name; + RunType run_type; // is this a measurement, or an aggregate? + std::string aggregate_name; std::string report_label; // Empty if not set by benchmark. bool error_occurred; std::string error_message; @@ -1304,10 +1364,6 @@ class BenchmarkReporter { // accumulated time. double GetAdjustedCPUTime() const; - // Zero if not set by benchmark. - double bytes_per_second; - double items_per_second; - // This is set to 0.0 if memory tracing is not enabled. double max_heapbytes_used; @@ -1324,6 +1380,11 @@ class BenchmarkReporter { bool report_rms; UserCounters counters; + + // Memory metrics. + bool has_memory_result; + double allocs_per_iter; + int64_t max_bytes_used; }; // Construct a BenchmarkReporter with the output stream set to 'std::cout' @@ -1438,6 +1499,29 @@ class BENCHMARK_DEPRECATED_MSG("The CSV Reporter will be removed in a future rel std::set<std::string> user_counter_names_; }; +// If a MemoryManager is registered, it can be used to collect and report +// allocation metrics for a run of the benchmark. +class MemoryManager { + public: + struct Result { + Result() : num_allocs(0), max_bytes_used(0) {} + + // The number of allocations made in total between Start and Stop. + int64_t num_allocs; + + // The peak memory use between Start and Stop. + int64_t max_bytes_used; + }; + + virtual ~MemoryManager() {} + + // Implement this to start recording allocation information. + virtual void Start() = 0; + + // Implement this to stop recording and fill out the given Result structure. + virtual void Stop(Result* result) = 0; +}; + inline const char* GetTimeUnitString(TimeUnit unit) { switch (unit) { case kMillisecond: @@ -1445,9 +1529,9 @@ inline const char* GetTimeUnitString(TimeUnit unit) { case kMicrosecond: return "us"; case kNanosecond: - default: return "ns"; } + BENCHMARK_UNREACHABLE(); } inline double GetTimeUnitMultiplier(TimeUnit unit) { @@ -1457,9 +1541,9 @@ inline double GetTimeUnitMultiplier(TimeUnit unit) { case kMicrosecond: return 1e6; case kNanosecond: - default: return 1e9; } + BENCHMARK_UNREACHABLE(); } } // namespace benchmark diff --git a/lib/libcxx/utils/google-benchmark/src/benchmark.cc b/lib/libcxx/utils/google-benchmark/src/benchmark.cc index b14bc629143..aab07500af4 100644 --- a/lib/libcxx/utils/google-benchmark/src/benchmark.cc +++ b/lib/libcxx/utils/google-benchmark/src/benchmark.cc @@ -14,6 +14,7 @@ #include "benchmark/benchmark.h" #include "benchmark_api_internal.h" +#include "benchmark_runner.h" #include "internal_macros.h" #ifndef BENCHMARK_OS_WINDOWS @@ -34,6 +35,7 @@ #include <memory> #include <string> #include <thread> +#include <utility> #include "check.h" #include "colorprint.h" @@ -55,9 +57,9 @@ DEFINE_bool(benchmark_list_tests, false, DEFINE_string(benchmark_filter, ".", "A regular expression that specifies the set of benchmarks " - "to execute. If this flag is empty, no benchmarks are run. " - "If this flag is the string \"all\", all benchmarks linked " - "into the process are run."); + "to execute. If this flag is empty, or if this flag is the " + "string \"all\", all benchmarks linked into the binary are " + "run."); DEFINE_double(benchmark_min_time, 0.5, "Minimum number of seconds we should run benchmark before " @@ -72,10 +74,19 @@ DEFINE_int32(benchmark_repetitions, 1, "The number of runs of each benchmark. If greater than 1, the " "mean and standard deviation of the runs will be reported."); -DEFINE_bool(benchmark_report_aggregates_only, false, - "Report the result of each benchmark repetitions. When 'true' is " - "specified only the mean, standard deviation, and other statistics " - "are reported for repeated benchmarks."); +DEFINE_bool( + benchmark_report_aggregates_only, false, + "Report the result of each benchmark repetitions. When 'true' is specified " + "only the mean, standard deviation, and other statistics are reported for " + "repeated benchmarks. Affects all reporters."); + +DEFINE_bool( + benchmark_display_aggregates_only, false, + "Display the result of each benchmark repetitions. When 'true' is " + "specified only the mean, standard deviation, and other statistics are " + "displayed for repeated benchmarks. Unlike " + "benchmark_report_aggregates_only, only affects the display reporter, but " + "*NOT* file reporter, which will still contain all the output."); DEFINE_string(benchmark_format, "console", "The format to use for console output. Valid values are " @@ -103,193 +114,11 @@ DEFINE_int32(v, 0, "The level of verbose logging to output"); namespace benchmark { -namespace { -static const size_t kMaxIterations = 1000000000; -} // end namespace - namespace internal { +// FIXME: wouldn't LTO mess this up? void UseCharPointer(char const volatile*) {} -namespace { - -BenchmarkReporter::Run CreateRunReport( - const benchmark::internal::Benchmark::Instance& b, - const internal::ThreadManager::Result& results, double seconds) { - // Create report about this benchmark run. - BenchmarkReporter::Run report; - - report.benchmark_name = b.name; - report.error_occurred = results.has_error_; - report.error_message = results.error_message_; - report.report_label = results.report_label_; - // This is the total iterations across all threads. - report.iterations = results.iterations; - report.time_unit = b.time_unit; - - if (!report.error_occurred) { - double bytes_per_second = 0; - if (results.bytes_processed > 0 && seconds > 0.0) { - bytes_per_second = (results.bytes_processed / seconds); - } - double items_per_second = 0; - if (results.items_processed > 0 && seconds > 0.0) { - items_per_second = (results.items_processed / seconds); - } - - if (b.use_manual_time) { - report.real_accumulated_time = results.manual_time_used; - } else { - report.real_accumulated_time = results.real_time_used; - } - report.cpu_accumulated_time = results.cpu_time_used; - report.bytes_per_second = bytes_per_second; - report.items_per_second = items_per_second; - report.complexity_n = results.complexity_n; - report.complexity = b.complexity; - report.complexity_lambda = b.complexity_lambda; - report.statistics = b.statistics; - report.counters = results.counters; - internal::Finish(&report.counters, results.iterations, seconds, b.threads); - } - return report; -} - -// Execute one thread of benchmark b for the specified number of iterations. -// Adds the stats collected for the thread into *total. -void RunInThread(const benchmark::internal::Benchmark::Instance* b, - size_t iters, int thread_id, - internal::ThreadManager* manager) { - internal::ThreadTimer timer; - State st(iters, b->arg, thread_id, b->threads, &timer, manager); - b->benchmark->Run(st); - CHECK(st.iterations() >= st.max_iterations) - << "Benchmark returned before State::KeepRunning() returned false!"; - { - MutexLock l(manager->GetBenchmarkMutex()); - internal::ThreadManager::Result& results = manager->results; - results.iterations += st.iterations(); - results.cpu_time_used += timer.cpu_time_used(); - results.real_time_used += timer.real_time_used(); - results.manual_time_used += timer.manual_time_used(); - results.bytes_processed += st.bytes_processed(); - results.items_processed += st.items_processed(); - results.complexity_n += st.complexity_length_n(); - internal::Increment(&results.counters, st.counters); - } - manager->NotifyThreadComplete(); -} - -std::vector<BenchmarkReporter::Run> RunBenchmark( - const benchmark::internal::Benchmark::Instance& b, - std::vector<BenchmarkReporter::Run>* complexity_reports) { - std::vector<BenchmarkReporter::Run> reports; // return value - - const bool has_explicit_iteration_count = b.iterations != 0; - size_t iters = has_explicit_iteration_count ? b.iterations : 1; - std::unique_ptr<internal::ThreadManager> manager; - std::vector<std::thread> pool(b.threads - 1); - const int repeats = - b.repetitions != 0 ? b.repetitions : FLAGS_benchmark_repetitions; - const bool report_aggregates_only = - repeats != 1 && - (b.report_mode == internal::RM_Unspecified - ? FLAGS_benchmark_report_aggregates_only - : b.report_mode == internal::RM_ReportAggregatesOnly); - for (int repetition_num = 0; repetition_num < repeats; repetition_num++) { - for (;;) { - // Try benchmark - VLOG(2) << "Running " << b.name << " for " << iters << "\n"; - - manager.reset(new internal::ThreadManager(b.threads)); - for (std::size_t ti = 0; ti < pool.size(); ++ti) { - pool[ti] = std::thread(&RunInThread, &b, iters, - static_cast<int>(ti + 1), manager.get()); - } - RunInThread(&b, iters, 0, manager.get()); - manager->WaitForAllThreads(); - for (std::thread& thread : pool) thread.join(); - internal::ThreadManager::Result results; - { - MutexLock l(manager->GetBenchmarkMutex()); - results = manager->results; - } - manager.reset(); - // Adjust real/manual time stats since they were reported per thread. - results.real_time_used /= b.threads; - results.manual_time_used /= b.threads; - - VLOG(2) << "Ran in " << results.cpu_time_used << "/" - << results.real_time_used << "\n"; - - // Base decisions off of real time if requested by this benchmark. - double seconds = results.cpu_time_used; - if (b.use_manual_time) { - seconds = results.manual_time_used; - } else if (b.use_real_time) { - seconds = results.real_time_used; - } - - const double min_time = - !IsZero(b.min_time) ? b.min_time : FLAGS_benchmark_min_time; - - // clang-format off - // turn off clang-format since it mangles prettiness here - // Determine if this run should be reported; Either it has - // run for a sufficient amount of time or because an error was reported. - const bool should_report = repetition_num > 0 - || has_explicit_iteration_count // An exact iteration count was requested - || results.has_error_ - || iters >= kMaxIterations // No chance to try again, we hit the limit. - || seconds >= min_time // the elapsed time is large enough - // CPU time is specified but the elapsed real time greatly exceeds the - // minimum time. Note that user provided timers are except from this - // sanity check. - || ((results.real_time_used >= 5 * min_time) && !b.use_manual_time); - // clang-format on - - if (should_report) { - BenchmarkReporter::Run report = CreateRunReport(b, results, seconds); - if (!report.error_occurred && b.complexity != oNone) - complexity_reports->push_back(report); - reports.push_back(report); - break; - } - - // See how much iterations should be increased by - // Note: Avoid division by zero with max(seconds, 1ns). - double multiplier = min_time * 1.4 / std::max(seconds, 1e-9); - // If our last run was at least 10% of FLAGS_benchmark_min_time then we - // use the multiplier directly. Otherwise we use at most 10 times - // expansion. - // NOTE: When the last run was at least 10% of the min time the max - // expansion should be 14x. - bool is_significant = (seconds / min_time) > 0.1; - multiplier = is_significant ? multiplier : std::min(10.0, multiplier); - if (multiplier <= 1.0) multiplier = 2.0; - double next_iters = std::max(multiplier * iters, iters + 1.0); - if (next_iters > kMaxIterations) { - next_iters = kMaxIterations; - } - VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n"; - iters = static_cast<int>(next_iters + 0.5); - } - } - // Calculate additional statistics - auto stat_reports = ComputeStats(reports); - if ((b.complexity != oNone) && b.last_benchmark_instance) { - auto additional_run_stats = ComputeBigO(*complexity_reports); - stat_reports.insert(stat_reports.end(), additional_run_stats.begin(), - additional_run_stats.end()); - complexity_reports->clear(); - } - - if (report_aggregates_only) reports.clear(); - reports.insert(reports.end(), stat_reports.begin(), stat_reports.end()); - return reports; -} - -} // namespace } // namespace internal State::State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i, @@ -302,8 +131,6 @@ State::State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i, finished_(false), error_occurred_(false), range_(ranges), - bytes_processed_(0), - items_processed_(0), complexity_n_(0), counters(), thread_index(thread_i), @@ -394,25 +221,25 @@ void State::FinishKeepRunning() { namespace internal { namespace { -void RunBenchmarks(const std::vector<Benchmark::Instance>& benchmarks, - BenchmarkReporter* console_reporter, +void RunBenchmarks(const std::vector<BenchmarkInstance>& benchmarks, + BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter) { // Note the file_reporter can be null. - CHECK(console_reporter != nullptr); + CHECK(display_reporter != nullptr); // Determine the width of the name field using a minimum width of 10. - bool has_repetitions = FLAGS_benchmark_repetitions > 1; + bool might_have_aggregates = FLAGS_benchmark_repetitions > 1; size_t name_field_width = 10; size_t stat_field_width = 0; - for (const Benchmark::Instance& benchmark : benchmarks) { + for (const BenchmarkInstance& benchmark : benchmarks) { name_field_width = std::max<size_t>(name_field_width, benchmark.name.size()); - has_repetitions |= benchmark.repetitions > 1; + might_have_aggregates |= benchmark.repetitions > 1; for (const auto& Stat : *benchmark.statistics) stat_field_width = std::max<size_t>(stat_field_width, Stat.name_.size()); } - if (has_repetitions) name_field_width += 1 + stat_field_width; + if (might_have_aggregates) name_field_width += 1 + stat_field_width; // Print header here BenchmarkReporter::Context context; @@ -429,22 +256,36 @@ void RunBenchmarks(const std::vector<Benchmark::Instance>& benchmarks, std::flush(reporter->GetErrorStream()); }; - if (console_reporter->ReportContext(context) && + if (display_reporter->ReportContext(context) && (!file_reporter || file_reporter->ReportContext(context))) { - flushStreams(console_reporter); + flushStreams(display_reporter); flushStreams(file_reporter); + for (const auto& benchmark : benchmarks) { - std::vector<BenchmarkReporter::Run> reports = - RunBenchmark(benchmark, &complexity_reports); - console_reporter->ReportRuns(reports); - if (file_reporter) file_reporter->ReportRuns(reports); - flushStreams(console_reporter); + RunResults run_results = RunBenchmark(benchmark, &complexity_reports); + + auto report = [&run_results](BenchmarkReporter* reporter, + bool report_aggregates_only) { + assert(reporter); + // If there are no aggregates, do output non-aggregates. + report_aggregates_only &= !run_results.aggregates_only.empty(); + if (!report_aggregates_only) + reporter->ReportRuns(run_results.non_aggregates); + if (!run_results.aggregates_only.empty()) + reporter->ReportRuns(run_results.aggregates_only); + }; + + report(display_reporter, run_results.display_report_aggregates_only); + if (file_reporter) + report(file_reporter, run_results.file_report_aggregates_only); + + flushStreams(display_reporter); flushStreams(file_reporter); } } - console_reporter->Finalize(); + display_reporter->Finalize(); if (file_reporter) file_reporter->Finalize(); - flushStreams(console_reporter); + flushStreams(display_reporter); flushStreams(file_reporter); } @@ -471,15 +312,20 @@ bool IsZero(double n) { ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) { int output_opts = ConsoleReporter::OO_Defaults; - if ((FLAGS_benchmark_color == "auto" && IsColorTerminal()) || - IsTruthyFlagValue(FLAGS_benchmark_color)) { + auto is_benchmark_color = [force_no_color] () -> bool { + if (force_no_color) { + return false; + } + if (FLAGS_benchmark_color == "auto") { + return IsColorTerminal(); + } + return IsTruthyFlagValue(FLAGS_benchmark_color); + }; + if (is_benchmark_color()) { output_opts |= ConsoleReporter::OO_Color; } else { output_opts &= ~ConsoleReporter::OO_Color; } - if (force_no_color) { - output_opts &= ~ConsoleReporter::OO_Color; - } if (FLAGS_benchmark_counters_tabular) { output_opts |= ConsoleReporter::OO_Tabular; } else { @@ -494,11 +340,11 @@ size_t RunSpecifiedBenchmarks() { return RunSpecifiedBenchmarks(nullptr, nullptr); } -size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter) { - return RunSpecifiedBenchmarks(console_reporter, nullptr); +size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter) { + return RunSpecifiedBenchmarks(display_reporter, nullptr); } -size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter, +size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter) { std::string spec = FLAGS_benchmark_filter; if (spec.empty() || spec == "all") @@ -506,15 +352,15 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter, // Setup the reporters std::ofstream output_file; - std::unique_ptr<BenchmarkReporter> default_console_reporter; + std::unique_ptr<BenchmarkReporter> default_display_reporter; std::unique_ptr<BenchmarkReporter> default_file_reporter; - if (!console_reporter) { - default_console_reporter = internal::CreateReporter( + if (!display_reporter) { + default_display_reporter = internal::CreateReporter( FLAGS_benchmark_format, internal::GetOutputOptions()); - console_reporter = default_console_reporter.get(); + display_reporter = default_display_reporter.get(); } - auto& Out = console_reporter->GetOutputStream(); - auto& Err = console_reporter->GetErrorStream(); + auto& Out = display_reporter->GetOutputStream(); + auto& Err = display_reporter->GetErrorStream(); std::string const& fname = FLAGS_benchmark_out; if (fname.empty() && file_reporter) { @@ -538,7 +384,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter, file_reporter->SetErrorStream(&output_file); } - std::vector<internal::Benchmark::Instance> benchmarks; + std::vector<internal::BenchmarkInstance> benchmarks; if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) return 0; if (benchmarks.empty()) { @@ -549,12 +395,16 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter, if (FLAGS_benchmark_list_tests) { for (auto const& benchmark : benchmarks) Out << benchmark.name << "\n"; } else { - internal::RunBenchmarks(benchmarks, console_reporter, file_reporter); + internal::RunBenchmarks(benchmarks, display_reporter, file_reporter); } return benchmarks.size(); } +void RegisterMemoryManager(MemoryManager* manager) { + internal::memory_manager = manager; +} + namespace internal { void PrintUsageAndExit() { @@ -564,7 +414,8 @@ void PrintUsageAndExit() { " [--benchmark_filter=<regex>]\n" " [--benchmark_min_time=<min_time>]\n" " [--benchmark_repetitions=<num_repetitions>]\n" - " [--benchmark_report_aggregates_only={true|false}\n" + " [--benchmark_report_aggregates_only={true|false}]\n" + " [--benchmark_display_aggregates_only={true|false}]\n" " [--benchmark_format=<console|json|csv>]\n" " [--benchmark_out=<filename>]\n" " [--benchmark_out_format=<json|console|csv>]\n" @@ -588,6 +439,8 @@ void ParseCommandLineFlags(int* argc, char** argv) { &FLAGS_benchmark_repetitions) || ParseBoolFlag(argv[i], "benchmark_report_aggregates_only", &FLAGS_benchmark_report_aggregates_only) || + ParseBoolFlag(argv[i], "benchmark_display_aggregates_only", + &FLAGS_benchmark_display_aggregates_only) || ParseStringFlag(argv[i], "benchmark_format", &FLAGS_benchmark_format) || ParseStringFlag(argv[i], "benchmark_out", &FLAGS_benchmark_out) || ParseStringFlag(argv[i], "benchmark_out_format", diff --git a/lib/libcxx/utils/google-benchmark/src/benchmark_api_internal.cc b/lib/libcxx/utils/google-benchmark/src/benchmark_api_internal.cc new file mode 100644 index 00000000000..8d3108363b8 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/src/benchmark_api_internal.cc @@ -0,0 +1,15 @@ +#include "benchmark_api_internal.h" + +namespace benchmark { +namespace internal { + +State BenchmarkInstance::Run( + size_t iters, int thread_id, internal::ThreadTimer* timer, + internal::ThreadManager* manager) const { + State st(iters, arg, thread_id, threads, timer, manager); + benchmark->Run(st); + return st; +} + +} // internal +} // benchmark diff --git a/lib/libcxx/utils/google-benchmark/src/benchmark_api_internal.h b/lib/libcxx/utils/google-benchmark/src/benchmark_api_internal.h index dd7a3ffe8cb..0524a85c01d 100644 --- a/lib/libcxx/utils/google-benchmark/src/benchmark_api_internal.h +++ b/lib/libcxx/utils/google-benchmark/src/benchmark_api_internal.h @@ -2,10 +2,12 @@ #define BENCHMARK_API_INTERNAL_H #include "benchmark/benchmark.h" +#include "commandlineflags.h" #include <cmath> #include <iosfwd> #include <limits> +#include <memory> #include <string> #include <vector> @@ -13,10 +15,10 @@ namespace benchmark { namespace internal { // Information kept per benchmark we may want to run -struct Benchmark::Instance { +struct BenchmarkInstance { std::string name; Benchmark* benchmark; - ReportMode report_mode; + AggregationReportMode aggregation_report_mode; std::vector<int64_t> arg; TimeUnit time_unit; int range_multiplier; @@ -31,10 +33,13 @@ struct Benchmark::Instance { double min_time; size_t iterations; int threads; // Number of concurrent threads to us + + State Run(size_t iters, int thread_id, internal::ThreadTimer* timer, + internal::ThreadManager* manager) const; }; bool FindBenchmarksInternal(const std::string& re, - std::vector<Benchmark::Instance>* benchmarks, + std::vector<BenchmarkInstance>* benchmarks, std::ostream* Err); bool IsZero(double n); diff --git a/lib/libcxx/utils/google-benchmark/src/benchmark_register.cc b/lib/libcxx/utils/google-benchmark/src/benchmark_register.cc index 26a89721c78..f17f5b223ce 100644 --- a/lib/libcxx/utils/google-benchmark/src/benchmark_register.cc +++ b/lib/libcxx/utils/google-benchmark/src/benchmark_register.cc @@ -78,7 +78,7 @@ class BenchmarkFamilies { // Extract the list of benchmark instances that match the specified // regular expression. bool FindBenchmarks(std::string re, - std::vector<Benchmark::Instance>* benchmarks, + std::vector<BenchmarkInstance>* benchmarks, std::ostream* Err); private: @@ -107,7 +107,7 @@ void BenchmarkFamilies::ClearBenchmarks() { } bool BenchmarkFamilies::FindBenchmarks( - std::string spec, std::vector<Benchmark::Instance>* benchmarks, + std::string spec, std::vector<BenchmarkInstance>* benchmarks, std::ostream* ErrStream) { CHECK(ErrStream); auto& Err = *ErrStream; @@ -152,10 +152,10 @@ bool BenchmarkFamilies::FindBenchmarks( for (auto const& args : family->args_) { for (int num_threads : *thread_counts) { - Benchmark::Instance instance; + BenchmarkInstance instance; instance.name = family->name_; instance.benchmark = family.get(); - instance.report_mode = family->report_mode_; + instance.aggregation_report_mode = family->aggregation_report_mode_; instance.arg = args; instance.time_unit = family->time_unit_; instance.range_multiplier = family->range_multiplier_; @@ -182,14 +182,19 @@ bool BenchmarkFamilies::FindBenchmarks( } } - instance.name += StrFormat("%d", arg); + // we know that the args are always non-negative (see 'AddRange()'), + // thus print as 'unsigned'. BUT, do a cast due to the 32-bit builds. + instance.name += StrFormat("%lu", static_cast<unsigned long>(arg)); ++arg_i; } if (!IsZero(family->min_time_)) instance.name += StrFormat("/min_time:%0.3f", family->min_time_); - if (family->iterations_ != 0) - instance.name += StrFormat("/iterations:%d", family->iterations_); + if (family->iterations_ != 0) { + instance.name += + StrFormat("/iterations:%lu", + static_cast<unsigned long>(family->iterations_)); + } if (family->repetitions_ != 0) instance.name += StrFormat("/repeats:%d", family->repetitions_); @@ -225,7 +230,7 @@ Benchmark* RegisterBenchmarkInternal(Benchmark* bench) { // FIXME: This function is a hack so that benchmark.cc can access // `BenchmarkFamilies` bool FindBenchmarksInternal(const std::string& re, - std::vector<Benchmark::Instance>* benchmarks, + std::vector<BenchmarkInstance>* benchmarks, std::ostream* Err) { return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err); } @@ -236,7 +241,7 @@ bool FindBenchmarksInternal(const std::string& re, Benchmark::Benchmark(const char* name) : name_(name), - report_mode_(RM_Unspecified), + aggregation_report_mode_(ARM_Unspecified), time_unit_(kNanosecond), range_multiplier_(kRangeMultiplier), min_time_(0), @@ -369,7 +374,23 @@ Benchmark* Benchmark::Repetitions(int n) { } Benchmark* Benchmark::ReportAggregatesOnly(bool value) { - report_mode_ = value ? RM_ReportAggregatesOnly : RM_Default; + aggregation_report_mode_ = value ? ARM_ReportAggregatesOnly : ARM_Default; + return this; +} + +Benchmark* Benchmark::DisplayAggregatesOnly(bool value) { + // If we were called, the report mode is no longer 'unspecified', in any case. + aggregation_report_mode_ = static_cast<AggregationReportMode>( + aggregation_report_mode_ | ARM_Default); + + if (value) { + aggregation_report_mode_ = static_cast<AggregationReportMode>( + aggregation_report_mode_ | ARM_DisplayReportAggregatesOnly); + } else { + aggregation_report_mode_ = static_cast<AggregationReportMode>( + aggregation_report_mode_ & ~ARM_DisplayReportAggregatesOnly); + } + return this; } diff --git a/lib/libcxx/utils/google-benchmark/src/benchmark_runner.cc b/lib/libcxx/utils/google-benchmark/src/benchmark_runner.cc new file mode 100644 index 00000000000..38faeec8e3e --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/src/benchmark_runner.cc @@ -0,0 +1,350 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark_runner.h" +#include "benchmark/benchmark.h" +#include "benchmark_api_internal.h" +#include "internal_macros.h" + +#ifndef BENCHMARK_OS_WINDOWS +#ifndef BENCHMARK_OS_FUCHSIA +#include <sys/resource.h> +#endif +#include <sys/time.h> +#include <unistd.h> +#endif + +#include <algorithm> +#include <atomic> +#include <condition_variable> +#include <cstdio> +#include <cstdlib> +#include <fstream> +#include <iostream> +#include <memory> +#include <string> +#include <thread> +#include <utility> + +#include "check.h" +#include "colorprint.h" +#include "commandlineflags.h" +#include "complexity.h" +#include "counter.h" +#include "internal_macros.h" +#include "log.h" +#include "mutex.h" +#include "re.h" +#include "statistics.h" +#include "string_util.h" +#include "thread_manager.h" +#include "thread_timer.h" + +namespace benchmark { + +namespace internal { + +MemoryManager* memory_manager = nullptr; + +namespace { + +static const size_t kMaxIterations = 1000000000; + +BenchmarkReporter::Run CreateRunReport( + const benchmark::internal::BenchmarkInstance& b, + const internal::ThreadManager::Result& results, size_t memory_iterations, + const MemoryManager::Result& memory_result, double seconds) { + // Create report about this benchmark run. + BenchmarkReporter::Run report; + + report.run_name = b.name; + report.error_occurred = results.has_error_; + report.error_message = results.error_message_; + report.report_label = results.report_label_; + // This is the total iterations across all threads. + report.iterations = results.iterations; + report.time_unit = b.time_unit; + + if (!report.error_occurred) { + if (b.use_manual_time) { + report.real_accumulated_time = results.manual_time_used; + } else { + report.real_accumulated_time = results.real_time_used; + } + report.cpu_accumulated_time = results.cpu_time_used; + report.complexity_n = results.complexity_n; + report.complexity = b.complexity; + report.complexity_lambda = b.complexity_lambda; + report.statistics = b.statistics; + report.counters = results.counters; + + if (memory_iterations > 0) { + report.has_memory_result = true; + report.allocs_per_iter = + memory_iterations ? static_cast<double>(memory_result.num_allocs) / + memory_iterations + : 0; + report.max_bytes_used = memory_result.max_bytes_used; + } + + internal::Finish(&report.counters, results.iterations, seconds, b.threads); + } + return report; +} + +// Execute one thread of benchmark b for the specified number of iterations. +// Adds the stats collected for the thread into *total. +void RunInThread(const BenchmarkInstance* b, size_t iters, int thread_id, + ThreadManager* manager) { + internal::ThreadTimer timer; + State st = b->Run(iters, thread_id, &timer, manager); + CHECK(st.iterations() >= st.max_iterations) + << "Benchmark returned before State::KeepRunning() returned false!"; + { + MutexLock l(manager->GetBenchmarkMutex()); + internal::ThreadManager::Result& results = manager->results; + results.iterations += st.iterations(); + results.cpu_time_used += timer.cpu_time_used(); + results.real_time_used += timer.real_time_used(); + results.manual_time_used += timer.manual_time_used(); + results.complexity_n += st.complexity_length_n(); + internal::Increment(&results.counters, st.counters); + } + manager->NotifyThreadComplete(); +} + +class BenchmarkRunner { + public: + BenchmarkRunner(const benchmark::internal::BenchmarkInstance& b_, + std::vector<BenchmarkReporter::Run>* complexity_reports_) + : b(b_), + complexity_reports(*complexity_reports_), + min_time(!IsZero(b.min_time) ? b.min_time : FLAGS_benchmark_min_time), + repeats(b.repetitions != 0 ? b.repetitions + : FLAGS_benchmark_repetitions), + has_explicit_iteration_count(b.iterations != 0), + pool(b.threads - 1), + iters(has_explicit_iteration_count ? b.iterations : 1) { + run_results.display_report_aggregates_only = + (FLAGS_benchmark_report_aggregates_only || + FLAGS_benchmark_display_aggregates_only); + run_results.file_report_aggregates_only = + FLAGS_benchmark_report_aggregates_only; + if (b.aggregation_report_mode != internal::ARM_Unspecified) { + run_results.display_report_aggregates_only = + (b.aggregation_report_mode & + internal::ARM_DisplayReportAggregatesOnly); + run_results.file_report_aggregates_only = + (b.aggregation_report_mode & internal::ARM_FileReportAggregatesOnly); + } + + for (int repetition_num = 0; repetition_num < repeats; repetition_num++) { + const bool is_the_first_repetition = repetition_num == 0; + DoOneRepetition(is_the_first_repetition); + } + + // Calculate additional statistics + run_results.aggregates_only = ComputeStats(run_results.non_aggregates); + + // Maybe calculate complexity report + if ((b.complexity != oNone) && b.last_benchmark_instance) { + auto additional_run_stats = ComputeBigO(complexity_reports); + run_results.aggregates_only.insert(run_results.aggregates_only.end(), + additional_run_stats.begin(), + additional_run_stats.end()); + complexity_reports.clear(); + } + } + + RunResults&& get_results() { return std::move(run_results); } + + private: + RunResults run_results; + + const benchmark::internal::BenchmarkInstance& b; + std::vector<BenchmarkReporter::Run>& complexity_reports; + + const double min_time; + const int repeats; + const bool has_explicit_iteration_count; + + std::vector<std::thread> pool; + + size_t iters; // preserved between repetitions! + // So only the first repetition has to find/calculate it, + // the other repetitions will just use that precomputed iteration count. + + struct IterationResults { + internal::ThreadManager::Result results; + size_t iters; + double seconds; + }; + IterationResults DoNIterations() { + VLOG(2) << "Running " << b.name << " for " << iters << "\n"; + + std::unique_ptr<internal::ThreadManager> manager; + manager.reset(new internal::ThreadManager(b.threads)); + + // Run all but one thread in separate threads + for (std::size_t ti = 0; ti < pool.size(); ++ti) { + pool[ti] = std::thread(&RunInThread, &b, iters, static_cast<int>(ti + 1), + manager.get()); + } + // And run one thread here directly. + // (If we were asked to run just one thread, we don't create new threads.) + // Yes, we need to do this here *after* we start the separate threads. + RunInThread(&b, iters, 0, manager.get()); + + // The main thread has finished. Now let's wait for the other threads. + manager->WaitForAllThreads(); + for (std::thread& thread : pool) thread.join(); + + IterationResults i; + // Acquire the measurements/counters from the manager, UNDER THE LOCK! + { + MutexLock l(manager->GetBenchmarkMutex()); + i.results = manager->results; + } + + // And get rid of the manager. + manager.reset(); + + // Adjust real/manual time stats since they were reported per thread. + i.results.real_time_used /= b.threads; + i.results.manual_time_used /= b.threads; + + VLOG(2) << "Ran in " << i.results.cpu_time_used << "/" + << i.results.real_time_used << "\n"; + + // So for how long were we running? + i.iters = iters; + // Base decisions off of real time if requested by this benchmark. + i.seconds = i.results.cpu_time_used; + if (b.use_manual_time) { + i.seconds = i.results.manual_time_used; + } else if (b.use_real_time) { + i.seconds = i.results.real_time_used; + } + + return i; + } + + size_t PredictNumItersNeeded(const IterationResults& i) const { + // See how much iterations should be increased by. + // Note: Avoid division by zero with max(seconds, 1ns). + double multiplier = min_time * 1.4 / std::max(i.seconds, 1e-9); + // If our last run was at least 10% of FLAGS_benchmark_min_time then we + // use the multiplier directly. + // Otherwise we use at most 10 times expansion. + // NOTE: When the last run was at least 10% of the min time the max + // expansion should be 14x. + bool is_significant = (i.seconds / min_time) > 0.1; + multiplier = is_significant ? multiplier : std::min(10.0, multiplier); + if (multiplier <= 1.0) multiplier = 2.0; + + // So what seems to be the sufficiently-large iteration count? Round up. + const size_t max_next_iters = + 0.5 + std::max(multiplier * i.iters, i.iters + 1.0); + // But we do have *some* sanity limits though.. + const size_t next_iters = std::min(max_next_iters, kMaxIterations); + + VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n"; + return next_iters; // round up before conversion to integer. + } + + bool ShouldReportIterationResults(const IterationResults& i) const { + // Determine if this run should be reported; + // Either it has run for a sufficient amount of time + // or because an error was reported. + return i.results.has_error_ || + i.iters >= kMaxIterations || // Too many iterations already. + i.seconds >= min_time || // The elapsed time is large enough. + // CPU time is specified but the elapsed real time greatly exceeds + // the minimum time. + // Note that user provided timers are except from this sanity check. + ((i.results.real_time_used >= 5 * min_time) && !b.use_manual_time); + } + + void DoOneRepetition(bool is_the_first_repetition) { + IterationResults i; + + // We *may* be gradually increasing the length (iteration count) + // of the benchmark until we decide the results are significant. + // And once we do, we report those last results and exit. + // Please do note that the if there are repetitions, the iteration count + // is *only* calculated for the *first* repetition, and other repetitions + // simply use that precomputed iteration count. + for (;;) { + i = DoNIterations(); + + // Do we consider the results to be significant? + // If we are doing repetitions, and the first repetition was already done, + // it has calculated the correct iteration time, so we have run that very + // iteration count just now. No need to calculate anything. Just report. + // Else, the normal rules apply. + const bool results_are_significant = !is_the_first_repetition || + has_explicit_iteration_count || + ShouldReportIterationResults(i); + + if (results_are_significant) break; // Good, let's report them! + + // Nope, bad iteration. Let's re-estimate the hopefully-sufficient + // iteration count, and run the benchmark again... + + iters = PredictNumItersNeeded(i); + assert(iters > i.iters && + "if we did more iterations than we want to do the next time, " + "then we should have accepted the current iteration run."); + } + + // Oh, one last thing, we need to also produce the 'memory measurements'.. + MemoryManager::Result memory_result; + size_t memory_iterations = 0; + if (memory_manager != nullptr) { + // Only run a few iterations to reduce the impact of one-time + // allocations in benchmarks that are not properly managed. + memory_iterations = std::min<size_t>(16, iters); + memory_manager->Start(); + std::unique_ptr<internal::ThreadManager> manager; + manager.reset(new internal::ThreadManager(1)); + RunInThread(&b, memory_iterations, 0, manager.get()); + manager->WaitForAllThreads(); + manager.reset(); + + memory_manager->Stop(&memory_result); + } + + // Ok, now actualy report. + BenchmarkReporter::Run report = CreateRunReport( + b, i.results, memory_iterations, memory_result, i.seconds); + + if (!report.error_occurred && b.complexity != oNone) + complexity_reports.push_back(report); + + run_results.non_aggregates.push_back(report); + } +}; + +} // end namespace + +RunResults RunBenchmark( + const benchmark::internal::BenchmarkInstance& b, + std::vector<BenchmarkReporter::Run>* complexity_reports) { + internal::BenchmarkRunner r(b, complexity_reports); + return r.get_results(); +} + +} // end namespace internal + +} // end namespace benchmark diff --git a/lib/libcxx/utils/google-benchmark/src/benchmark_runner.h b/lib/libcxx/utils/google-benchmark/src/benchmark_runner.h new file mode 100644 index 00000000000..96e8282a11a --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/src/benchmark_runner.h @@ -0,0 +1,51 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BENCHMARK_RUNNER_H_ +#define BENCHMARK_RUNNER_H_ + +#include "benchmark_api_internal.h" +#include "internal_macros.h" + +DECLARE_double(benchmark_min_time); + +DECLARE_int32(benchmark_repetitions); + +DECLARE_bool(benchmark_report_aggregates_only); + +DECLARE_bool(benchmark_display_aggregates_only); + +namespace benchmark { + +namespace internal { + +extern MemoryManager* memory_manager; + +struct RunResults { + std::vector<BenchmarkReporter::Run> non_aggregates; + std::vector<BenchmarkReporter::Run> aggregates_only; + + bool display_report_aggregates_only = false; + bool file_report_aggregates_only = false; +}; + +RunResults RunBenchmark( + const benchmark::internal::BenchmarkInstance& b, + std::vector<BenchmarkReporter::Run>* complexity_reports); + +} // namespace internal + +} // end namespace benchmark + +#endif // BENCHMARK_RUNNER_H_ diff --git a/lib/libcxx/utils/google-benchmark/src/colorprint.cc b/lib/libcxx/utils/google-benchmark/src/colorprint.cc index 2dec4a8b28b..fff6a98818b 100644 --- a/lib/libcxx/utils/google-benchmark/src/colorprint.cc +++ b/lib/libcxx/utils/google-benchmark/src/colorprint.cc @@ -25,7 +25,7 @@ #include "internal_macros.h" #ifdef BENCHMARK_OS_WINDOWS -#include <Windows.h> +#include <windows.h> #include <io.h> #else #include <unistd.h> diff --git a/lib/libcxx/utils/google-benchmark/src/complexity.cc b/lib/libcxx/utils/google-benchmark/src/complexity.cc index aafd538df21..6ef17660c95 100644 --- a/lib/libcxx/utils/google-benchmark/src/complexity.cc +++ b/lib/libcxx/utils/google-benchmark/src/complexity.cc @@ -73,8 +73,8 @@ std::string GetBigOString(BigO complexity) { // - time : Vector containing the times for the benchmark tests. // - fitting_curve : lambda expression (e.g. [](int64_t n) {return n; };). -// For a deeper explanation on the algorithm logic, look the README file at -// http://github.com/ismaelJimenez/Minimal-Cpp-Least-Squared-Fit +// For a deeper explanation on the algorithm logic, please refer to +// https://en.wikipedia.org/wiki/Least_squares#Least_squares,_regression_analysis_and_statistics LeastSq MinimalLeastSq(const std::vector<int64_t>& n, const std::vector<double>& time, @@ -182,12 +182,15 @@ std::vector<BenchmarkReporter::Run> ComputeBigO( result_cpu = MinimalLeastSq(n, cpu_time, reports[0].complexity); result_real = MinimalLeastSq(n, real_time, result_cpu.complexity); } - std::string benchmark_name = - reports[0].benchmark_name.substr(0, reports[0].benchmark_name.find('/')); + + std::string run_name = reports[0].benchmark_name().substr( + 0, reports[0].benchmark_name().find('/')); // Get the data from the accumulator to BenchmarkReporter::Run's. Run big_o; - big_o.benchmark_name = benchmark_name + "_BigO"; + big_o.run_name = run_name; + big_o.run_type = BenchmarkReporter::Run::RT_Aggregate; + big_o.aggregate_name = "BigO"; big_o.iterations = 0; big_o.real_accumulated_time = result_real.coef; big_o.cpu_accumulated_time = result_cpu.coef; @@ -203,8 +206,10 @@ std::vector<BenchmarkReporter::Run> ComputeBigO( // Only add label to mean/stddev if it is same for all runs Run rms; + rms.run_name = run_name; big_o.report_label = reports[0].report_label; - rms.benchmark_name = benchmark_name + "_RMS"; + rms.run_type = BenchmarkReporter::Run::RT_Aggregate; + rms.aggregate_name = "RMS"; rms.report_label = big_o.report_label; rms.iterations = 0; rms.real_accumulated_time = result_real.rms / multiplier; diff --git a/lib/libcxx/utils/google-benchmark/src/console_reporter.cc b/lib/libcxx/utils/google-benchmark/src/console_reporter.cc index 48920ca7829..ca364727cb4 100644 --- a/lib/libcxx/utils/google-benchmark/src/console_reporter.cc +++ b/lib/libcxx/utils/google-benchmark/src/console_reporter.cc @@ -53,7 +53,7 @@ bool ConsoleReporter::ReportContext(const Context& context) { } void ConsoleReporter::PrintHeader(const Run& run) { - std::string str = FormatString("%-*s %13s %13s %10s", static_cast<int>(name_field_width_), + std::string str = FormatString("%-*s %13s %15s %12s", static_cast<int>(name_field_width_), "Benchmark", "Time", "CPU", "Iterations"); if(!run.counters.empty()) { if(output_options_ & OO_Tabular) { @@ -98,6 +98,21 @@ static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt, va_end(args); } + +static std::string FormatTime(double time) { + // Align decimal places... + if (time < 1.0) { + return FormatString("%10.3f", time); + } + if (time < 10.0) { + return FormatString("%10.2f", time); + } + if (time < 100.0) { + return FormatString("%10.1f", time); + } + return FormatString("%10.0f", time); +} + void ConsoleReporter::PrintRunData(const Run& result) { typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...); auto& Out = GetOutputStream(); @@ -106,7 +121,7 @@ void ConsoleReporter::PrintRunData(const Run& result) { auto name_color = (result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN; printer(Out, name_color, "%-*s ", name_field_width_, - result.benchmark_name.c_str()); + result.benchmark_name().c_str()); if (result.error_occurred) { printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'", @@ -114,33 +129,24 @@ void ConsoleReporter::PrintRunData(const Run& result) { printer(Out, COLOR_DEFAULT, "\n"); return; } - // Format bytes per second - std::string rate; - if (result.bytes_per_second > 0) { - rate = StrCat(" ", HumanReadableNumber(result.bytes_per_second), "B/s"); - } - - // Format items per second - std::string items; - if (result.items_per_second > 0) { - items = - StrCat(" ", HumanReadableNumber(result.items_per_second), " items/s"); - } const double real_time = result.GetAdjustedRealTime(); const double cpu_time = result.GetAdjustedCPUTime(); + const std::string real_time_str = FormatTime(real_time); + const std::string cpu_time_str = FormatTime(cpu_time); + if (result.report_big_o) { std::string big_o = GetBigOString(result.complexity); - printer(Out, COLOR_YELLOW, "%10.2f %s %10.2f %s ", real_time, big_o.c_str(), + printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", real_time, big_o.c_str(), cpu_time, big_o.c_str()); } else if (result.report_rms) { - printer(Out, COLOR_YELLOW, "%10.0f %% %10.0f %% ", real_time * 100, - cpu_time * 100); + printer(Out, COLOR_YELLOW, "%10.0f %-4s %10.0f %-4s ", real_time * 100, "%", + cpu_time * 100, "%"); } else { const char* timeLabel = GetTimeUnitString(result.time_unit); - printer(Out, COLOR_YELLOW, "%10.0f %s %10.0f %s ", real_time, timeLabel, - cpu_time, timeLabel); + printer(Out, COLOR_YELLOW, "%s %-4s %s %-4s ", real_time_str.c_str(), timeLabel, + cpu_time_str.c_str(), timeLabel); } if (!result.report_big_o && !result.report_rms) { @@ -150,7 +156,7 @@ void ConsoleReporter::PrintRunData(const Run& result) { for (auto& c : result.counters) { const std::size_t cNameLen = std::max(std::string::size_type(10), c.first.length()); - auto const& s = HumanReadableNumber(c.second.value, 1000); + auto const& s = HumanReadableNumber(c.second.value, c.second.oneK); if (output_options_ & OO_Tabular) { if (c.second.flags & Counter::kIsRate) { printer(Out, COLOR_DEFAULT, " %*s/s", cNameLen - 2, s.c_str()); @@ -164,14 +170,6 @@ void ConsoleReporter::PrintRunData(const Run& result) { } } - if (!rate.empty()) { - printer(Out, COLOR_DEFAULT, " %*s", 13, rate.c_str()); - } - - if (!items.empty()) { - printer(Out, COLOR_DEFAULT, " %*s", 18, items.c_str()); - } - if (!result.report_label.empty()) { printer(Out, COLOR_DEFAULT, " %s", result.report_label.c_str()); } diff --git a/lib/libcxx/utils/google-benchmark/src/csv_reporter.cc b/lib/libcxx/utils/google-benchmark/src/csv_reporter.cc index 4a641909d80..d2f1d27eb62 100644 --- a/lib/libcxx/utils/google-benchmark/src/csv_reporter.cc +++ b/lib/libcxx/utils/google-benchmark/src/csv_reporter.cc @@ -49,6 +49,8 @@ void CSVReporter::ReportRuns(const std::vector<Run>& reports) { // save the names of all the user counters for (const auto& run : reports) { for (const auto& cnt : run.counters) { + if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") + continue; user_counter_names_.insert(cnt.first); } } @@ -69,6 +71,8 @@ void CSVReporter::ReportRuns(const std::vector<Run>& reports) { // check that all the current counters are saved in the name set for (const auto& run : reports) { for (const auto& cnt : run.counters) { + if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") + continue; CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end()) << "All counters must be present in each run. " << "Counter named \"" << cnt.first @@ -88,7 +92,7 @@ void CSVReporter::PrintRunData(const Run& run) { // Field with embedded double-quote characters must be doubled and the field // delimited with double-quotes. - std::string name = run.benchmark_name; + std::string name = run.benchmark_name(); ReplaceAll(&name, "\"", "\"\""); Out << '"' << name << "\","; if (run.error_occurred) { @@ -117,12 +121,12 @@ void CSVReporter::PrintRunData(const Run& run) { } Out << ","; - if (run.bytes_per_second > 0.0) { - Out << run.bytes_per_second; + if (run.counters.find("bytes_per_second") != run.counters.end()) { + Out << run.counters.at("bytes_per_second"); } Out << ","; - if (run.items_per_second > 0.0) { - Out << run.items_per_second; + if (run.counters.find("items_per_second") != run.counters.end()) { + Out << run.counters.at("items_per_second"); } Out << ","; if (!run.report_label.empty()) { diff --git a/lib/libcxx/utils/google-benchmark/src/cycleclock.h b/lib/libcxx/utils/google-benchmark/src/cycleclock.h index 00d57641676..f5e37b011b9 100644 --- a/lib/libcxx/utils/google-benchmark/src/cycleclock.h +++ b/lib/libcxx/utils/google-benchmark/src/cycleclock.h @@ -41,7 +41,7 @@ extern "C" uint64_t __rdtsc(); #pragma intrinsic(__rdtsc) #endif -#ifndef BENCHMARK_OS_WINDOWS +#if !defined(BENCHMARK_OS_WINDOWS) || defined(BENCHMARK_OS_MINGW) #include <sys/time.h> #include <time.h> #endif diff --git a/lib/libcxx/utils/google-benchmark/src/internal_macros.h b/lib/libcxx/utils/google-benchmark/src/internal_macros.h index b7e9203ff60..5dbf4fd2752 100644 --- a/lib/libcxx/utils/google-benchmark/src/internal_macros.h +++ b/lib/libcxx/utils/google-benchmark/src/internal_macros.h @@ -11,9 +11,6 @@ #ifndef __has_feature #define __has_feature(x) 0 #endif -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif #if defined(__clang__) #if !defined(COMPILER_CLANG) @@ -43,6 +40,9 @@ #define BENCHMARK_OS_CYGWIN 1 #elif defined(_WIN32) #define BENCHMARK_OS_WINDOWS 1 + #if defined(__MINGW32__) + #define BENCHMARK_OS_MINGW 1 + #endif #elif defined(__APPLE__) #define BENCHMARK_OS_APPLE 1 #include "TargetConditionals.h" @@ -87,14 +87,6 @@ #define BENCHMARK_MAYBE_UNUSED #endif -#if defined(COMPILER_GCC) || __has_builtin(__builtin_unreachable) - #define BENCHMARK_UNREACHABLE() __builtin_unreachable() -#elif defined(COMPILER_MSVC) - #define BENCHMARK_UNREACHABLE() __assume(false) -#else - #define BENCHMARK_UNREACHABLE() ((void)0) -#endif - // clang-format on #endif // BENCHMARK_INTERNAL_MACROS_H_ diff --git a/lib/libcxx/utils/google-benchmark/src/json_reporter.cc b/lib/libcxx/utils/google-benchmark/src/json_reporter.cc index 611605af6b5..7d01e8e4e31 100644 --- a/lib/libcxx/utils/google-benchmark/src/json_reporter.cc +++ b/lib/libcxx/utils/google-benchmark/src/json_reporter.cc @@ -77,8 +77,15 @@ bool JSONReporter::ReportContext(const Context& context) { std::string walltime_value = LocalDateTimeString(); out << indent << FormatKV("date", walltime_value) << ",\n"; + out << indent << FormatKV("host_name", context.sys_info.name) << ",\n"; + if (Context::executable_name) { - out << indent << FormatKV("executable", Context::executable_name) << ",\n"; + // windows uses backslash for its path separator, + // which must be escaped in JSON otherwise it blows up conforming JSON + // decoders + std::string executable_name = Context::executable_name; + ReplaceAll(&executable_name, "\\", "\\\\"); + out << indent << FormatKV("executable", executable_name) << ",\n"; } CPUInfo const& info = context.cpu_info; @@ -111,6 +118,12 @@ bool JSONReporter::ReportContext(const Context& context) { } indent = std::string(4, ' '); out << indent << "],\n"; + out << indent << "\"load_avg\": ["; + for (auto it = info.load_avg.begin(); it != info.load_avg.end();) { + out << *it++; + if (it != info.load_avg.end()) out << ","; + } + out << "],\n"; #if defined(NDEBUG) const char build_type[] = "release"; @@ -154,7 +167,20 @@ void JSONReporter::Finalize() { void JSONReporter::PrintRunData(Run const& run) { std::string indent(6, ' '); std::ostream& out = GetOutputStream(); - out << indent << FormatKV("name", run.benchmark_name) << ",\n"; + out << indent << FormatKV("name", run.benchmark_name()) << ",\n"; + out << indent << FormatKV("run_name", run.run_name) << ",\n"; + out << indent << FormatKV("run_type", [&run]() -> const char* { + switch (run.run_type) { + case BenchmarkReporter::Run::RT_Iteration: + return "iteration"; + case BenchmarkReporter::Run::RT_Aggregate: + return "aggregate"; + } + BENCHMARK_UNREACHABLE(); + }()) << ",\n"; + if (run.run_type == BenchmarkReporter::Run::RT_Aggregate) { + out << indent << FormatKV("aggregate_name", run.aggregate_name) << ",\n"; + } if (run.error_occurred) { out << indent << FormatKV("error_occurred", run.error_occurred) << ",\n"; out << indent << FormatKV("error_message", run.error_message) << ",\n"; @@ -175,17 +201,16 @@ void JSONReporter::PrintRunData(Run const& run) { } else if (run.report_rms) { out << indent << FormatKV("rms", run.GetAdjustedCPUTime()); } - if (run.bytes_per_second > 0.0) { - out << ",\n" - << indent << FormatKV("bytes_per_second", run.bytes_per_second); - } - if (run.items_per_second > 0.0) { - out << ",\n" - << indent << FormatKV("items_per_second", run.items_per_second); - } + for (auto& c : run.counters) { out << ",\n" << indent << FormatKV(c.first, c.second); } + + if (run.has_memory_result) { + out << ",\n" << indent << FormatKV("allocs_per_iter", run.allocs_per_iter); + out << ",\n" << indent << FormatKV("max_bytes_used", run.max_bytes_used); + } + if (!run.report_label.empty()) { out << ",\n" << indent << FormatKV("label", run.report_label); } diff --git a/lib/libcxx/utils/google-benchmark/src/reporter.cc b/lib/libcxx/utils/google-benchmark/src/reporter.cc index 541661a25f0..59bc5f71023 100644 --- a/lib/libcxx/utils/google-benchmark/src/reporter.cc +++ b/lib/libcxx/utils/google-benchmark/src/reporter.cc @@ -22,6 +22,7 @@ #include <vector> #include "check.h" +#include "string_util.h" namespace benchmark { @@ -54,6 +55,14 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, Out << "\n"; } } + if (!info.load_avg.empty()) { + Out << "Load Average: "; + for (auto It = info.load_avg.begin(); It != info.load_avg.end();) { + Out << StrFormat("%.2f", *It++); + if (It != info.load_avg.end()) Out << ", "; + } + Out << "\n"; + } if (info.scaling_enabled) { Out << "***WARNING*** CPU scaling is enabled, the benchmark " @@ -70,7 +79,16 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, // No initializer because it's already initialized to NULL. const char *BenchmarkReporter::Context::executable_name; -BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()) {} +BenchmarkReporter::Context::Context() + : cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {} + +std::string BenchmarkReporter::Run::benchmark_name() const { + std::string name = run_name; + if (run_type == RT_Aggregate) { + name += "_" + aggregate_name; + } + return name; +} double BenchmarkReporter::Run::GetAdjustedRealTime() const { double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit); diff --git a/lib/libcxx/utils/google-benchmark/src/sleep.cc b/lib/libcxx/utils/google-benchmark/src/sleep.cc index 54aa04a4224..1512ac90f7e 100644 --- a/lib/libcxx/utils/google-benchmark/src/sleep.cc +++ b/lib/libcxx/utils/google-benchmark/src/sleep.cc @@ -21,7 +21,7 @@ #include "internal_macros.h" #ifdef BENCHMARK_OS_WINDOWS -#include <Windows.h> +#include <windows.h> #endif namespace benchmark { diff --git a/lib/libcxx/utils/google-benchmark/src/statistics.cc b/lib/libcxx/utils/google-benchmark/src/statistics.cc index 612dda2d1a7..e821aec18b7 100644 --- a/lib/libcxx/utils/google-benchmark/src/statistics.cc +++ b/lib/libcxx/utils/google-benchmark/src/statistics.cc @@ -91,13 +91,9 @@ std::vector<BenchmarkReporter::Run> ComputeStats( // Accumulators. std::vector<double> real_accumulated_time_stat; std::vector<double> cpu_accumulated_time_stat; - std::vector<double> bytes_per_second_stat; - std::vector<double> items_per_second_stat; real_accumulated_time_stat.reserve(reports.size()); cpu_accumulated_time_stat.reserve(reports.size()); - bytes_per_second_stat.reserve(reports.size()); - items_per_second_stat.reserve(reports.size()); // All repetitions should be run with the same number of iterations so we // can take this information from the first benchmark. @@ -123,13 +119,11 @@ std::vector<BenchmarkReporter::Run> ComputeStats( // Populate the accumulators. for (Run const& run : reports) { - CHECK_EQ(reports[0].benchmark_name, run.benchmark_name); + CHECK_EQ(reports[0].benchmark_name(), run.benchmark_name()); CHECK_EQ(run_iterations, run.iterations); if (run.error_occurred) continue; real_accumulated_time_stat.emplace_back(run.real_accumulated_time); cpu_accumulated_time_stat.emplace_back(run.cpu_accumulated_time); - items_per_second_stat.emplace_back(run.items_per_second); - bytes_per_second_stat.emplace_back(run.bytes_per_second); // user counters for (auto const& cnt : run.counters) { auto it = counter_stats.find(cnt.first); @@ -147,24 +141,43 @@ std::vector<BenchmarkReporter::Run> ComputeStats( } } + const double iteration_rescale_factor = + double(reports.size()) / double(run_iterations); + for (const auto& Stat : *reports[0].statistics) { // Get the data from the accumulator to BenchmarkReporter::Run's. Run data; - data.benchmark_name = reports[0].benchmark_name + "_" + Stat.name_; + data.run_name = reports[0].benchmark_name(); + data.run_type = BenchmarkReporter::Run::RT_Aggregate; + data.aggregate_name = Stat.name_; data.report_label = report_label; - data.iterations = run_iterations; + + // It is incorrect to say that an aggregate is computed over + // run's iterations, because those iterations already got averaged. + // Similarly, if there are N repetitions with 1 iterations each, + // an aggregate will be computed over N measurements, not 1. + // Thus it is best to simply use the count of separate reports. + data.iterations = reports.size(); data.real_accumulated_time = Stat.compute_(real_accumulated_time_stat); data.cpu_accumulated_time = Stat.compute_(cpu_accumulated_time_stat); - data.bytes_per_second = Stat.compute_(bytes_per_second_stat); - data.items_per_second = Stat.compute_(items_per_second_stat); + + // We will divide these times by data.iterations when reporting, but the + // data.iterations is not nessesairly the scale of these measurements, + // because in each repetition, these timers are sum over all the iterations. + // And if we want to say that the stats are over N repetitions and not + // M iterations, we need to multiply these by (N/M). + data.real_accumulated_time *= iteration_rescale_factor; + data.cpu_accumulated_time *= iteration_rescale_factor; data.time_unit = reports[0].time_unit; // user counters for (auto const& kv : counter_stats) { + // Do *NOT* rescale the custom counters. They are already properly scaled. const auto uc_stat = Stat.compute_(kv.second.s); - auto c = Counter(uc_stat, counter_stats[kv.first].c.flags); + auto c = Counter(uc_stat, counter_stats[kv.first].c.flags, + counter_stats[kv.first].c.oneK); data.counters[kv.first] = c; } diff --git a/lib/libcxx/utils/google-benchmark/src/string_util.h b/lib/libcxx/utils/google-benchmark/src/string_util.h index 4a5501273cf..fc5f8b0304b 100644 --- a/lib/libcxx/utils/google-benchmark/src/string_util.h +++ b/lib/libcxx/utils/google-benchmark/src/string_util.h @@ -12,7 +12,11 @@ void AppendHumanReadable(int n, std::string* str); std::string HumanReadableNumber(double n, double one_k = 1024.0); -std::string StrFormat(const char* format, ...); +#ifdef __GNUC__ +__attribute__((format(printf, 1, 2))) +#endif +std::string +StrFormat(const char* format, ...); inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT { return out; diff --git a/lib/libcxx/utils/google-benchmark/src/sysinfo.cc b/lib/libcxx/utils/google-benchmark/src/sysinfo.cc index 73064b97ba2..c0c07e5e62a 100644 --- a/lib/libcxx/utils/google-benchmark/src/sysinfo.cc +++ b/lib/libcxx/utils/google-benchmark/src/sysinfo.cc @@ -15,10 +15,11 @@ #include "internal_macros.h" #ifdef BENCHMARK_OS_WINDOWS -#include <Shlwapi.h> +#include <shlwapi.h> #undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA -#include <VersionHelpers.h> -#include <Windows.h> +#include <versionhelpers.h> +#include <windows.h> +#include <codecvt> #else #include <fcntl.h> #ifndef BENCHMARK_OS_FUCHSIA @@ -52,6 +53,7 @@ #include <limits> #include <memory> #include <sstream> +#include <locale> #include "check.h" #include "cycleclock.h" @@ -288,7 +290,7 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizesMacOSX() { std::string name; std::string type; int level; - size_t num_sharing; + uint64_t num_sharing; } Cases[] = {{"hw.l1dcachesize", "Data", 1, CacheCounts[1]}, {"hw.l1icachesize", "Instruction", 1, CacheCounts[1]}, {"hw.l2cachesize", "Unified", 2, CacheCounts[2]}, @@ -366,6 +368,35 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizes() { #endif } +std::string GetSystemName() { +#if defined(BENCHMARK_OS_WINDOWS) + std::string str; + const unsigned COUNT = MAX_COMPUTERNAME_LENGTH+1; + TCHAR hostname[COUNT] = {'\0'}; + DWORD DWCOUNT = COUNT; + if (!GetComputerName(hostname, &DWCOUNT)) + return std::string(""); +#ifndef UNICODE + str = std::string(hostname, DWCOUNT); +#else + //Using wstring_convert, Is deprecated in C++17 + using convert_type = std::codecvt_utf8<wchar_t>; + std::wstring_convert<convert_type, wchar_t> converter; + std::wstring wStr(hostname, DWCOUNT); + str = converter.to_bytes(wStr); +#endif + return str; +#else // defined(BENCHMARK_OS_WINDOWS) +#ifdef BENCHMARK_OS_MACOSX //Mac Doesnt have HOST_NAME_MAX defined +#define HOST_NAME_MAX 64 +#endif + char hostname[HOST_NAME_MAX]; + int retVal = gethostname(hostname, HOST_NAME_MAX); + if (retVal != 0) return std::string(""); + return std::string(hostname); +#endif // Catch-all POSIX block. +} + int GetNumCPUs() { #ifdef BENCHMARK_HAS_SYSCTL int NumCPU = -1; @@ -404,7 +435,13 @@ int GetNumCPUs() { if (ln.empty()) continue; size_t SplitIdx = ln.find(':'); std::string value; +#if defined(__s390__) + // s390 has another format in /proc/cpuinfo + // it needs to be parsed differently + if (SplitIdx != std::string::npos) value = ln.substr(Key.size()+1,SplitIdx-Key.size()-1); +#else if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1); +#endif if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) { NumCPUs++; if (!value.empty()) { @@ -571,6 +608,24 @@ double GetCPUCyclesPerSecond() { return static_cast<double>(cycleclock::Now() - start_ticks); } +std::vector<double> GetLoadAvg() { +#if defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) || \ + defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \ + defined BENCHMARK_OS_OPENBSD + constexpr int kMaxSamples = 3; + std::vector<double> res(kMaxSamples, 0.0); + const int nelem = getloadavg(res.data(), kMaxSamples); + if (nelem < 1) { + res.clear(); + } else { + res.resize(nelem); + } + return res; +#else + return {}; +#endif +} + } // end namespace const CPUInfo& CPUInfo::Get() { @@ -582,6 +637,14 @@ CPUInfo::CPUInfo() : num_cpus(GetNumCPUs()), cycles_per_second(GetCPUCyclesPerSecond()), caches(GetCacheSizes()), - scaling_enabled(CpuScalingEnabled(num_cpus)) {} + scaling_enabled(CpuScalingEnabled(num_cpus)), + load_avg(GetLoadAvg()) {} + + +const SystemInfo& SystemInfo::Get() { + static const SystemInfo* info = new SystemInfo(); + return *info; +} +SystemInfo::SystemInfo() : name(GetSystemName()) {} } // end namespace benchmark diff --git a/lib/libcxx/utils/google-benchmark/src/thread_manager.h b/lib/libcxx/utils/google-benchmark/src/thread_manager.h index 82b4d72b62f..6e274c7ea6b 100644 --- a/lib/libcxx/utils/google-benchmark/src/thread_manager.h +++ b/lib/libcxx/utils/google-benchmark/src/thread_manager.h @@ -42,8 +42,6 @@ class ThreadManager { double real_time_used = 0; double cpu_time_used = 0; double manual_time_used = 0; - int64_t bytes_processed = 0; - int64_t items_processed = 0; int64_t complexity_n = 0; std::string report_label_; std::string error_message_; diff --git a/lib/libcxx/utils/google-benchmark/src/timers.cc b/lib/libcxx/utils/google-benchmark/src/timers.cc index 2010e2450b4..7613ff92c6e 100644 --- a/lib/libcxx/utils/google-benchmark/src/timers.cc +++ b/lib/libcxx/utils/google-benchmark/src/timers.cc @@ -16,10 +16,10 @@ #include "internal_macros.h" #ifdef BENCHMARK_OS_WINDOWS -#include <Shlwapi.h> +#include <shlwapi.h> #undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA -#include <VersionHelpers.h> -#include <Windows.h> +#include <versionhelpers.h> +#include <windows.h> #else #include <fcntl.h> #ifndef BENCHMARK_OS_FUCHSIA diff --git a/lib/libcxx/utils/google-benchmark/test/AssemblyTests.cmake b/lib/libcxx/utils/google-benchmark/test/AssemblyTests.cmake new file mode 100644 index 00000000000..3d078586f1d --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/test/AssemblyTests.cmake @@ -0,0 +1,46 @@ + +include(split_list) + +set(ASM_TEST_FLAGS "") +check_cxx_compiler_flag(-O3 BENCHMARK_HAS_O3_FLAG) +if (BENCHMARK_HAS_O3_FLAG) + list(APPEND ASM_TEST_FLAGS -O3) +endif() + +check_cxx_compiler_flag(-g0 BENCHMARK_HAS_G0_FLAG) +if (BENCHMARK_HAS_G0_FLAG) + list(APPEND ASM_TEST_FLAGS -g0) +endif() + +check_cxx_compiler_flag(-fno-stack-protector BENCHMARK_HAS_FNO_STACK_PROTECTOR_FLAG) +if (BENCHMARK_HAS_FNO_STACK_PROTECTOR_FLAG) + list(APPEND ASM_TEST_FLAGS -fno-stack-protector) +endif() + +split_list(ASM_TEST_FLAGS) +string(TOUPPER "${CMAKE_CXX_COMPILER_ID}" ASM_TEST_COMPILER) + +macro(add_filecheck_test name) + cmake_parse_arguments(ARG "" "" "CHECK_PREFIXES" ${ARGV}) + add_library(${name} OBJECT ${name}.cc) + set_target_properties(${name} PROPERTIES COMPILE_FLAGS "-S ${ASM_TEST_FLAGS}") + set(ASM_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${name}.s") + add_custom_target(copy_${name} ALL + COMMAND ${PROJECT_SOURCE_DIR}/tools/strip_asm.py + $<TARGET_OBJECTS:${name}> + ${ASM_OUTPUT_FILE} + BYPRODUCTS ${ASM_OUTPUT_FILE}) + add_dependencies(copy_${name} ${name}) + if (NOT ARG_CHECK_PREFIXES) + set(ARG_CHECK_PREFIXES "CHECK") + endif() + foreach(prefix ${ARG_CHECK_PREFIXES}) + add_test(NAME run_${name}_${prefix} + COMMAND + ${LLVM_FILECHECK_EXE} ${name}.cc + --input-file=${ASM_OUTPUT_FILE} + --check-prefixes=CHECK,CHECK-${ASM_TEST_COMPILER} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + endforeach() +endmacro() + diff --git a/lib/libcxx/utils/google-benchmark/test/CMakeLists.txt b/lib/libcxx/utils/google-benchmark/test/CMakeLists.txt index f49ca5148f4..f15ce208189 100644 --- a/lib/libcxx/utils/google-benchmark/test/CMakeLists.txt +++ b/lib/libcxx/utils/google-benchmark/test/CMakeLists.txt @@ -125,9 +125,21 @@ add_test(templated_fixture_test templated_fixture_test --benchmark_min_time=0.01 compile_output_test(user_counters_test) add_test(user_counters_test user_counters_test --benchmark_min_time=0.01) +compile_output_test(report_aggregates_only_test) +add_test(report_aggregates_only_test report_aggregates_only_test --benchmark_min_time=0.01) + +compile_output_test(display_aggregates_only_test) +add_test(display_aggregates_only_test display_aggregates_only_test --benchmark_min_time=0.01) + compile_output_test(user_counters_tabular_test) add_test(user_counters_tabular_test user_counters_tabular_test --benchmark_counters_tabular=true --benchmark_min_time=0.01) +compile_output_test(user_counters_thousands_test) +add_test(user_counters_thousands_test user_counters_thousands_test --benchmark_min_time=0.01) + +compile_output_test(memory_manager_test) +add_test(memory_manager_test memory_manager_test --benchmark_min_time=0.01) + check_cxx_compiler_flag(-std=c++03 BENCHMARK_HAS_CXX03_FLAG) if (BENCHMARK_HAS_CXX03_FLAG) compile_benchmark_test(cxx03_test) diff --git a/lib/libcxx/utils/google-benchmark/test/complexity_test.cc b/lib/libcxx/utils/google-benchmark/test/complexity_test.cc index 5f91660898b..323ddfe7ac5 100644 --- a/lib/libcxx/utils/google-benchmark/test/complexity_test.cc +++ b/lib/libcxx/utils/google-benchmark/test/complexity_test.cc @@ -12,9 +12,10 @@ namespace { #define ADD_COMPLEXITY_CASES(...) \ int CONCAT(dummy, __LINE__) = AddComplexityTest(__VA_ARGS__) -int AddComplexityTest(std::string big_o_test_name, std::string rms_test_name, - std::string big_o) { - SetSubstitutions({{"%bigo_name", big_o_test_name}, +int AddComplexityTest(std::string test_name, std::string big_o_test_name, + std::string rms_test_name, std::string big_o) { + SetSubstitutions({{"%name", test_name}, + {"%bigo_name", big_o_test_name}, {"%rms_name", rms_test_name}, {"%bigo_str", "[ ]* %float " + big_o}, {"%bigo", big_o}, @@ -25,12 +26,18 @@ int AddComplexityTest(std::string big_o_test_name, std::string rms_test_name, {"^%bigo_name", MR_Not}, // Assert we we didn't only matched a name. {"^%rms_name %rms %rms[ ]*$", MR_Next}}); AddCases(TC_JSONOut, {{"\"name\": \"%bigo_name\",$"}, + {"\"run_name\": \"%name\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"BigO\",$", MR_Next}, {"\"cpu_coefficient\": %float,$", MR_Next}, {"\"real_coefficient\": %float,$", MR_Next}, {"\"big_o\": \"%bigo\",$", MR_Next}, {"\"time_unit\": \"ns\"$", MR_Next}, {"}", MR_Next}, {"\"name\": \"%rms_name\",$"}, + {"\"run_name\": \"%name\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"RMS\",$", MR_Next}, {"\"rms\": %float$", MR_Next}, {"}", MR_Next}}); AddCases(TC_CSVOut, {{"^\"%bigo_name\",,%float,%float,%bigo,,,,,$"}, @@ -59,6 +66,7 @@ BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity([](int64_t) { return 1.0; }); +const char *one_test_name = "BM_Complexity_O1"; const char *big_o_1_test_name = "BM_Complexity_O1_BigO"; const char *rms_o_1_test_name = "BM_Complexity_O1_RMS"; const char *enum_big_o_1 = "\\([0-9]+\\)"; @@ -69,13 +77,16 @@ const char *auto_big_o_1 = "(\\([0-9]+\\))|(lgN)"; const char *lambda_big_o_1 = "f\\(N\\)"; // Add enum tests -ADD_COMPLEXITY_CASES(big_o_1_test_name, rms_o_1_test_name, enum_big_o_1); +ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, + enum_big_o_1); // Add auto enum tests -ADD_COMPLEXITY_CASES(big_o_1_test_name, rms_o_1_test_name, auto_big_o_1); +ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, + auto_big_o_1); // Add lambda tests -ADD_COMPLEXITY_CASES(big_o_1_test_name, rms_o_1_test_name, lambda_big_o_1); +ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, + lambda_big_o_1); // ========================================================================= // // --------------------------- Testing BigO O(N) --------------------------- // @@ -112,16 +123,19 @@ BENCHMARK(BM_Complexity_O_N) ->Range(1 << 10, 1 << 16) ->Complexity(); +const char *n_test_name = "BM_Complexity_O_N"; const char *big_o_n_test_name = "BM_Complexity_O_N_BigO"; const char *rms_o_n_test_name = "BM_Complexity_O_N_RMS"; const char *enum_auto_big_o_n = "N"; const char *lambda_big_o_n = "f\\(N\\)"; // Add enum tests -ADD_COMPLEXITY_CASES(big_o_n_test_name, rms_o_n_test_name, enum_auto_big_o_n); +ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name, + enum_auto_big_o_n); // Add lambda tests -ADD_COMPLEXITY_CASES(big_o_n_test_name, rms_o_n_test_name, lambda_big_o_n); +ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name, + lambda_big_o_n); // ========================================================================= // // ------------------------- Testing BigO O(N*lgN) ------------------------- // @@ -148,18 +162,19 @@ BENCHMARK(BM_Complexity_O_N_log_N) ->Range(1 << 10, 1 << 16) ->Complexity(); +const char *n_lg_n_test_name = "BM_Complexity_O_N_log_N"; const char *big_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_BigO"; const char *rms_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_RMS"; const char *enum_auto_big_o_n_lg_n = "NlgN"; const char *lambda_big_o_n_lg_n = "f\\(N\\)"; // Add enum tests -ADD_COMPLEXITY_CASES(big_o_n_lg_n_test_name, rms_o_n_lg_n_test_name, - enum_auto_big_o_n_lg_n); +ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name, + rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n); // Add lambda tests -ADD_COMPLEXITY_CASES(big_o_n_lg_n_test_name, rms_o_n_lg_n_test_name, - lambda_big_o_n_lg_n); +ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name, + rms_o_n_lg_n_test_name, lambda_big_o_n_lg_n); // ========================================================================= // // --------------------------- TEST CASES END ------------------------------ // diff --git a/lib/libcxx/utils/google-benchmark/test/display_aggregates_only_test.cc b/lib/libcxx/utils/google-benchmark/test/display_aggregates_only_test.cc new file mode 100644 index 00000000000..3c36d3f03c1 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/test/display_aggregates_only_test.cc @@ -0,0 +1,43 @@ + +#undef NDEBUG +#include <cstdio> +#include <string> + +#include "benchmark/benchmark.h" +#include "output_test.h" + +// Ok this test is super ugly. We want to check what happens with the file +// reporter in the presence of DisplayAggregatesOnly(). +// We do not care about console output, the normal tests check that already. + +void BM_SummaryRepeat(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_SummaryRepeat)->Repetitions(3)->DisplayAggregatesOnly(); + +int main(int argc, char* argv[]) { + const std::string output = GetFileReporterOutput(argc, argv); + + if (SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3") != 6 || + SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3\"") != 3 || + SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_mean\"") != 1 || + SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_median\"") != + 1 || + SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"") != + 1) { + std::cout << "Precondition mismatch. Expected to only find 6 " + "occurrences of \"BM_SummaryRepeat/repeats:3\" substring:\n" + "\"name\": \"BM_SummaryRepeat/repeats:3\", " + "\"name\": \"BM_SummaryRepeat/repeats:3\", " + "\"name\": \"BM_SummaryRepeat/repeats:3\", " + "\"name\": \"BM_SummaryRepeat/repeats:3_mean\", " + "\"name\": \"BM_SummaryRepeat/repeats:3_median\", " + "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"\nThe entire " + "output:\n"; + std::cout << output; + return 1; + } + + return 0; +} diff --git a/lib/libcxx/utils/google-benchmark/test/memory_manager_test.cc b/lib/libcxx/utils/google-benchmark/test/memory_manager_test.cc new file mode 100644 index 00000000000..94be6083795 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/test/memory_manager_test.cc @@ -0,0 +1,42 @@ +#include <memory> + +#include "../src/check.h" +#include "benchmark/benchmark.h" +#include "output_test.h" + +class TestMemoryManager : public benchmark::MemoryManager { + void Start() {} + void Stop(Result* result) { + result->num_allocs = 42; + result->max_bytes_used = 42000; + } +}; + +void BM_empty(benchmark::State& state) { + for (auto _ : state) { + benchmark::DoNotOptimize(state.iterations()); + } +} +BENCHMARK(BM_empty); + +ADD_CASES(TC_ConsoleOut, {{"^BM_empty %console_report$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_empty\",$"}, + {"\"run_name\": \"BM_empty\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"allocs_per_iter\": %float,$", MR_Next}, + {"\"max_bytes_used\": 42000$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_empty\",%csv_report$"}}); + + +int main(int argc, char *argv[]) { + std::unique_ptr<benchmark::MemoryManager> mm(new TestMemoryManager()); + + benchmark::RegisterMemoryManager(mm.get()); + RunOutputTests(argc, argv); + benchmark::RegisterMemoryManager(nullptr); +} diff --git a/lib/libcxx/utils/google-benchmark/test/output_test.h b/lib/libcxx/utils/google-benchmark/test/output_test.h index 31a919991f7..9385761b214 100644 --- a/lib/libcxx/utils/google-benchmark/test/output_test.h +++ b/lib/libcxx/utils/google-benchmark/test/output_test.h @@ -60,6 +60,13 @@ int SetSubstitutions( // Run all output tests. void RunOutputTests(int argc, char* argv[]); +// Count the number of 'pat' substrings in the 'haystack' string. +int SubstrCnt(const std::string& haystack, const std::string& pat); + +// Run registered benchmarks with file reporter enabled, and return the content +// outputted by the file reporter. +std::string GetFileReporterOutput(int argc, char* argv[]); + // ========================================================================= // // ------------------------- Results checking ------------------------------ // // ========================================================================= // diff --git a/lib/libcxx/utils/google-benchmark/test/output_test_helper.cc b/lib/libcxx/utils/google-benchmark/test/output_test_helper.cc index 394c4f5d1a2..5dc951d2bca 100644 --- a/lib/libcxx/utils/google-benchmark/test/output_test_helper.cc +++ b/lib/libcxx/utils/google-benchmark/test/output_test_helper.cc @@ -1,8 +1,12 @@ +#include <cstdio> #include <cstring> +#include <fstream> #include <iostream> #include <map> #include <memory> +#include <random> #include <sstream> +#include <streambuf> #include "../src/benchmark_api_internal.h" #include "../src/check.h" // NOTE: check.h is for internal use only! @@ -35,15 +39,18 @@ SubMap& GetSubstitutions() { // Don't use 'dec_re' from header because it may not yet be initialized. // clang-format off static std::string safe_dec_re = "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?"; + static std::string time_re = "([0-9]+[.])?[0-9]+"; static SubMap map = { {"%float", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?"}, // human-readable float {"%hrfloat", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?[kMGTPEZYmunpfazy]?"}, {"%int", "[ ]*[0-9]+"}, {" %s ", "[ ]+"}, - {"%time", "[ ]*[0-9]{1,6} ns"}, - {"%console_report", "[ ]*[0-9]{1,6} ns [ ]*[0-9]{1,6} ns [ ]*[0-9]+"}, - {"%console_us_report", "[ ]*[0-9] us [ ]*[0-9] us [ ]*[0-9]+"}, + {"%time", "[ ]*" + time_re + "[ ]+ns"}, + {"%console_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns [ ]*[0-9]+"}, + {"%console_time_only_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns"}, + {"%console_us_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us [ ]*[0-9]+"}, + {"%console_us_time_only_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us"}, {"%csv_header", "name,iterations,real_time,cpu_time,time_unit,bytes_per_second," "items_per_second,label,error_occurred,error_message"}, @@ -202,7 +209,7 @@ void ResultsChecker::Add(const std::string& entry_pattern, ResultsCheckFn fn) { void ResultsChecker::CheckResults(std::stringstream& output) { // first reset the stream to the start { - auto start = std::ios::streampos(0); + auto start = std::stringstream::pos_type(0); // clear before calling tellg() output.clear(); // seek to zero only when needed @@ -423,3 +430,76 @@ void RunOutputTests(int argc, char* argv[]) { CHECK(std::strcmp(csv.name, "CSVReporter") == 0); internal::GetResultsChecker().CheckResults(csv.out_stream); } + +int SubstrCnt(const std::string& haystack, const std::string& pat) { + if (pat.length() == 0) return 0; + int count = 0; + for (size_t offset = haystack.find(pat); offset != std::string::npos; + offset = haystack.find(pat, offset + pat.length())) + ++count; + return count; +} + +static char ToHex(int ch) { + return ch < 10 ? static_cast<char>('0' + ch) + : static_cast<char>('a' + (ch - 10)); +} + +static char RandomHexChar() { + static std::mt19937 rd{std::random_device{}()}; + static std::uniform_int_distribution<int> mrand{0, 15}; + return ToHex(mrand(rd)); +} + +static std::string GetRandomFileName() { + std::string model = "test.%%%%%%"; + for (auto & ch : model) { + if (ch == '%') + ch = RandomHexChar(); + } + return model; +} + +static bool FileExists(std::string const& name) { + std::ifstream in(name.c_str()); + return in.good(); +} + +static std::string GetTempFileName() { + // This function attempts to avoid race conditions where two tests + // create the same file at the same time. However, it still introduces races + // similar to tmpnam. + int retries = 3; + while (--retries) { + std::string name = GetRandomFileName(); + if (!FileExists(name)) + return name; + } + std::cerr << "Failed to create unique temporary file name" << std::endl; + std::abort(); +} + +std::string GetFileReporterOutput(int argc, char* argv[]) { + std::vector<char*> new_argv(argv, argv + argc); + assert(static_cast<decltype(new_argv)::size_type>(argc) == new_argv.size()); + + std::string tmp_file_name = GetTempFileName(); + std::cout << "Will be using this as the tmp file: " << tmp_file_name << '\n'; + + std::string tmp = "--benchmark_out="; + tmp += tmp_file_name; + new_argv.emplace_back(const_cast<char*>(tmp.c_str())); + + argc = int(new_argv.size()); + + benchmark::Initialize(&argc, new_argv.data()); + benchmark::RunSpecifiedBenchmarks(); + + // Read the output back from the file, and delete the file. + std::ifstream tmp_stream(tmp_file_name); + std::string output = std::string((std::istreambuf_iterator<char>(tmp_stream)), + std::istreambuf_iterator<char>()); + std::remove(tmp_file_name.c_str()); + + return output; +} diff --git a/lib/libcxx/utils/google-benchmark/test/register_benchmark_test.cc b/lib/libcxx/utils/google-benchmark/test/register_benchmark_test.cc index 18de6d68e21..3ac5b21fb34 100644 --- a/lib/libcxx/utils/google-benchmark/test/register_benchmark_test.cc +++ b/lib/libcxx/utils/google-benchmark/test/register_benchmark_test.cc @@ -30,8 +30,8 @@ struct TestCase { void CheckRun(Run const& run) const { // clang-format off - CHECK(name == run.benchmark_name) << "expected " << name << " got " - << run.benchmark_name; + CHECK(name == run.benchmark_name()) << "expected " << name << " got " + << run.benchmark_name(); if (label) { CHECK(run.report_label == label) << "expected " << label << " got " << run.report_label; diff --git a/lib/libcxx/utils/google-benchmark/test/report_aggregates_only_test.cc b/lib/libcxx/utils/google-benchmark/test/report_aggregates_only_test.cc new file mode 100644 index 00000000000..9646b9be534 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/test/report_aggregates_only_test.cc @@ -0,0 +1,39 @@ + +#undef NDEBUG +#include <cstdio> +#include <string> + +#include "benchmark/benchmark.h" +#include "output_test.h" + +// Ok this test is super ugly. We want to check what happens with the file +// reporter in the presence of ReportAggregatesOnly(). +// We do not care about console output, the normal tests check that already. + +void BM_SummaryRepeat(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_SummaryRepeat)->Repetitions(3)->ReportAggregatesOnly(); + +int main(int argc, char* argv[]) { + const std::string output = GetFileReporterOutput(argc, argv); + + if (SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3") != 3 || + SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_mean\"") != 1 || + SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_median\"") != + 1 || + SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"") != + 1) { + std::cout << "Precondition mismatch. Expected to only find three " + "occurrences of \"BM_SummaryRepeat/repeats:3\" substring:\n" + "\"name\": \"BM_SummaryRepeat/repeats:3_mean\", " + "\"name\": \"BM_SummaryRepeat/repeats:3_median\", " + "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"\nThe entire " + "output:\n"; + std::cout << output; + return 1; + } + + return 0; +} diff --git a/lib/libcxx/utils/google-benchmark/test/reporter_output_test.cc b/lib/libcxx/utils/google-benchmark/test/reporter_output_test.cc index 1662fcb8b54..ec6d51b3591 100644 --- a/lib/libcxx/utils/google-benchmark/test/reporter_output_test.cc +++ b/lib/libcxx/utils/google-benchmark/test/reporter_output_test.cc @@ -17,18 +17,21 @@ static int AddContextCases() { { {"%int[-/]%int[-/]%int %int:%int:%int$", MR_Default}, {"Running .*/reporter_output_test(\\.exe)?$", MR_Next}, - {"Run on \\(%int X %float MHz CPU s\\)", MR_Next}, + {"Run on \\(%int X %float MHz CPU s?\\)", MR_Next}, }); AddCases(TC_JSONOut, {{"^\\{", MR_Default}, {"\"context\":", MR_Next}, {"\"date\": \"", MR_Next}, - {"\"executable\": \".*/reporter_output_test(\\.exe)?\",", MR_Next}, + {"\"host_name\":", MR_Next}, + {"\"executable\": \".*(/|\\\\)reporter_output_test(\\.exe)?\",", + MR_Next}, {"\"num_cpus\": %int,$", MR_Next}, {"\"mhz_per_cpu\": %float,$", MR_Next}, {"\"cpu_scaling_enabled\": ", MR_Next}, {"\"caches\": \\[$", MR_Next}}); - auto const& Caches = benchmark::CPUInfo::Get().caches; + auto const& Info = benchmark::CPUInfo::Get(); + auto const& Caches = Info.caches; if (!Caches.empty()) { AddCases(TC_ConsoleErr, {{"CPU Caches:$", MR_Next}}); } @@ -45,8 +48,13 @@ static int AddContextCases() { {"\"num_sharing\": %int$", MR_Next}, {"}[,]{0,1}$", MR_Next}}); } - AddCases(TC_JSONOut, {{"],$"}}); + auto const& LoadAvg = Info.load_avg; + if (!LoadAvg.empty()) { + AddCases(TC_ConsoleErr, + {{"Load Average: (%float, ){0,2}%float$", MR_Next}}); + } + AddCases(TC_JSONOut, {{"\"load_avg\": \\[(%float,?){0,3}],$", MR_Next}}); return 0; } int dummy_register = AddContextCases(); @@ -64,6 +72,8 @@ BENCHMARK(BM_basic); ADD_CASES(TC_ConsoleOut, {{"^BM_basic %console_report$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_basic\",$"}, + {"\"run_name\": \"BM_basic\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -82,9 +92,11 @@ void BM_bytes_per_second(benchmark::State& state) { } BENCHMARK(BM_bytes_per_second); -ADD_CASES(TC_ConsoleOut, - {{"^BM_bytes_per_second %console_report +%float[kM]{0,1}B/s$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_bytes_per_second %console_report " + "bytes_per_second=%float[kM]{0,1}/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_bytes_per_second\",$"}, + {"\"run_name\": \"BM_bytes_per_second\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -104,9 +116,11 @@ void BM_items_per_second(benchmark::State& state) { } BENCHMARK(BM_items_per_second); -ADD_CASES(TC_ConsoleOut, - {{"^BM_items_per_second %console_report +%float[kM]{0,1} items/s$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_items_per_second %console_report " + "items_per_second=%float[kM]{0,1}/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_items_per_second\",$"}, + {"\"run_name\": \"BM_items_per_second\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -128,6 +142,8 @@ BENCHMARK(BM_label); ADD_CASES(TC_ConsoleOut, {{"^BM_label %console_report some label$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_label\",$"}, + {"\"run_name\": \"BM_label\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -149,6 +165,8 @@ void BM_error(benchmark::State& state) { BENCHMARK(BM_error); ADD_CASES(TC_ConsoleOut, {{"^BM_error[ ]+ERROR OCCURRED: 'message'$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_error\",$"}, + {"\"run_name\": \"BM_error\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"error_occurred\": true,$", MR_Next}, {"\"error_message\": \"message\",$", MR_Next}}); @@ -165,7 +183,9 @@ void BM_no_arg_name(benchmark::State& state) { } BENCHMARK(BM_no_arg_name)->Arg(3); ADD_CASES(TC_ConsoleOut, {{"^BM_no_arg_name/3 %console_report$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_no_arg_name/3\",$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_no_arg_name/3\",$"}, + {"\"run_name\": \"BM_no_arg_name/3\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_no_arg_name/3\",%csv_report$"}}); // ========================================================================= // @@ -178,7 +198,9 @@ void BM_arg_name(benchmark::State& state) { } BENCHMARK(BM_arg_name)->ArgName("first")->Arg(3); ADD_CASES(TC_ConsoleOut, {{"^BM_arg_name/first:3 %console_report$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_arg_name/first:3\",$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_arg_name/first:3\",$"}, + {"\"run_name\": \"BM_arg_name/first:3\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_arg_name/first:3\",%csv_report$"}}); // ========================================================================= // @@ -192,10 +214,25 @@ void BM_arg_names(benchmark::State& state) { BENCHMARK(BM_arg_names)->Args({2, 5, 4})->ArgNames({"first", "", "third"}); ADD_CASES(TC_ConsoleOut, {{"^BM_arg_names/first:2/5/third:4 %console_report$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_arg_names/first:2/5/third:4\",$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_arg_names/first:2/5/third:4\",$"}, + {"\"run_name\": \"BM_arg_names/first:2/5/third:4\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_arg_names/first:2/5/third:4\",%csv_report$"}}); // ========================================================================= // +// ------------------------ Testing Big Args Output ------------------------ // +// ========================================================================= // + +void BM_BigArgs(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_BigArgs)->RangeMultiplier(2)->Range(1U << 30U, 1U << 31U); +ADD_CASES(TC_ConsoleOut, {{"^BM_BigArgs/1073741824 %console_report$"}, + {"^BM_BigArgs/2147483648 %console_report$"}}); + +// ========================================================================= // // ----------------------- Testing Complexity Output ----------------------- // // ========================================================================= // @@ -221,16 +258,33 @@ void BM_Repeat(benchmark::State& state) { } // need two repetitions min to be able to output any aggregate output BENCHMARK(BM_Repeat)->Repetitions(2); -ADD_CASES(TC_ConsoleOut, {{"^BM_Repeat/repeats:2 %console_report$"}, - {"^BM_Repeat/repeats:2 %console_report$"}, - {"^BM_Repeat/repeats:2_mean %console_report$"}, - {"^BM_Repeat/repeats:2_median %console_report$"}, - {"^BM_Repeat/repeats:2_stddev %console_report$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_Repeat/repeats:2 %console_report$"}, + {"^BM_Repeat/repeats:2 %console_report$"}, + {"^BM_Repeat/repeats:2_mean %console_time_only_report [ ]*2$"}, + {"^BM_Repeat/repeats:2_median %console_time_only_report [ ]*2$"}, + {"^BM_Repeat/repeats:2_stddev %console_time_only_report [ ]*2$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:2\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:2\"", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:2\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:2_mean\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:2_median\",$"}, - {"\"name\": \"BM_Repeat/repeats:2_stddev\",$"}}); + {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}, + {"\"name\": \"BM_Repeat/repeats:2_stddev\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:2\",%csv_report$"}, {"^\"BM_Repeat/repeats:2\",%csv_report$"}, {"^\"BM_Repeat/repeats:2_mean\",%csv_report$"}, @@ -238,18 +292,37 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:2\",%csv_report$"}, {"^\"BM_Repeat/repeats:2_stddev\",%csv_report$"}}); // but for two repetitions, mean and median is the same, so let's repeat.. BENCHMARK(BM_Repeat)->Repetitions(3); -ADD_CASES(TC_ConsoleOut, {{"^BM_Repeat/repeats:3 %console_report$"}, - {"^BM_Repeat/repeats:3 %console_report$"}, - {"^BM_Repeat/repeats:3 %console_report$"}, - {"^BM_Repeat/repeats:3_mean %console_report$"}, - {"^BM_Repeat/repeats:3_median %console_report$"}, - {"^BM_Repeat/repeats:3_stddev %console_report$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_Repeat/repeats:3 %console_report$"}, + {"^BM_Repeat/repeats:3 %console_report$"}, + {"^BM_Repeat/repeats:3 %console_report$"}, + {"^BM_Repeat/repeats:3_mean %console_time_only_report [ ]*3$"}, + {"^BM_Repeat/repeats:3_median %console_time_only_report [ ]*3$"}, + {"^BM_Repeat/repeats:3_stddev %console_time_only_report [ ]*3$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:3\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3_mean\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3_median\",$"}, - {"\"name\": \"BM_Repeat/repeats:3_stddev\",$"}}); + {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"name\": \"BM_Repeat/repeats:3_stddev\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:3\",%csv_report$"}, {"^\"BM_Repeat/repeats:3\",%csv_report$"}, {"^\"BM_Repeat/repeats:3\",%csv_report$"}, @@ -258,20 +331,41 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:3\",%csv_report$"}, {"^\"BM_Repeat/repeats:3_stddev\",%csv_report$"}}); // median differs between even/odd number of repetitions, so just to be sure BENCHMARK(BM_Repeat)->Repetitions(4); -ADD_CASES(TC_ConsoleOut, {{"^BM_Repeat/repeats:4 %console_report$"}, - {"^BM_Repeat/repeats:4 %console_report$"}, - {"^BM_Repeat/repeats:4 %console_report$"}, - {"^BM_Repeat/repeats:4 %console_report$"}, - {"^BM_Repeat/repeats:4_mean %console_report$"}, - {"^BM_Repeat/repeats:4_median %console_report$"}, - {"^BM_Repeat/repeats:4_stddev %console_report$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_Repeat/repeats:4 %console_report$"}, + {"^BM_Repeat/repeats:4 %console_report$"}, + {"^BM_Repeat/repeats:4 %console_report$"}, + {"^BM_Repeat/repeats:4 %console_report$"}, + {"^BM_Repeat/repeats:4_mean %console_time_only_report [ ]*4$"}, + {"^BM_Repeat/repeats:4_median %console_time_only_report [ ]*4$"}, + {"^BM_Repeat/repeats:4_stddev %console_time_only_report [ ]*4$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4_mean\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 4,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4_median\",$"}, - {"\"name\": \"BM_Repeat/repeats:4_stddev\",$"}}); + {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 4,$", MR_Next}, + {"\"name\": \"BM_Repeat/repeats:4_stddev\",$"}, + {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 4,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:4\",%csv_report$"}, {"^\"BM_Repeat/repeats:4\",%csv_report$"}, {"^\"BM_Repeat/repeats:4\",%csv_report$"}, @@ -288,7 +382,9 @@ void BM_RepeatOnce(benchmark::State& state) { } BENCHMARK(BM_RepeatOnce)->Repetitions(1)->ReportAggregatesOnly(); ADD_CASES(TC_ConsoleOut, {{"^BM_RepeatOnce/repeats:1 %console_report$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_RepeatOnce/repeats:1\",$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_RepeatOnce/repeats:1\",$"}, + {"\"run_name\": \"BM_RepeatOnce/repeats:1\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_RepeatOnce/repeats:1\",%csv_report$"}}); // Test that non-aggregate data is not reported @@ -297,20 +393,72 @@ void BM_SummaryRepeat(benchmark::State& state) { } } BENCHMARK(BM_SummaryRepeat)->Repetitions(3)->ReportAggregatesOnly(); -ADD_CASES(TC_ConsoleOut, +ADD_CASES( + TC_ConsoleOut, + {{".*BM_SummaryRepeat/repeats:3 ", MR_Not}, + {"^BM_SummaryRepeat/repeats:3_mean %console_time_only_report [ ]*3$"}, + {"^BM_SummaryRepeat/repeats:3_median %console_time_only_report [ ]*3$"}, + {"^BM_SummaryRepeat/repeats:3_stddev %console_time_only_report [ ]*3$"}}); +ADD_CASES(TC_JSONOut, {{".*BM_SummaryRepeat/repeats:3 ", MR_Not}, - {"^BM_SummaryRepeat/repeats:3_mean %console_report$"}, - {"^BM_SummaryRepeat/repeats:3_median %console_report$"}, - {"^BM_SummaryRepeat/repeats:3_stddev %console_report$"}}); -ADD_CASES(TC_JSONOut, {{".*BM_SummaryRepeat/repeats:3 ", MR_Not}, - {"\"name\": \"BM_SummaryRepeat/repeats:3_mean\",$"}, - {"\"name\": \"BM_SummaryRepeat/repeats:3_median\",$"}, - {"\"name\": \"BM_SummaryRepeat/repeats:3_stddev\",$"}}); + {"\"name\": \"BM_SummaryRepeat/repeats:3_mean\",$"}, + {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"name\": \"BM_SummaryRepeat/repeats:3_median\",$"}, + {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"name\": \"BM_SummaryRepeat/repeats:3_stddev\",$"}, + {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{".*BM_SummaryRepeat/repeats:3 ", MR_Not}, {"^\"BM_SummaryRepeat/repeats:3_mean\",%csv_report$"}, {"^\"BM_SummaryRepeat/repeats:3_median\",%csv_report$"}, {"^\"BM_SummaryRepeat/repeats:3_stddev\",%csv_report$"}}); +// Test that non-aggregate data is not displayed. +// NOTE: this test is kinda bad. we are only testing the display output. +// But we don't check that the file output still contains everything... +void BM_SummaryDisplay(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_SummaryDisplay)->Repetitions(2)->DisplayAggregatesOnly(); +ADD_CASES( + TC_ConsoleOut, + {{".*BM_SummaryDisplay/repeats:2 ", MR_Not}, + {"^BM_SummaryDisplay/repeats:2_mean %console_time_only_report [ ]*2$"}, + {"^BM_SummaryDisplay/repeats:2_median %console_time_only_report [ ]*2$"}, + {"^BM_SummaryDisplay/repeats:2_stddev %console_time_only_report [ ]*2$"}}); +ADD_CASES(TC_JSONOut, + {{".*BM_SummaryDisplay/repeats:2 ", MR_Not}, + {"\"name\": \"BM_SummaryDisplay/repeats:2_mean\",$"}, + {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}, + {"\"name\": \"BM_SummaryDisplay/repeats:2_median\",$"}, + {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}, + {"\"name\": \"BM_SummaryDisplay/repeats:2_stddev\",$"}, + {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}}); +ADD_CASES(TC_CSVOut, + {{".*BM_SummaryDisplay/repeats:2 ", MR_Not}, + {"^\"BM_SummaryDisplay/repeats:2_mean\",%csv_report$"}, + {"^\"BM_SummaryDisplay/repeats:2_median\",%csv_report$"}, + {"^\"BM_SummaryDisplay/repeats:2_stddev\",%csv_report$"}}); + +// Test repeats with custom time unit. void BM_RepeatTimeUnit(benchmark::State& state) { for (auto _ : state) { } @@ -319,18 +467,34 @@ BENCHMARK(BM_RepeatTimeUnit) ->Repetitions(3) ->ReportAggregatesOnly() ->Unit(benchmark::kMicrosecond); -ADD_CASES(TC_ConsoleOut, +ADD_CASES( + TC_ConsoleOut, + {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not}, + {"^BM_RepeatTimeUnit/repeats:3_mean %console_us_time_only_report [ ]*3$"}, + {"^BM_RepeatTimeUnit/repeats:3_median %console_us_time_only_report [ " + "]*3$"}, + {"^BM_RepeatTimeUnit/repeats:3_stddev %console_us_time_only_report [ " + "]*3$"}}); +ADD_CASES(TC_JSONOut, {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not}, - {"^BM_RepeatTimeUnit/repeats:3_mean %console_us_report$"}, - {"^BM_RepeatTimeUnit/repeats:3_median %console_us_report$"}, - {"^BM_RepeatTimeUnit/repeats:3_stddev %console_us_report$"}}); -ADD_CASES(TC_JSONOut, {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not}, - {"\"name\": \"BM_RepeatTimeUnit/repeats:3_mean\",$"}, - {"\"time_unit\": \"us\",?$"}, - {"\"name\": \"BM_RepeatTimeUnit/repeats:3_median\",$"}, - {"\"time_unit\": \"us\",?$"}, - {"\"name\": \"BM_RepeatTimeUnit/repeats:3_stddev\",$"}, - {"\"time_unit\": \"us\",?$"}}); + {"\"name\": \"BM_RepeatTimeUnit/repeats:3_mean\",$"}, + {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"time_unit\": \"us\",?$"}, + {"\"name\": \"BM_RepeatTimeUnit/repeats:3_median\",$"}, + {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"time_unit\": \"us\",?$"}, + {"\"name\": \"BM_RepeatTimeUnit/repeats:3_stddev\",$"}, + {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"time_unit\": \"us\",?$"}}); ADD_CASES(TC_CSVOut, {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not}, {"^\"BM_RepeatTimeUnit/repeats:3_mean\",%csv_us_report$"}, @@ -346,37 +510,92 @@ const auto UserStatistics = [](const std::vector<double>& v) { }; void BM_UserStats(benchmark::State& state) { for (auto _ : state) { + state.SetIterationTime(150 / 10e8); } } // clang-format off BENCHMARK(BM_UserStats) ->Repetitions(3) + ->Iterations(5) + ->UseManualTime() ->ComputeStatistics("", UserStatistics); // clang-format on // check that user-provided stats is calculated, and is after the default-ones // empty string as name is intentional, it would sort before anything else -ADD_CASES(TC_ConsoleOut, {{"^BM_UserStats/repeats:3 %console_report$"}, - {"^BM_UserStats/repeats:3 %console_report$"}, - {"^BM_UserStats/repeats:3 %console_report$"}, - {"^BM_UserStats/repeats:3_mean %console_report$"}, - {"^BM_UserStats/repeats:3_median %console_report$"}, - {"^BM_UserStats/repeats:3_stddev %console_report$"}, - {"^BM_UserStats/repeats:3_ %console_report$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_UserStats/repeats:3\",$"}, - {"\"name\": \"BM_UserStats/repeats:3\",$"}, - {"\"name\": \"BM_UserStats/repeats:3\",$"}, - {"\"name\": \"BM_UserStats/repeats:3_mean\",$"}, - {"\"name\": \"BM_UserStats/repeats:3_median\",$"}, - {"\"name\": \"BM_UserStats/repeats:3_stddev\",$"}, - {"\"name\": \"BM_UserStats/repeats:3_\",$"}}); -ADD_CASES(TC_CSVOut, {{"^\"BM_UserStats/repeats:3\",%csv_report$"}, - {"^\"BM_UserStats/repeats:3\",%csv_report$"}, - {"^\"BM_UserStats/repeats:3\",%csv_report$"}, - {"^\"BM_UserStats/repeats:3_mean\",%csv_report$"}, - {"^\"BM_UserStats/repeats:3_median\",%csv_report$"}, - {"^\"BM_UserStats/repeats:3_stddev\",%csv_report$"}, - {"^\"BM_UserStats/repeats:3_\",%csv_report$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_UserStats/iterations:5/repeats:3/manual_time [ " + "]* 150 ns %time [ ]*5$"}, + {"^BM_UserStats/iterations:5/repeats:3/manual_time [ " + "]* 150 ns %time [ ]*5$"}, + {"^BM_UserStats/iterations:5/repeats:3/manual_time [ " + "]* 150 ns %time [ ]*5$"}, + {"^BM_UserStats/iterations:5/repeats:3/" + "manual_time_mean [ ]* 150 ns %time [ ]*3$"}, + {"^BM_UserStats/iterations:5/repeats:3/" + "manual_time_median [ ]* 150 ns %time [ ]*3$"}, + {"^BM_UserStats/iterations:5/repeats:3/" + "manual_time_stddev [ ]* 0.000 ns %time [ ]*3$"}, + {"^BM_UserStats/iterations:5/repeats:3/manual_time_ " + "[ ]* 150 ns %time [ ]*3$"}}); +ADD_CASES( + TC_JSONOut, + {{"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"}, + {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": 5,$", MR_Next}, + {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, + {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"}, + {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": 5,$", MR_Next}, + {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, + {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"}, + {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": 5,$", MR_Next}, + {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, + {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_mean\",$"}, + {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, + {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_median\",$"}, + {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, + {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_stddev\",$"}, + {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_\",$"}, + {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"\",$", MR_Next}, + {"\"iterations\": 3,$", MR_Next}, + {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}}); +ADD_CASES( + TC_CSVOut, + {{"^\"BM_UserStats/iterations:5/repeats:3/manual_time\",%csv_report$"}, + {"^\"BM_UserStats/iterations:5/repeats:3/manual_time\",%csv_report$"}, + {"^\"BM_UserStats/iterations:5/repeats:3/manual_time\",%csv_report$"}, + {"^\"BM_UserStats/iterations:5/repeats:3/manual_time_mean\",%csv_report$"}, + {"^\"BM_UserStats/iterations:5/repeats:3/" + "manual_time_median\",%csv_report$"}, + {"^\"BM_UserStats/iterations:5/repeats:3/" + "manual_time_stddev\",%csv_report$"}, + {"^\"BM_UserStats/iterations:5/repeats:3/manual_time_\",%csv_report$"}}); // ========================================================================= // // --------------------------- TEST CASES END ------------------------------ // diff --git a/lib/libcxx/utils/google-benchmark/test/skip_with_error_test.cc b/lib/libcxx/utils/google-benchmark/test/skip_with_error_test.cc index 39785fb7f6d..06579772ff7 100644 --- a/lib/libcxx/utils/google-benchmark/test/skip_with_error_test.cc +++ b/lib/libcxx/utils/google-benchmark/test/skip_with_error_test.cc @@ -33,8 +33,8 @@ struct TestCase { typedef benchmark::BenchmarkReporter::Run Run; void CheckRun(Run const& run) const { - CHECK(name == run.benchmark_name) - << "expected " << name << " got " << run.benchmark_name; + CHECK(name == run.benchmark_name()) + << "expected " << name << " got " << run.benchmark_name(); CHECK(error_occurred == run.error_occurred); CHECK(error_message == run.error_message); if (error_occurred) { diff --git a/lib/libcxx/utils/google-benchmark/test/string_util_gtest.cc b/lib/libcxx/utils/google-benchmark/test/string_util_gtest.cc index 4c81734cf8a..2c5d073f613 100644 --- a/lib/libcxx/utils/google-benchmark/test/string_util_gtest.cc +++ b/lib/libcxx/utils/google-benchmark/test/string_util_gtest.cc @@ -9,56 +9,56 @@ namespace { TEST(StringUtilTest, stoul) { { size_t pos = 0; - EXPECT_EQ(0, benchmark::stoul("0", &pos)); - EXPECT_EQ(1, pos); + EXPECT_EQ(0ul, benchmark::stoul("0", &pos)); + EXPECT_EQ(1ul, pos); } { size_t pos = 0; - EXPECT_EQ(7, benchmark::stoul("7", &pos)); - EXPECT_EQ(1, pos); + EXPECT_EQ(7ul, benchmark::stoul("7", &pos)); + EXPECT_EQ(1ul, pos); } { size_t pos = 0; - EXPECT_EQ(135, benchmark::stoul("135", &pos)); - EXPECT_EQ(3, pos); + EXPECT_EQ(135ul, benchmark::stoul("135", &pos)); + EXPECT_EQ(3ul, pos); } #if ULONG_MAX == 0xFFFFFFFFul { size_t pos = 0; EXPECT_EQ(0xFFFFFFFFul, benchmark::stoul("4294967295", &pos)); - EXPECT_EQ(10, pos); + EXPECT_EQ(10ul, pos); } #elif ULONG_MAX == 0xFFFFFFFFFFFFFFFFul { size_t pos = 0; EXPECT_EQ(0xFFFFFFFFFFFFFFFFul, benchmark::stoul("18446744073709551615", &pos)); - EXPECT_EQ(20, pos); + EXPECT_EQ(20ul, pos); } #endif { size_t pos = 0; - EXPECT_EQ(10, benchmark::stoul("1010", &pos, 2)); - EXPECT_EQ(4, pos); + EXPECT_EQ(10ul, benchmark::stoul("1010", &pos, 2)); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; - EXPECT_EQ(520, benchmark::stoul("1010", &pos, 8)); - EXPECT_EQ(4, pos); + EXPECT_EQ(520ul, benchmark::stoul("1010", &pos, 8)); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; - EXPECT_EQ(1010, benchmark::stoul("1010", &pos, 10)); - EXPECT_EQ(4, pos); + EXPECT_EQ(1010ul, benchmark::stoul("1010", &pos, 10)); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; - EXPECT_EQ(4112, benchmark::stoul("1010", &pos, 16)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4112ul, benchmark::stoul("1010", &pos, 16)); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; - EXPECT_EQ(0xBEEF, benchmark::stoul("BEEF", &pos, 16)); - EXPECT_EQ(4, pos); + EXPECT_EQ(0xBEEFul, benchmark::stoul("BEEF", &pos, 16)); + EXPECT_EQ(4ul, pos); } { ASSERT_THROW(benchmark::stoul("this is a test"), std::invalid_argument); @@ -69,42 +69,42 @@ TEST(StringUtilTest, stoi) { { size_t pos = 0; EXPECT_EQ(0, benchmark::stoi("0", &pos)); - EXPECT_EQ(1, pos); + EXPECT_EQ(1ul, pos); } { size_t pos = 0; EXPECT_EQ(-17, benchmark::stoi("-17", &pos)); - EXPECT_EQ(3, pos); + EXPECT_EQ(3ul, pos); } { size_t pos = 0; EXPECT_EQ(1357, benchmark::stoi("1357", &pos)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; EXPECT_EQ(10, benchmark::stoi("1010", &pos, 2)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; EXPECT_EQ(520, benchmark::stoi("1010", &pos, 8)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; EXPECT_EQ(1010, benchmark::stoi("1010", &pos, 10)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; EXPECT_EQ(4112, benchmark::stoi("1010", &pos, 16)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; EXPECT_EQ(0xBEEF, benchmark::stoi("BEEF", &pos, 16)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4ul, pos); } { ASSERT_THROW(benchmark::stoi("this is a test"), std::invalid_argument); @@ -115,28 +115,28 @@ TEST(StringUtilTest, stod) { { size_t pos = 0; EXPECT_EQ(0.0, benchmark::stod("0", &pos)); - EXPECT_EQ(1, pos); + EXPECT_EQ(1ul, pos); } { size_t pos = 0; EXPECT_EQ(-84.0, benchmark::stod("-84", &pos)); - EXPECT_EQ(3, pos); + EXPECT_EQ(3ul, pos); } { size_t pos = 0; EXPECT_EQ(1234.0, benchmark::stod("1234", &pos)); - EXPECT_EQ(4, pos); + EXPECT_EQ(4ul, pos); } { size_t pos = 0; EXPECT_EQ(1.5, benchmark::stod("1.5", &pos)); - EXPECT_EQ(3, pos); + EXPECT_EQ(3ul, pos); } { size_t pos = 0; /* Note: exactly representable as double */ EXPECT_EQ(-1.25e+9, benchmark::stod("-1.25e+9", &pos)); - EXPECT_EQ(8, pos); + EXPECT_EQ(8ul, pos); } { ASSERT_THROW(benchmark::stod("this is a test"), std::invalid_argument); diff --git a/lib/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc b/lib/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc index 4f126b6d978..030e98916c3 100644 --- a/lib/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc +++ b/lib/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc @@ -69,18 +69,21 @@ void BM_Counters_Tabular(benchmark::State& state) { }); } BENCHMARK(BM_Counters_Tabular)->ThreadRange(1, 16); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Tabular/threads:%int\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"Bar\": %float,$", MR_Next}, - {"\"Bat\": %float,$", MR_Next}, - {"\"Baz\": %float,$", MR_Next}, - {"\"Foo\": %float,$", MR_Next}, - {"\"Frob\": %float,$", MR_Next}, - {"\"Lob\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/threads:%int\",$"}, + {"\"run_name\": \"BM_Counters_Tabular/threads:%int\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Tabular/threads:%int\",%csv_report," "%float,%float,%float,%float,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument @@ -113,18 +116,22 @@ void BM_CounterRates_Tabular(benchmark::State& state) { }); } BENCHMARK(BM_CounterRates_Tabular)->ThreadRange(1, 16); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterRates_Tabular/threads:%int\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"Bar\": %float,$", MR_Next}, - {"\"Bat\": %float,$", MR_Next}, - {"\"Baz\": %float,$", MR_Next}, - {"\"Foo\": %float,$", MR_Next}, - {"\"Frob\": %float,$", MR_Next}, - {"\"Lob\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_CounterRates_Tabular/threads:%int\",$"}, + {"\"run_name\": \"BM_CounterRates_Tabular/threads:%int\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_CounterRates_Tabular/threads:%int\",%csv_report," "%float,%float,%float,%float,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument @@ -157,15 +164,18 @@ void BM_CounterSet0_Tabular(benchmark::State& state) { }); } BENCHMARK(BM_CounterSet0_Tabular)->ThreadRange(1, 16); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterSet0_Tabular/threads:%int\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"Bar\": %float,$", MR_Next}, - {"\"Baz\": %float,$", MR_Next}, - {"\"Foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_CounterSet0_Tabular/threads:%int\",$"}, + {"\"run_name\": \"BM_CounterSet0_Tabular/threads:%int\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_CounterSet0_Tabular/threads:%int\",%csv_report," "%float,,%float,%float,,"}}); // VS2013 does not allow this function to be passed as a lambda argument @@ -189,15 +199,18 @@ void BM_CounterSet1_Tabular(benchmark::State& state) { }); } BENCHMARK(BM_CounterSet1_Tabular)->ThreadRange(1, 16); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterSet1_Tabular/threads:%int\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"Bar\": %float,$", MR_Next}, - {"\"Baz\": %float,$", MR_Next}, - {"\"Foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_CounterSet1_Tabular/threads:%int\",$"}, + {"\"run_name\": \"BM_CounterSet1_Tabular/threads:%int\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_CounterSet1_Tabular/threads:%int\",%csv_report," "%float,,%float,%float,,"}}); // VS2013 does not allow this function to be passed as a lambda argument @@ -225,15 +238,18 @@ void BM_CounterSet2_Tabular(benchmark::State& state) { }); } BENCHMARK(BM_CounterSet2_Tabular)->ThreadRange(1, 16); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterSet2_Tabular/threads:%int\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"Bat\": %float,$", MR_Next}, - {"\"Baz\": %float,$", MR_Next}, - {"\"Foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_CounterSet2_Tabular/threads:%int\",$"}, + {"\"run_name\": \"BM_CounterSet2_Tabular/threads:%int\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_CounterSet2_Tabular/threads:%int\",%csv_report," ",%float,%float,%float,,"}}); // VS2013 does not allow this function to be passed as a lambda argument diff --git a/lib/libcxx/utils/google-benchmark/test/user_counters_test.cc b/lib/libcxx/utils/google-benchmark/test/user_counters_test.cc index 7f7ccb9f77a..bb0d6b4c5a9 100644 --- a/lib/libcxx/utils/google-benchmark/test/user_counters_test.cc +++ b/lib/libcxx/utils/google-benchmark/test/user_counters_test.cc @@ -32,6 +32,8 @@ BENCHMARK(BM_Counters_Simple); ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_Simple %console_report bar=%hrfloat foo=%hrfloat$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Simple\",$"}, + {"\"run_name\": \"BM_Counters_Simple\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -66,19 +68,22 @@ void BM_Counters_WithBytesAndItemsPSec(benchmark::State& state) { state.SetItemsProcessed(150); } BENCHMARK(BM_Counters_WithBytesAndItemsPSec); -ADD_CASES(TC_ConsoleOut, - {{"^BM_Counters_WithBytesAndItemsPSec %console_report " - "bar=%hrfloat foo=%hrfloat +%hrfloatB/s +%hrfloat items/s$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_WithBytesAndItemsPSec\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"bytes_per_second\": %float,$", MR_Next}, - {"\"items_per_second\": %float,$", MR_Next}, - {"\"bar\": %float,$", MR_Next}, - {"\"foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_WithBytesAndItemsPSec %console_report " + "bar=%hrfloat bytes_per_second=%hrfloat/s " + "foo=%hrfloat items_per_second=%hrfloat/s$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_WithBytesAndItemsPSec\",$"}, + {"\"run_name\": \"BM_Counters_WithBytesAndItemsPSec\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"bytes_per_second\": %float,$", MR_Next}, + {"\"foo\": %float,$", MR_Next}, + {"\"items_per_second\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_WithBytesAndItemsPSec\"," "%csv_bytes_items_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument @@ -110,6 +115,8 @@ ADD_CASES( TC_ConsoleOut, {{"^BM_Counters_Rate %console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Rate\",$"}, + {"\"run_name\": \"BM_Counters_Rate\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -141,14 +148,17 @@ void BM_Counters_Threads(benchmark::State& state) { BENCHMARK(BM_Counters_Threads)->ThreadRange(1, 8); ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_Threads/threads:%int %console_report " "bar=%hrfloat foo=%hrfloat$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Threads/threads:%int\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"bar\": %float,$", MR_Next}, - {"\"foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Threads/threads:%int\",$"}, + {"\"run_name\": \"BM_Counters_Threads/threads:%int\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES( TC_CSVOut, {{"^\"BM_Counters_Threads/threads:%int\",%csv_report,%float,%float$"}}); @@ -174,14 +184,17 @@ void BM_Counters_AvgThreads(benchmark::State& state) { BENCHMARK(BM_Counters_AvgThreads)->ThreadRange(1, 8); ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgThreads/threads:%int " "%console_report bar=%hrfloat foo=%hrfloat$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgThreads/threads:%int\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"bar\": %float,$", MR_Next}, - {"\"foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_AvgThreads/threads:%int\",$"}, + {"\"run_name\": \"BM_Counters_AvgThreads/threads:%int\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES( TC_CSVOut, {{"^\"BM_Counters_AvgThreads/threads:%int\",%csv_report,%float,%float$"}}); @@ -210,6 +223,9 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgThreadsRate/threads:%int " "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgThreadsRate/threads:%int\",$"}, + {"\"run_name\": \"BM_Counters_AvgThreadsRate/threads:%int\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -242,14 +258,17 @@ void BM_Counters_IterationInvariant(benchmark::State& state) { BENCHMARK(BM_Counters_IterationInvariant); ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_IterationInvariant %console_report " "bar=%hrfloat foo=%hrfloat$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_IterationInvariant\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"bar\": %float,$", MR_Next}, - {"\"foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_IterationInvariant\",$"}, + {"\"run_name\": \"BM_Counters_IterationInvariant\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_IterationInvariant\",%csv_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument @@ -281,6 +300,9 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_kIsIterationInvariantRate " "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_kIsIterationInvariantRate\",$"}, + {"\"run_name\": \"BM_Counters_kIsIterationInvariantRate\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -316,14 +338,17 @@ void BM_Counters_AvgIterations(benchmark::State& state) { BENCHMARK(BM_Counters_AvgIterations); ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgIterations %console_report " "bar=%hrfloat foo=%hrfloat$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgIterations\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"bar\": %float,$", MR_Next}, - {"\"foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_AvgIterations\",$"}, + {"\"run_name\": \"BM_Counters_AvgIterations\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_AvgIterations\",%csv_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument @@ -351,14 +376,17 @@ void BM_Counters_kAvgIterationsRate(benchmark::State& state) { BENCHMARK(BM_Counters_kAvgIterationsRate); ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_kAvgIterationsRate " "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); -ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_kAvgIterationsRate\",$"}, - {"\"iterations\": %int,$", MR_Next}, - {"\"real_time\": %float,$", MR_Next}, - {"\"cpu_time\": %float,$", MR_Next}, - {"\"time_unit\": \"ns\",$", MR_Next}, - {"\"bar\": %float,$", MR_Next}, - {"\"foo\": %float$", MR_Next}, - {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_kAvgIterationsRate\",$"}, + {"\"run_name\": \"BM_Counters_kAvgIterationsRate\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"foo\": %float$", MR_Next}, + {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_kAvgIterationsRate\",%csv_report," "%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument diff --git a/lib/libcxx/utils/google-benchmark/test/user_counters_thousands_test.cc b/lib/libcxx/utils/google-benchmark/test/user_counters_thousands_test.cc new file mode 100644 index 00000000000..fa0ef972047 --- /dev/null +++ b/lib/libcxx/utils/google-benchmark/test/user_counters_thousands_test.cc @@ -0,0 +1,161 @@ + +#undef NDEBUG + +#include "benchmark/benchmark.h" +#include "output_test.h" + +// ========================================================================= // +// ------------------------ Thousands Customisation ------------------------ // +// ========================================================================= // + +void BM_Counters_Thousands(benchmark::State& state) { + for (auto _ : state) { + } + namespace bm = benchmark; + state.counters.insert({ + {"t0_1000000DefaultBase", + bm::Counter(1000 * 1000, bm::Counter::kDefaults)}, + {"t1_1000000Base1000", bm::Counter(1000 * 1000, bm::Counter::kDefaults, + benchmark::Counter::OneK::kIs1000)}, + {"t2_1000000Base1024", bm::Counter(1000 * 1000, bm::Counter::kDefaults, + benchmark::Counter::OneK::kIs1024)}, + {"t3_1048576Base1000", bm::Counter(1024 * 1024, bm::Counter::kDefaults, + benchmark::Counter::OneK::kIs1000)}, + {"t4_1048576Base1024", bm::Counter(1024 * 1024, bm::Counter::kDefaults, + benchmark::Counter::OneK::kIs1024)}, + }); +} +BENCHMARK(BM_Counters_Thousands)->Repetitions(2); +ADD_CASES( + TC_ConsoleOut, + { + {"^BM_Counters_Thousands/repeats:2 %console_report " + "t0_1000000DefaultBase=1000k " + "t1_1000000Base1000=1000k t2_1000000Base1024=976.56[23]k " + "t3_1048576Base1000=1048.58k t4_1048576Base1024=1024k$"}, + {"^BM_Counters_Thousands/repeats:2 %console_report " + "t0_1000000DefaultBase=1000k " + "t1_1000000Base1000=1000k t2_1000000Base1024=976.56[23]k " + "t3_1048576Base1000=1048.58k t4_1048576Base1024=1024k$"}, + {"^BM_Counters_Thousands/repeats:2_mean %console_report " + "t0_1000000DefaultBase=1000k t1_1000000Base1000=1000k " + "t2_1000000Base1024=976.56[23]k t3_1048576Base1000=1048.58k " + "t4_1048576Base1024=1024k$"}, + {"^BM_Counters_Thousands/repeats:2_median %console_report " + "t0_1000000DefaultBase=1000k t1_1000000Base1000=1000k " + "t2_1000000Base1024=976.56[23]k t3_1048576Base1000=1048.58k " + "t4_1048576Base1024=1024k$"}, + {"^BM_Counters_Thousands/repeats:2_stddev %console_time_only_report [ " + "]*2 t0_1000000DefaultBase=0 t1_1000000Base1000=0 " + "t2_1000000Base1024=0 t3_1048576Base1000=0 t4_1048576Base1024=0$"}, + }); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Thousands/repeats:2\",$"}, + {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next}, + {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Thousands/repeats:2\",$"}, + {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next}, + {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Thousands/repeats:2_mean\",$"}, + {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next}, + {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Thousands/repeats:2_median\",$"}, + {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next}, + {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next}, + {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Thousands/repeats:2_stddev\",$"}, + {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": 2,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"t0_1000000DefaultBase\": 0\\.(0)*e\\+(0)*,$", MR_Next}, + {"\"t1_1000000Base1000\": 0\\.(0)*e\\+(0)*,$", MR_Next}, + {"\"t2_1000000Base1024\": 0\\.(0)*e\\+(0)*,$", MR_Next}, + {"\"t3_1048576Base1000\": 0\\.(0)*e\\+(0)*,$", MR_Next}, + {"\"t4_1048576Base1024\": 0\\.(0)*e\\+(0)*$", MR_Next}, + {"}", MR_Next}}); + +ADD_CASES( + TC_CSVOut, + {{"^\"BM_Counters_Thousands/" + "repeats:2\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\.04858e\\+(" + "0)*6,1\\.04858e\\+(0)*6$"}, + {"^\"BM_Counters_Thousands/" + "repeats:2\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\.04858e\\+(" + "0)*6,1\\.04858e\\+(0)*6$"}, + {"^\"BM_Counters_Thousands/" + "repeats:2_mean\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\." + "04858e\\+(0)*6,1\\.04858e\\+(0)*6$"}, + {"^\"BM_Counters_Thousands/" + "repeats:2_median\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\." + "04858e\\+(0)*6,1\\.04858e\\+(0)*6$"}, + {"^\"BM_Counters_Thousands/repeats:2_stddev\",%csv_report,0,0,0,0,0$"}}); +// VS2013 does not allow this function to be passed as a lambda argument +// to CHECK_BENCHMARK_RESULTS() +void CheckThousands(Results const& e) { + if (e.name != "BM_Counters_Thousands/repeats:2") + return; // Do not check the aggregates! + + // check that the values are within 0.01% of the expected values + CHECK_FLOAT_COUNTER_VALUE(e, "t0_1000000DefaultBase", EQ, 1000 * 1000, + 0.0001); + CHECK_FLOAT_COUNTER_VALUE(e, "t1_1000000Base1000", EQ, 1000 * 1000, 0.0001); + CHECK_FLOAT_COUNTER_VALUE(e, "t2_1000000Base1024", EQ, 1000 * 1000, 0.0001); + CHECK_FLOAT_COUNTER_VALUE(e, "t3_1048576Base1000", EQ, 1024 * 1024, 0.0001); + CHECK_FLOAT_COUNTER_VALUE(e, "t4_1048576Base1024", EQ, 1024 * 1024, 0.0001); +} +CHECK_BENCHMARK_RESULTS("BM_Counters_Thousands", &CheckThousands); + +// ========================================================================= // +// --------------------------- TEST CASES END ------------------------------ // +// ========================================================================= // + +int main(int argc, char* argv[]) { RunOutputTests(argc, argv); } diff --git a/lib/libcxx/utils/google-benchmark/tools/compare.py b/lib/libcxx/utils/google-benchmark/tools/compare.py index d27e24b3492..539ace6fb16 100755 --- a/lib/libcxx/utils/google-benchmark/tools/compare.py +++ b/lib/libcxx/utils/google-benchmark/tools/compare.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import unittest """ compare.py - versatile benchmark output compare tool """ @@ -36,6 +37,17 @@ def create_parser(): parser = ArgumentParser( description='versatile benchmark output compare tool') + parser.add_argument( + '-a', + '--display_aggregates_only', + dest='display_aggregates_only', + action="store_true", + help="If there are repetitions, by default, we display everything - the" + " actual runs, and the aggregates computed. Sometimes, it is " + "desirable to only view the aggregates. E.g. when there are a lot " + "of repetitions. Do note that only the display is affected. " + "Internally, all the actual runs are still used, e.g. for U test.") + utest = parser.add_argument_group() utest.add_argument( '--no-utest', @@ -200,6 +212,9 @@ def main(): check_inputs(test_baseline, test_contender, benchmark_options) + if args.display_aggregates_only: + benchmark_options += ['--benchmark_display_aggregates_only=true'] + options_baseline = [] options_contender = [] @@ -223,15 +238,13 @@ def main(): # Diff and output output_lines = gbench.report.generate_difference_report( - json1, json2, args.utest, args.utest_alpha) + json1, json2, args.display_aggregates_only, + args.utest, args.utest_alpha) print(description) for ln in output_lines: print(ln) -import unittest - - class TestParser(unittest.TestCase): def setUp(self): self.parser = create_parser() @@ -246,6 +259,7 @@ class TestParser(unittest.TestCase): def test_benchmarks_basic(self): parsed = self.parser.parse_args( ['benchmarks', self.testInput0, self.testInput1]) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarks') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) @@ -255,6 +269,7 @@ class TestParser(unittest.TestCase): def test_benchmarks_basic_without_utest(self): parsed = self.parser.parse_args( ['--no-utest', 'benchmarks', self.testInput0, self.testInput1]) + self.assertFalse(parsed.display_aggregates_only) self.assertFalse(parsed.utest) self.assertEqual(parsed.utest_alpha, 0.05) self.assertEqual(parsed.mode, 'benchmarks') @@ -262,9 +277,20 @@ class TestParser(unittest.TestCase): self.assertEqual(parsed.test_contender[0].name, self.testInput1) self.assertFalse(parsed.benchmark_options) + def test_benchmarks_basic_display_aggregates_only(self): + parsed = self.parser.parse_args( + ['-a', 'benchmarks', self.testInput0, self.testInput1]) + self.assertTrue(parsed.display_aggregates_only) + self.assertTrue(parsed.utest) + self.assertEqual(parsed.mode, 'benchmarks') + self.assertEqual(parsed.test_baseline[0].name, self.testInput0) + self.assertEqual(parsed.test_contender[0].name, self.testInput1) + self.assertFalse(parsed.benchmark_options) + def test_benchmarks_basic_with_utest_alpha(self): parsed = self.parser.parse_args( ['--alpha=0.314', 'benchmarks', self.testInput0, self.testInput1]) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.utest_alpha, 0.314) self.assertEqual(parsed.mode, 'benchmarks') @@ -275,6 +301,7 @@ class TestParser(unittest.TestCase): def test_benchmarks_basic_without_utest_with_utest_alpha(self): parsed = self.parser.parse_args( ['--no-utest', '--alpha=0.314', 'benchmarks', self.testInput0, self.testInput1]) + self.assertFalse(parsed.display_aggregates_only) self.assertFalse(parsed.utest) self.assertEqual(parsed.utest_alpha, 0.314) self.assertEqual(parsed.mode, 'benchmarks') @@ -285,6 +312,7 @@ class TestParser(unittest.TestCase): def test_benchmarks_with_remainder(self): parsed = self.parser.parse_args( ['benchmarks', self.testInput0, self.testInput1, 'd']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarks') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) @@ -294,6 +322,7 @@ class TestParser(unittest.TestCase): def test_benchmarks_with_remainder_after_doubleminus(self): parsed = self.parser.parse_args( ['benchmarks', self.testInput0, self.testInput1, '--', 'e']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarks') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) @@ -303,6 +332,7 @@ class TestParser(unittest.TestCase): def test_filters_basic(self): parsed = self.parser.parse_args( ['filters', self.testInput0, 'c', 'd']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'filters') self.assertEqual(parsed.test[0].name, self.testInput0) @@ -313,6 +343,7 @@ class TestParser(unittest.TestCase): def test_filters_with_remainder(self): parsed = self.parser.parse_args( ['filters', self.testInput0, 'c', 'd', 'e']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'filters') self.assertEqual(parsed.test[0].name, self.testInput0) @@ -323,6 +354,7 @@ class TestParser(unittest.TestCase): def test_filters_with_remainder_after_doubleminus(self): parsed = self.parser.parse_args( ['filters', self.testInput0, 'c', 'd', '--', 'f']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'filters') self.assertEqual(parsed.test[0].name, self.testInput0) @@ -333,6 +365,7 @@ class TestParser(unittest.TestCase): def test_benchmarksfiltered_basic(self): parsed = self.parser.parse_args( ['benchmarksfiltered', self.testInput0, 'c', self.testInput1, 'e']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarksfiltered') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) @@ -344,6 +377,7 @@ class TestParser(unittest.TestCase): def test_benchmarksfiltered_with_remainder(self): parsed = self.parser.parse_args( ['benchmarksfiltered', self.testInput0, 'c', self.testInput1, 'e', 'f']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarksfiltered') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) @@ -355,6 +389,7 @@ class TestParser(unittest.TestCase): def test_benchmarksfiltered_with_remainder_after_doubleminus(self): parsed = self.parser.parse_args( ['benchmarksfiltered', self.testInput0, 'c', self.testInput1, 'e', '--', 'g']) + self.assertFalse(parsed.display_aggregates_only) self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarksfiltered') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) diff --git a/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run0.json b/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run0.json index ca793f3367e..49f8b061437 100644 --- a/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run0.json +++ b/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run0.json @@ -9,6 +9,7 @@ "benchmarks": [ { "name": "BM_One", + "run_type": "aggregate", "iterations": 1000, "real_time": 10, "cpu_time": 100, @@ -25,15 +26,40 @@ "name": "BM_Two", "iterations": 1000, "real_time": 8, + "cpu_time": 86, + "time_unit": "ns" + }, + { + "name": "short", + "run_type": "aggregate", + "iterations": 1000, + "real_time": 8, "cpu_time": 80, "time_unit": "ns" }, { "name": "short", + "run_type": "aggregate", + "iterations": 1000, + "real_time": 8, + "cpu_time": 77, + "time_unit": "ns" + }, + { + "name": "medium", + "run_type": "iteration", "iterations": 1000, "real_time": 8, "cpu_time": 80, "time_unit": "ns" + }, + { + "name": "medium", + "run_type": "iteration", + "iterations": 1000, + "real_time": 9, + "cpu_time": 82, + "time_unit": "ns" } ] } diff --git a/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run1.json b/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run1.json index e5cf50c7445..acc5ba17aed 100644 --- a/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run1.json +++ b/lib/libcxx/utils/google-benchmark/tools/gbench/Inputs/test3_run1.json @@ -16,6 +16,7 @@ }, { "name": "BM_Two", + "run_type": "aggregate", "iterations": 1000, "real_time": 10, "cpu_time": 89, @@ -25,14 +26,39 @@ "name": "BM_Two", "iterations": 1000, "real_time": 7, - "cpu_time": 70, + "cpu_time": 72, "time_unit": "ns" }, { "name": "short", + "run_type": "aggregate", "iterations": 1000, - "real_time": 8, - "cpu_time": 80, + "real_time": 7, + "cpu_time": 75, + "time_unit": "ns" + }, + { + "name": "short", + "run_type": "aggregate", + "iterations": 762, + "real_time": 4.54, + "cpu_time": 66.6, + "time_unit": "ns" + }, + { + "name": "short", + "run_type": "iteration", + "iterations": 1000, + "real_time": 800, + "cpu_time": 1, + "time_unit": "ns" + }, + { + "name": "medium", + "run_type": "iteration", + "iterations": 1200, + "real_time": 5, + "cpu_time": 53, "time_unit": "ns" } ] diff --git a/lib/libcxx/utils/google-benchmark/tools/gbench/report.py b/lib/libcxx/utils/google-benchmark/tools/gbench/report.py index 4d03a547677..5085b931947 100644 --- a/lib/libcxx/utils/google-benchmark/tools/gbench/report.py +++ b/lib/libcxx/utils/google-benchmark/tools/gbench/report.py @@ -1,3 +1,4 @@ +import unittest """report.py - Utilities for reporting statistics about benchmark results """ import os @@ -36,6 +37,7 @@ BC_UNDERLINE = BenchmarkColor('UNDERLINE', '\033[4m') UTEST_MIN_REPETITIONS = 2 UTEST_OPTIMAL_REPETITIONS = 9 # Lowest reasonable number, More is better. +UTEST_COL_NAME = "_pvalue" def color_format(use_color, fmt_str, *args, **kwargs): @@ -93,9 +95,103 @@ def filter_benchmark(json_orig, family, replacement=""): return filtered +def get_unique_benchmark_names(json): + """ + While *keeping* the order, give all the unique 'names' used for benchmarks. + """ + seen = set() + uniqued = [x['name'] for x in json['benchmarks'] + if x['name'] not in seen and + (seen.add(x['name']) or True)] + return uniqued + + +def intersect(list1, list2): + """ + Given two lists, get a new list consisting of the elements only contained + in *both of the input lists*, while preserving the ordering. + """ + return [x for x in list1 if x in list2] + + +def partition_benchmarks(json1, json2): + """ + While preserving the ordering, find benchmarks with the same names in + both of the inputs, and group them. + (i.e. partition/filter into groups with common name) + """ + json1_unique_names = get_unique_benchmark_names(json1) + json2_unique_names = get_unique_benchmark_names(json2) + names = intersect(json1_unique_names, json2_unique_names) + partitions = [] + for name in names: + # Pick the time unit from the first entry of the lhs benchmark. + time_unit = (x['time_unit'] + for x in json1['benchmarks'] if x['name'] == name).next() + # Filter by name and time unit. + lhs = [x for x in json1['benchmarks'] if x['name'] == name and + x['time_unit'] == time_unit] + rhs = [x for x in json2['benchmarks'] if x['name'] == name and + x['time_unit'] == time_unit] + partitions.append([lhs, rhs]) + return partitions + + +def extract_field(partition, field_name): + # The count of elements may be different. We want *all* of them. + lhs = [x[field_name] for x in partition[0]] + rhs = [x[field_name] for x in partition[1]] + return [lhs, rhs] + + +def print_utest(partition, utest_alpha, first_col_width, use_color=True): + timings_time = extract_field(partition, 'real_time') + timings_cpu = extract_field(partition, 'cpu_time') + + min_rep_cnt = min(len(timings_time[0]), + len(timings_time[1]), + len(timings_cpu[0]), + len(timings_cpu[1])) + + # Does *everything* has at least UTEST_MIN_REPETITIONS repetitions? + if min_rep_cnt < UTEST_MIN_REPETITIONS: + return [] + + def get_utest_color(pval): + return BC_FAIL if pval >= utest_alpha else BC_OKGREEN + + time_pvalue = mannwhitneyu( + timings_time[0], timings_time[1], alternative='two-sided').pvalue + cpu_pvalue = mannwhitneyu( + timings_cpu[0], timings_cpu[1], alternative='two-sided').pvalue + + dsc = "U Test, Repetitions: {} vs {}".format( + len(timings_cpu[0]), len(timings_cpu[1])) + dsc_color = BC_OKGREEN + + if min_rep_cnt < UTEST_OPTIMAL_REPETITIONS: + dsc_color = BC_WARNING + dsc += ". WARNING: Results unreliable! {}+ repetitions recommended.".format( + UTEST_OPTIMAL_REPETITIONS) + + special_str = "{}{:<{}s}{endc}{}{:16.4f}{endc}{}{:16.4f}{endc}{} {}" + + last_name = partition[0][0]['name'] + return [color_format(use_color, + special_str, + BC_HEADER, + "{}{}".format(last_name, UTEST_COL_NAME), + first_col_width, + get_utest_color(time_pvalue), time_pvalue, + get_utest_color(cpu_pvalue), cpu_pvalue, + dsc_color, dsc, + endc=BC_ENDC)] + + def generate_difference_report( json1, json2, + display_aggregates_only=False, utest=False, utest_alpha=0.05, use_color=True): @@ -112,108 +208,95 @@ def generate_difference_report( return b return None - utest_col_name = "_pvalue" first_col_width = max( first_col_width, len('Benchmark')) - first_col_width += len(utest_col_name) + first_col_width += len(UTEST_COL_NAME) first_line = "{:<{}s}Time CPU Time Old Time New CPU Old CPU New".format( 'Benchmark', 12 + first_col_width) output_strs = [first_line, '-' * len(first_line)] - last_name = None - timings_time = [[], []] - timings_cpu = [[], []] - - gen = (bn for bn in json1['benchmarks'] - if 'real_time' in bn and 'cpu_time' in bn) - for bn in gen: - fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}" - special_str = "{}{:<{}s}{endc}{}{:16.4f}{endc}{}{:16.4f}{endc}{} {}" - - if last_name is None: - last_name = bn['name'] - if last_name != bn['name']: - if ((len(timings_time[0]) >= UTEST_MIN_REPETITIONS) and - (len(timings_time[1]) >= UTEST_MIN_REPETITIONS) and - (len(timings_cpu[0]) >= UTEST_MIN_REPETITIONS) and - (len(timings_cpu[1]) >= UTEST_MIN_REPETITIONS)): - if utest: - def get_utest_color(pval): - if pval >= utest_alpha: - return BC_FAIL - else: - return BC_OKGREEN - time_pvalue = mannwhitneyu( - timings_time[0], timings_time[1], alternative='two-sided').pvalue - cpu_pvalue = mannwhitneyu( - timings_cpu[0], timings_cpu[1], alternative='two-sided').pvalue - dsc = "U Test, Repetitions: {}".format(len(timings_cpu[0])) - dsc_color = BC_OKGREEN - if len(timings_cpu[0]) < UTEST_OPTIMAL_REPETITIONS: - dsc_color = BC_WARNING - dsc += ". WARNING: Results unreliable! {}+ repetitions recommended.".format( - UTEST_OPTIMAL_REPETITIONS) - output_strs += [color_format(use_color, - special_str, - BC_HEADER, - "{}{}".format(last_name, - utest_col_name), - first_col_width, - get_utest_color(time_pvalue), - time_pvalue, - get_utest_color(cpu_pvalue), - cpu_pvalue, - dsc_color, - dsc, - endc=BC_ENDC)] - last_name = bn['name'] - timings_time = [[], []] - timings_cpu = [[], []] - - other_bench = find_test(bn['name']) - if not other_bench: - continue - - if bn['time_unit'] != other_bench['time_unit']: - continue + partitions = partition_benchmarks(json1, json2) + for partition in partitions: + # Careful, we may have different repetition count. + for i in range(min(len(partition[0]), len(partition[1]))): + bn = partition[0][i] + other_bench = partition[1][i] + + # *If* we were asked to only display aggregates, + # and if it is non-aggregate, then skip it. + if display_aggregates_only and 'run_type' in bn and 'run_type' in other_bench: + assert bn['run_type'] == other_bench['run_type'] + if bn['run_type'] != 'aggregate': + continue + + fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}" + + def get_color(res): + if res > 0.05: + return BC_FAIL + elif res > -0.07: + return BC_WHITE + else: + return BC_CYAN + + tres = calculate_change(bn['real_time'], other_bench['real_time']) + cpures = calculate_change(bn['cpu_time'], other_bench['cpu_time']) + output_strs += [color_format(use_color, + fmt_str, + BC_HEADER, + bn['name'], + first_col_width, + get_color(tres), + tres, + get_color(cpures), + cpures, + bn['real_time'], + other_bench['real_time'], + bn['cpu_time'], + other_bench['cpu_time'], + endc=BC_ENDC)] + + # After processing the whole partition, if requested, do the U test. + if utest: + output_strs += print_utest(partition, + utest_alpha=utest_alpha, + first_col_width=first_col_width, + use_color=use_color) - def get_color(res): - if res > 0.05: - return BC_FAIL - elif res > -0.07: - return BC_WHITE - else: - return BC_CYAN - - timings_time[0].append(bn['real_time']) - timings_time[1].append(other_bench['real_time']) - timings_cpu[0].append(bn['cpu_time']) - timings_cpu[1].append(other_bench['cpu_time']) - - tres = calculate_change(timings_time[0][-1], timings_time[1][-1]) - cpures = calculate_change(timings_cpu[0][-1], timings_cpu[1][-1]) - output_strs += [color_format(use_color, - fmt_str, - BC_HEADER, - bn['name'], - first_col_width, - get_color(tres), - tres, - get_color(cpures), - cpures, - timings_time[0][-1], - timings_time[1][-1], - timings_cpu[0][-1], - timings_cpu[1][-1], - endc=BC_ENDC)] return output_strs + ############################################################################### # Unit tests -import unittest +class TestGetUniqueBenchmarkNames(unittest.TestCase): + def load_results(self): + import json + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') + testOutput = os.path.join(testInputs, 'test3_run0.json') + with open(testOutput, 'r') as f: + json = json.load(f) + return json + + def test_basic(self): + expect_lines = [ + 'BM_One', + 'BM_Two', + 'short', # These two are not sorted + 'medium', # These two are not sorted + ] + json = self.load_results() + output_lines = get_unique_benchmark_names(json) + print("\n") + print("\n".join(output_lines)) + self.assertEqual(len(output_lines), len(expect_lines)) + for i in range(0, len(output_lines)): + self.assertEqual(expect_lines[i], output_lines[i]) class TestReportDifference(unittest.TestCase): @@ -259,7 +342,7 @@ class TestReportDifference(unittest.TestCase): for i in range(0, len(output_lines)): parts = [x for x in output_lines[i].split(' ') if x] self.assertEqual(len(parts), 7) - self.assertEqual(parts, expect_lines[i]) + self.assertEqual(expect_lines[i], parts) class TestReportDifferenceBetweenFamilies(unittest.TestCase): @@ -293,7 +376,7 @@ class TestReportDifferenceBetweenFamilies(unittest.TestCase): for i in range(0, len(output_lines)): parts = [x for x in output_lines[i].split(' ') if x] self.assertEqual(len(parts), 7) - self.assertEqual(parts, expect_lines[i]) + self.assertEqual(expect_lines[i], parts) class TestReportDifferenceWithUTest(unittest.TestCase): @@ -316,13 +399,15 @@ class TestReportDifferenceWithUTest(unittest.TestCase): expect_lines = [ ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'], - ['BM_Two', '+0.2500', '+0.1125', '8', '10', '80', '89'], + ['BM_Two', '-0.1250', '-0.1628', '8', '7', '86', '72'], ['BM_Two_pvalue', - '0.2207', - '0.6831', + '0.6985', + '0.6985', 'U', 'Test,', 'Repetitions:', + '2', + 'vs', '2.', 'WARNING:', 'Results', @@ -330,18 +415,103 @@ class TestReportDifferenceWithUTest(unittest.TestCase): '9+', 'repetitions', 'recommended.'], - ['short', '+0.0000', '+0.0000', '8', '8', '80', '80'], + ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'], + ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'], + ['short_pvalue', + '0.7671', + '0.1489', + 'U', + 'Test,', + 'Repetitions:', + '2', + 'vs', + '3.', + 'WARNING:', + 'Results', + 'unreliable!', + '9+', + 'repetitions', + 'recommended.'], + ['medium', '-0.3750', '-0.3375', '8', '5', '80', '53'], + ] + json1, json2 = self.load_results() + output_lines_with_header = generate_difference_report( + json1, json2, utest=True, utest_alpha=0.05, use_color=False) + output_lines = output_lines_with_header[2:] + print("\n") + print("\n".join(output_lines_with_header)) + self.assertEqual(len(output_lines), len(expect_lines)) + for i in range(0, len(output_lines)): + parts = [x for x in output_lines[i].split(' ') if x] + self.assertEqual(expect_lines[i], parts) + + +class TestReportDifferenceWithUTestWhileDisplayingAggregatesOnly( + unittest.TestCase): + def load_results(self): + import json + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') + testOutput1 = os.path.join(testInputs, 'test3_run0.json') + testOutput2 = os.path.join(testInputs, 'test3_run1.json') + with open(testOutput1, 'r') as f: + json1 = json.load(f) + with open(testOutput2, 'r') as f: + json2 = json.load(f) + return json1, json2 + + def test_utest(self): + expect_lines = [] + expect_lines = [ + ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], + ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'], + ['BM_Two', '-0.1250', '-0.1628', '8', '7', '86', '72'], + ['BM_Two_pvalue', + '0.6985', + '0.6985', + 'U', + 'Test,', + 'Repetitions:', + '2', + 'vs', + '2.', + 'WARNING:', + 'Results', + 'unreliable!', + '9+', + 'repetitions', + 'recommended.'], + ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'], + ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'], + ['short_pvalue', + '0.7671', + '0.1489', + 'U', + 'Test,', + 'Repetitions:', + '2', + 'vs', + '3.', + 'WARNING:', + 'Results', + 'unreliable!', + '9+', + 'repetitions', + 'recommended.'], ] json1, json2 = self.load_results() output_lines_with_header = generate_difference_report( - json1, json2, True, 0.05, use_color=False) + json1, json2, display_aggregates_only=True, + utest=True, utest_alpha=0.05, use_color=False) output_lines = output_lines_with_header[2:] print("\n") print("\n".join(output_lines_with_header)) self.assertEqual(len(output_lines), len(expect_lines)) for i in range(0, len(output_lines)): parts = [x for x in output_lines[i].split(' ') if x] - self.assertEqual(parts, expect_lines[i]) + self.assertEqual(expect_lines[i], parts) if __name__ == '__main__': diff --git a/lib/libcxx/utils/google-benchmark/tools/gbench/util.py b/lib/libcxx/utils/google-benchmark/tools/gbench/util.py index 07c23772754..1f8e8e2c479 100644 --- a/lib/libcxx/utils/google-benchmark/tools/gbench/util.py +++ b/lib/libcxx/utils/google-benchmark/tools/gbench/util.py @@ -7,11 +7,13 @@ import subprocess import sys # Input file type enumeration -IT_Invalid = 0 -IT_JSON = 1 +IT_Invalid = 0 +IT_JSON = 1 IT_Executable = 2 _num_magic_bytes = 2 if sys.platform.startswith('win') else 4 + + def is_executable_file(filename): """ Return 'True' if 'filename' names a valid file which is likely @@ -46,7 +48,7 @@ def is_json_file(filename): with open(filename, 'r') as f: json.load(f) return True - except: + except BaseException: pass return False @@ -84,6 +86,7 @@ def check_input_file(filename): sys.exit(1) return ftype + def find_benchmark_flag(prefix, benchmark_flags): """ Search the specified list of flags for a flag matching `<prefix><arg>` and @@ -97,6 +100,7 @@ def find_benchmark_flag(prefix, benchmark_flags): result = f[len(prefix):] return result + def remove_benchmark_flags(prefix, benchmark_flags): """ Return a new list containing the specified benchmark_flags except those @@ -105,6 +109,7 @@ def remove_benchmark_flags(prefix, benchmark_flags): assert prefix.startswith('--') and prefix.endswith('=') return [f for f in benchmark_flags if not f.startswith(prefix)] + def load_benchmark_results(fname): """ Read benchmark output from a file and return the JSON object. @@ -129,7 +134,7 @@ def run_benchmark(exe_name, benchmark_flags): thandle, output_name = tempfile.mkstemp() os.close(thandle) benchmark_flags = list(benchmark_flags) + \ - ['--benchmark_out=%s' % output_name] + ['--benchmark_out=%s' % output_name] cmd = [exe_name] + benchmark_flags print("RUNNING: %s" % ' '.join(cmd)) @@ -156,4 +161,4 @@ def run_or_load_benchmark(filename, benchmark_flags): elif ftype == IT_Executable: return run_benchmark(filename, benchmark_flags) else: - assert False # This branch is unreachable
\ No newline at end of file + assert False # This branch is unreachable diff --git a/lib/libcxx/utils/libcxx/test/format.py b/lib/libcxx/utils/libcxx/test/format.py index 74e3cc0aa30..6a334ac31cf 100644 --- a/lib/libcxx/utils/libcxx/test/format.py +++ b/lib/libcxx/utils/libcxx/test/format.py @@ -188,7 +188,7 @@ class LibcxxTestFormat(object): if rc != 0: report = libcxx.util.makeReport(cmd, out, err, rc) report += "Compilation failed unexpectedly!" - return lit.Test.FAIL, report + return lit.Test.Result(lit.Test.FAIL, report) # Run the test local_cwd = os.path.dirname(source_path) env = None @@ -206,14 +206,14 @@ class LibcxxTestFormat(object): cmd, out, err, rc = self.executor.run(exec_path, [exec_path], local_cwd, data_files, env) + report = "Compiled With: '%s'\n" % ' '.join(compile_cmd) + report += libcxx.util.makeReport(cmd, out, err, rc) if rc == 0: res = lit.Test.PASS if retry_count == 0 else lit.Test.FLAKYPASS - return res, '' + return lit.Test.Result(res, report) elif rc != 0 and retry_count + 1 == max_retry: - report = libcxx.util.makeReport(cmd, out, err, rc) - report = "Compiled With: %s\n%s" % (compile_cmd, report) report += "Compiled test failed unexpectedly!" - return lit.Test.FAIL, report + return lit.Test.Result(lit.Test.FAIL, report) assert False # Unreachable finally: @@ -250,16 +250,15 @@ class LibcxxTestFormat(object): # # Therefore, we check if the test was expected to fail because of # nodiscard before enabling it - test_str = "ignoring return value of function declared with " \ - + "'nodiscard' attribute" - if test_str in contents: + test_str_list = ['ignoring return value', 'nodiscard', 'NODISCARD'] + if any(test_str in contents for test_str in test_str_list): test_cxx.flags += ['-Werror=unused-result'] cmd, out, err, rc = test_cxx.compile(source_path, out=os.devnull) expected_rc = 0 if use_verify else 1 + report = libcxx.util.makeReport(cmd, out, err, rc) if rc == expected_rc: - return lit.Test.PASS, '' + return lit.Test.Result(lit.Test.PASS, report) else: - report = libcxx.util.makeReport(cmd, out, err, rc) - report_msg = ('Expected compilation to fail!' if not use_verify else - 'Expected compilation using verify to pass!') - return lit.Test.FAIL, report + report_msg + '\n' + report += ('Expected compilation to fail!\n' if not use_verify else + 'Expected compilation using verify to pass!\n') + return lit.Test.Result(lit.Test.FAIL, report) diff --git a/lib/libcxx/utils/libcxx/test/googlebenchmark.py b/lib/libcxx/utils/libcxx/test/googlebenchmark.py new file mode 100644 index 00000000000..6fe731e8c91 --- /dev/null +++ b/lib/libcxx/utils/libcxx/test/googlebenchmark.py @@ -0,0 +1,122 @@ +from __future__ import absolute_import +import os +import subprocess +import sys + +import lit.Test +import lit.TestRunner +import lit.util +from lit.formats.base import TestFormat + +kIsWindows = sys.platform in ['win32', 'cygwin'] + +class GoogleBenchmark(TestFormat): + def __init__(self, test_sub_dirs, test_suffix, benchmark_args=[]): + self.benchmark_args = list(benchmark_args) + self.test_sub_dirs = os.path.normcase(str(test_sub_dirs)).split(';') + + # On Windows, assume tests will also end in '.exe'. + exe_suffix = str(test_suffix) + if kIsWindows: + exe_suffix += '.exe' + + # Also check for .py files for testing purposes. + self.test_suffixes = {exe_suffix, test_suffix + '.py'} + + def getBenchmarkTests(self, path, litConfig, localConfig): + """getBenchmarkTests(path) - [name] + + Return the tests available in gtest executable. + + Args: + path: String path to a gtest executable + litConfig: LitConfig instance + localConfig: TestingConfig instance""" + + # TODO: allow splitting tests according to the "benchmark family" so + # the output for a single family of tests all belongs to the same test + # target. + list_test_cmd = [path, '--benchmark_list_tests'] + try: + output = subprocess.check_output(list_test_cmd, + env=localConfig.environment) + except subprocess.CalledProcessError as exc: + litConfig.warning( + "unable to discover google-benchmarks in %r: %s. Process output: %s" + % (path, sys.exc_info()[1], exc.output)) + raise StopIteration + + nested_tests = [] + for ln in output.splitlines(False): # Don't keep newlines. + ln = lit.util.to_string(ln) + if not ln.strip(): + continue + + index = 0 + while ln[index*2:index*2+2] == ' ': + index += 1 + while len(nested_tests) > index: + nested_tests.pop() + + ln = ln[index*2:] + if ln.endswith('.'): + nested_tests.append(ln) + elif any([name.startswith('DISABLED_') + for name in nested_tests + [ln]]): + # Gtest will internally skip these tests. No need to launch a + # child process for it. + continue + else: + yield ''.join(nested_tests) + ln + + def getTestsInDirectory(self, testSuite, path_in_suite, + litConfig, localConfig): + source_path = testSuite.getSourcePath(path_in_suite) + for subdir in self.test_sub_dirs: + dir_path = os.path.join(source_path, subdir) + if not os.path.isdir(dir_path): + continue + for fn in lit.util.listdir_files(dir_path, + suffixes=self.test_suffixes): + # Discover the tests in this executable. + execpath = os.path.join(source_path, subdir, fn) + testnames = self.getBenchmarkTests(execpath, litConfig, localConfig) + for testname in testnames: + testPath = path_in_suite + (subdir, fn, testname) + yield lit.Test.Test(testSuite, testPath, localConfig, + file_path=execpath) + + def execute(self, test, litConfig): + testPath,testName = os.path.split(test.getSourcePath()) + while not os.path.exists(testPath): + # Handle GTest parametrized and typed tests, whose name includes + # some '/'s. + testPath, namePrefix = os.path.split(testPath) + testName = namePrefix + '/' + testName + + cmd = [testPath, '--benchmark_filter=%s$' % testName ] + self.benchmark_args + + if litConfig.noExecute: + return lit.Test.PASS, '' + + try: + out, err, exitCode = lit.util.executeCommand( + cmd, env=test.config.environment, + timeout=litConfig.maxIndividualTestTime) + except lit.util.ExecuteCommandTimeoutException: + return (lit.Test.TIMEOUT, + 'Reached timeout of {} seconds'.format( + litConfig.maxIndividualTestTime) + ) + + if exitCode: + return lit.Test.FAIL, out + err + + passing_test_line = testName + if passing_test_line not in out: + msg = ('Unable to find %r in google benchmark output:\n\n%s%s' % + (passing_test_line, out, err)) + return lit.Test.UNRESOLVED, msg + + return lit.Test.PASS, err + out + diff --git a/lib/libcxx/utils/libcxx/test/target_info.py b/lib/libcxx/utils/libcxx/test/target_info.py index de2232ff418..32bbb2e1150 100644 --- a/lib/libcxx/utils/libcxx/test/target_info.py +++ b/lib/libcxx/utils/libcxx/test/target_info.py @@ -15,6 +15,8 @@ import re import subprocess import sys +from libcxx.util import executeCommand + class DefaultTargetInfo(object): def __init__(self, full_config): self.full_config = full_config @@ -127,14 +129,13 @@ class DarwinLocalTI(DefaultTargetInfo): cmd = ['xcrun', '--sdk', name, '--show-sdk-path'] else: cmd = ['xcrun', '--show-sdk-path'] - try: - out = subprocess.check_output(cmd).strip() - res = 0 - except OSError: - res = -1 - if res == 0 and out: - sdk_path = out + out, err, exit_code = executeCommand(cmd) + if exit_code != 0: + self.full_config.lit_config.warning("Could not determine macOS SDK path! stderr was " + err) + if exit_code == 0 and out: + sdk_path = out.strip() self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path) + assert isinstance(sdk_path, str) flags += ["-isysroot", sdk_path] def add_cxx_link_flags(self, flags): @@ -143,12 +144,12 @@ class DarwinLocalTI(DefaultTargetInfo): def configure_env(self, env): library_paths = [] # Configure the library path for libc++ - if self.full_config.use_system_cxx_lib: + if self.full_config.cxx_runtime_root: + library_paths += [self.full_config.cxx_runtime_root] + elif self.full_config.use_system_cxx_lib: if (os.path.isdir(str(self.full_config.use_system_cxx_lib))): library_paths += [self.full_config.use_system_cxx_lib] - pass - elif self.full_config.cxx_runtime_root: - library_paths += [self.full_config.cxx_runtime_root] + # Configure the abi library path if self.full_config.abi_library_root: library_paths += [self.full_config.abi_library_root] @@ -181,6 +182,18 @@ class FreeBSDLocalTI(DefaultTargetInfo): flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] +class NetBSDLocalTI(DefaultTargetInfo): + def __init__(self, full_config): + super(NetBSDLocalTI, self).__init__(full_config) + + def add_locale_features(self, features): + add_common_locales(features, self.full_config.lit_config) + + def add_cxx_link_flags(self, flags): + flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lc++abi', + '-lunwind'] + + class LinuxLocalTI(DefaultTargetInfo): def __init__(self, full_config): super(LinuxLocalTI, self).__init__(full_config) @@ -279,6 +292,7 @@ def make_target_info(full_config): target_system = platform.system() if target_system == 'Darwin': return DarwinLocalTI(full_config) if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config) + if target_system == 'NetBSD': return NetBSDLocalTI(full_config) if target_system == 'Linux': return LinuxLocalTI(full_config) if target_system == 'Windows': return WindowsLocalTI(full_config) return DefaultTargetInfo(full_config) |